Django-更新对象时出现“此字段必填”错误

时间:2020-10-07 21:55:35

标签: django file-upload django-forms

当我尝试使用表单编辑包含图像上传的对象时,我得到“此字段为必填”。类似的形式可以很好地创建对象,但是当我检索对象并尝试修改其他字段时,它在图像上会失败。

#-------models.py:
class Star(models.Model):
    firstname = models.CharField(max_length=32)
    lastname = models.CharField(max_length=32, blank=True)
    portrait = models.ImageField(upload_to='images/')

#------views.py:
class StarForm(forms.ModelForm):
    class Meta:
        model = Star
        fields = ["firstname", "lastname", "portrait"]

def staredit(request, star_id):
    instance = Star.objects.get(pk=star_id)
    form = StarForm(request.POST or None, instance=instance)
    context = {
        "form": form,
    }
    return render(request, "stars/edit.html", context)


def starchange(request):
    form = StarForm(request.POST, request.FILES)
    if form.is_valid():
        newstar.save()
        context = {
            "message": "The form was posted",
        }
        return render(request, "stars/edit.html", context)
    else:
        context = {
            "message": form.errors,
        }
        return render(request, "stars/edit.html", context)

#-----edit.html
<form action="/starchange" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Submit">
</form>
{{message}}

错误消息:

肖像 此字段为必填。

1 个答案:

答案 0 :(得分:0)

您不是要 更新实例,因为您从未将实例传递给应该更新实例的视图。进行POST要求时,浏览器仅提交表单元素的内容。没有有关呈现先前表单的数据,该数据会丢失。

您应指定instance进行更新,因此:

from django.shortcuts import get_object_or_404

def starchange(request, pk):
    obj = get_object_or_404(Star, pk=pk)
    form = StarForm(request.POST, request.FILES, instance=obj)
    if form.is_valid():
        form.save()
        context = {
            "message": "The form was posted",
        }
        return render(request, "stars/edit.html", context)
    else:
        context = {
            "message": form.errors,
        }
        return render(request, "stars/edit.html", context)

在网址中,因此您应指定要更新的对象的主键:

urlpatterns = [
    # …,
    path('starchange/<int:pk>/', views.starchange, name='starchange')
]

在模板中,您应该向具有给定实例的视图发出POST请求:

<form action="{% url 'starchange' pk=form.instance.pk %}" method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Submit">
</form>

这是为什么相同视图经常用于GET和POST请求的主要原因之一,因为它消除了很多重复的逻辑。此外,它也更干净:您可以使用GET检索页面,并使用POST提交页面。


注意:如果POST请求成功,则应进行redirect [Django-doc] 实现Post/Redirect/Get pattern [wiki]。 这样可以避免在用户刷新页面时发出相同的POST请求。 浏览器。


注意:通常最好使用get_object_or_404(…) [Django-doc], 然后直接使用.get(…) [Django-doc]。如果对象不存在, 例如,由于用户自己更改了网址,因此get_object_or_404(…)将导致返回 HTTP 404 Not Found 响应,而使用 .get(…)将导致 HTTP 500服务器错误