我正在尝试在我的 Django 项目上实现图像上传功能,但没有创建文件。我的代码有什么问题?

I am trying to implement an image upload feature on my Django project but no file is being created. What is wrong with my code?

我有一个个人资料页面,其中包含默认个人资料图片和旁边的 'Change' 按钮,单击该按钮将触发模式。在此模式中,图像上传按钮(用于选择图像)将与提交按钮一起出现。我创建了一个单独的视图来处理图像上传。我不知道为什么上传后没有创建文件。 Django 没有给出错误消息。我怀疑它与 settings.py 配置或我的模态字段的操作部分有关。

views.py


from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect

from .forms import KeyForm, Weekly_Item_Form, Daily_Item_Form, ProfileForm
from .models import Key, Weekly_Item, Daily_Item, Profile


def profile_view(request):
    profiles = Profile.objects.all()
    mainprofile = profiles.last()
    if profiles:
        form = ProfileForm()
        context = {
            'page_title':"Profile", 
            'mainprofile':mainprofile,
            'form': form
        }
    else:
        context = {'page_title':"Profile"}
    return render(request, "bujo/profile.html", context)


def update_image(request, pk):
    mainprofile = Profile.objects.get(id=pk)
    form = ProfileForm(instance=mainprofile)
    
    if request.method == 'POST':
        form = ProfileForm(request.POST, request.FILES, instance=mainprofile)
        if form.is_valid():
            form.save()
            return redirect('profile')
    return redirect('profile')

urls.py


urlpatterns = [
    path('admin/', admin.site.urls),
    path('profile/', app_views.profile_view, name='profile'),
    path('update_image/<str:pk>', app_views.update_image, name='update_image'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

settings.py

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

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

profile.html

<form method='POST' enctype="multipart/form-data" action="{% url 'update_image' mainprofile.pk %}"> {% csrf_token %}
                 {{ form.image }}
             <input type='submit' class="btn btn-primary"" value='Change profile picture' />
             </form>

forms.py

from django import forms
from .models import Profile

class ProfileForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['name', 'image', 'nickname', 'bio']

models.py

class Profile(models.Model):
    name = models.CharField(max_length=50, blank=False)
    image = models.ImageField(null=True, blank=True, upload_to="images/")
    nickname = models.CharField(max_length=20, null=False, blank=True)
    bio = models.CharField(max_length=100, null=False, blank=True)

您的表单也有图像以外的字段。您不在模板中呈现它们,但表单 class 需要它们,因此当提交表单时,它被认为是无效的。如果您只想更新图像,请创建另一个只有图像字段的表单 class。

在您的 forms.py 中添加另一个表格 class:

from django import forms
from .models import Profile

class ProfileImageForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ['image']

在您看来:

from django.shortcuts import render, redirect
from django.http import HttpResponse, HttpResponseRedirect

from .forms import KeyForm, Weekly_Item_Form, Daily_Item_Form, ProfileForm, ProfileImageForm
from .models import Key, Weekly_Item, Daily_Item, Profile


def profile_view(request):
    profiles = Profile.objects.all()
    mainprofile = profiles.last() # This line feels weird! You always make the form for the last profile only.
    if profiles:
        form = ProfileImageForm()
        context = {
            'page_title':"Profile", 
            'mainprofile':mainprofile,
            'form': form
        }
    else:
        context = {'page_title':"Profile"}
    return render(request, "bujo/profile.html", context)


def update_image(request, pk):
    mainprofile = Profile.objects.get(id=pk)
    form = ProfileImageForm(instance=mainprofile)
    
    if request.method == 'POST':
        form = ProfileImageForm(request.POST, request.FILES, instance=mainprofile)
        if form.is_valid():
            form.save()
            return redirect('profile')
    return redirect('profile')