我的Django管理员挂接了以下表单:
# forms.py
class ProfileForm(ModelForm):
class Meta:
model = UserProfile
fields = ('name', 'profile_pic')
# admin.py
class ProfileAdmin(ModelAdmin):
form = ProfileForm
admin.site.register(UserProfile, ProfileAdmin)
# models.py
class UserProfile(models.Model):
user = models.OneToOneField(CustomUser, null=True, on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
profile_pic = models.ImageField(upload_to='profile_image', null=True, blank=True)
def __str__(self):
return str(self.user)
现在,如果我用Django Admin上传profile_pic
,一切都很好。但是,如果我通过模板提交图像,它就不起作用。
这是我的模板:
{% extends '_base.html' %}
{% block content %}
<form action="." enctype="multipart/form-data" id="userprofile_form" method="post">
<h1> Update your profile </h1>
{% csrf_token %}
<div>
{{ form }}
<button class="border-2">Update Profile</button>
</form>
{% endblock %}
相应的视图是:
@login_required
def get_profile(request):
profile = request.user.userprofile
form = ProfileForm(instance=profile)
if request.method == 'POST':
form = ProfileForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return render(request, 'profile-edit.html', {'form':form})
在视图(if form.is_valid()
内部(中,form.cleaned_data
的值None
对应于profile_pic
。request.FILES
是<MultiValueDict: {'profile_pic': [<InMemoryUploadedFile: dave_pic.png (image/png)>]}>
我的上传逻辑出了什么问题。正如我所说的,Django Admin同样适用。CCD_ 8和CCD_。
在调用表单时,我一直在与instance
争论不休;涵盖了Django的表单API的粗糙细节;也没有提到过一次(可能是在其他地方提到过,但我找不到(。
更新后的视图应为:
@login_required
def get_profile(request):
profile = request.user.userprofile
form = ProfileForm(instance=profile)
if request.method == 'POST':
form = ProfileForm(request.POST, request.FILES, instance=profile) # <---
if form.is_valid():
form.save()
return render(request, 'profile-edit.html', {'form':form})
模型表单初始化模型窗体可以使用两个初始化参数:initial
和instance
。initial
自变量的工作原理与标准的初始形式自变量一样……——为未绑定表单提供初始值。instance
参数用于使用模型实例初始化模型表单,而模型实例又用于初始化未绑定表单的值。(来源:Django的新书(
为什么Django Admin有效,但OP的方法无效实际上,它总是有效的,只是当使用form = ProfileForm(request.POST, request.FILES)
时,Django会在遇到form.save()
时创建新的UserProfile
对象。我通过检查数据库中的UserProfile
对象来确认这一点。然而,这些都没有通过UserProfile.user
一对一字段链接到当前用户,因此这些更改永远不会影响当前用户。当使用form = ProfileForm(request.POST, request.FILES, instance=profile)
时,user
字段将填充已登录的用户,一切正常。当OP更新配置文件时,没有创建新的UserProfile
对象,一切正常。