Изображение из поля ImageField ModelForm не загружается на сервер

Привет, я новичок в Django и одна из вещей, которую я пытаюсь сделать, это создать простое приложение галереи. Почему-то я не могу добавлять изображения через сервер с помощью форм, если я использую Model Form, хотя я могу делать это с помощью обычной формы. Я пробовал многое из того, что написано здесь, а также пробовал кое-что из Youtube, но это все еще не работает.

Вот мой models.py

from django.db import models
from django.urls import reverse
from django.core.validators import validate_image_file_extension
from django.core.files.storage import FileSystemStorage


fs = FileSystemStorage(location='/media')
class FavoriteImages(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(favorite=True)


# Create your models here.
class Photo(models.Model):
    name = models.CharField(max_length=120, null=True)
    photo = models.ImageField(storage=fs, upload_to='media/', validators=[validate_image_file_extension])
    date_uploaded = models.DateTimeField(auto_now=True)
    favorite = models.BooleanField(default=False, blank=False)
    slug = models.SlugField(null=True, blank=True)

    gallery = models.Manager()
    gallery_favorites = FavoriteImages()

    class Meta:
        ordering = ['-date_uploaded']

Мой Views.py

from PIL import Image
def image_new(request, *args, **kwargs):
    Image.init()
    form = PhotoForm(data=request.POST, files=request.FILES)
    if request.method == 'POST':
        form = PhotoForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            redirect('../all')
    context = {
        'form': form
    }
    return render(request, "form.html", context)

Мой forms.py

class PhotoForm(forms.ModelForm):
    name = forms.CharField(label='',widget=forms.TextInput(attrs={'class':'form-control', 'placeholder':'Title'}))
    photo = forms.ImageField(widget=forms.FileInput(attrs={'class':'form-control'}))
    favorite = forms.BooleanField(label='Mark as Favorite',widget=forms.CheckboxInput(attrs={'class':'form-check-input'}))

class Meta:
    model = Photo
    fields = ['name',
              'photo',
              'favorite']

my .html

{% extends "base.html" %}

{% block content %}
    {% if form.is_multipart %}
    <form enctype="multipart/form-data" method="post">
        This form is a multipart.
    {% else %}
    <form method="post">
    {% endif %}
        {% csrf_token %}
    {% if form.media %}
    {{ form.media }}
    {% endif %}
    {{ form.as_p }}

    <input type="submit" class="btn btn-primary" value="Save"/>
    </form>

{% endblock %}

Я разместил это в настройках:

MEDIA_URL = 'media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

Кое-что, что я заметил:

  • Папка media (корень) остается пустой, но Model.photo имеет url. (не null)

Как мне изменить форму, чтобы изображение было размещено?

<
{% extends "base.html" %}

{% block content %}
    
    <form enctype="multipart/form-data" method="post">
       
    {% csrf_token %}
    
    {{ form.as_p }}

    <button type="submit" class="btn btn-primary" value="Save"></button>
    </form>

{% endblock %}

Вашу форму можно упростить и так,

class PhotoForm(forms.ModelForm):
    name = forms.CharField(label='',widget=forms.TextInput(attrs={'class':'form-control', 'placeholder':'Title'}))
    photo = forms.ImageField()
    favorite = forms.BooleanField(label='Mark as Favorite',widget=forms.CheckboxInput(attrs={'class':'form-check-input'}))
'''
You don't need the Meta class when inheriting from forms.ModelForm. I think the widgets aren't necessary, unless you need to style with CSS specifics. 

Your view can also be simplified quite a bit. You don't need PIL Image unless you are modifying your image. 

I would write like this,

def image_new(request, *args, **kwargs):

form = PhotoForm()
if request.method == 'POST':
    form = PhotoForm(request.POST, request.FILES)
    if form.is_valid():
        form.save()
        redirect('../all')
context = {
    'form': form
}
return render(request, "form.html", context)
Django will take care of saving the image to your media folder and assigning it to the ImageField in the model. 
Вернуться на верх