【问题标题】:Replacing a file in django在 django 中替换文件
【发布时间】:2020-02-10 14:33:51
【问题描述】:

我有一个标准表单来编辑其中包含文件字段的对象。当我添加一个新的配置文件时,一切正常,但是当我想修改一个字段时,就会出现问题:当我不包含 request.FILES 时,所有字段都会在表单中检索并且可以毫无问题地更新,除了头像(文件字段),但是当我添加 request.FILES 时,不再在输入中检索字段,并且表单无效。我做错了什么?

models.py:

from django.db import models

class Profile(models.Model):
    name = models.CharField(max_length=45)
    email = models.EmailField()
    avatar = models.FileField(upload_to="avatars/")

    def __str__(self):
        return self.name

forms.py:

from django import forms
from .models import Profile

class EditUserForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ["name", "email", "avatar"]

profile.html:

<form method="POST">
        {% csrf_token %}
        <div class="col-md-12">
          <div class="row border m-3 p-5">
            <div class="col-md-6">Name</div>
            <div class="col-md-6">{{ form.name }}</div>
          </div>
          <div class="row border m-3 p-5">
            <div class="col-md-6">Email</div>
            <div class="col-md-6">{{ form.email }}</div>
          </div>
          <div class="row border m-3 p-5">
            <div class="col-md-6">Avatar</div>
            <div class="col-md-6">
              <img src="{{ profile.avatar.url }}" width="100rem" />
              {{ form.avatar }}
            </div>
          </div>
          <div class="row">
            <button type="submit" class="btn btn-success">Save</button>
          </div>
        </div>
      </form>

views.py:

def profile(request, pk):
    profile_instance = Profile.objects.get(id=pk)
    form = EditUserForm(request.POST, request.FILES, instance = profile_instance)
    context = {
        'profile': profile_instance,
        'form': form,
    }
    if request.method == "POST":
        if form.is_valid():
            profile = form.save(commit=False)
            profile.save()
        else:
            print("form not valid")
    else:
        return render(request, "app/profile.html", context)

    return render(request, "app/profile.html", context)

【问题讨论】:

  • 首先,您需要将 (html) 表单的 enctype 设置为“multipart/form-data”(参见docs.djangoproject.com/en/3.0/topics/http/file-uploads),否则request.FILES 将为空。然后,您希望在模板中实际显示表单的验证错误。最后,您应该始终在成功发布后重定向(post-redirect-get 模式),以防止重复提交。
  • 现在可以使用了,谢谢。不,我已经在代码中使用了 enctype,但问题是返回渲染,我将其更改为重定向并且它起作用了。但是,表单中没有填充前 2 个字段(姓名和电子邮件)。
  • 如果是GET 请求,您应该用数据实例化您的表单。这是因为如果您传递数据(通过传递 request.POST 来完成)并且数据为空,则您的表单被绑定并且初始值被设置为数据值。请按照example 中所示的方式完全 进行操作:在GET 请求的情况下实例化EditUserForm(instance=...)。并且仅在表单有效的情况下重定向

标签: django django-forms


【解决方案1】:

特别感谢@bruno desthuilliers 和@dirkgroten。 以下是解决这两个问题的答案:

def profile(request, pk):
    if request.method == 'POST':
        form = EditUserForm(request.POST, request.FILES, instance = Profile.objects.get(id=pk))
        if form.is_valid():
            profile = form.save(commit=False)
            profile.save()
            return redirect('profile', pk)
    else:
        form = EditUserForm(instance = Profile.objects.get(id=pk))
    context = {
        'profile': Profile.objects.get(id=pk),
        'form': form,
    }
    return render(request, "app/profile.html", context)

【讨论】:

    【解决方案2】:

    尝试如下重构代码:(如果我遗漏了什么,请编辑它。在 form.is_valid 之后,应该在上下文中发送相同的表单以显示错误。

    def profile(request, pk):
        profile_instance = Profile.objects.get(id=pk)
        form = EditUserForm(instance = profile_instance)
        if request.method == "POST":
            form = EditUserForm(request.POST, request.FILES, instance = profile_instance)
            if form.is_valid():
                profile = form.save(commit=False)
                profile.save()
                form = EditUserForm(instance = profile_instance)
    
       context = {
            'profile': profile_instance,
            'form': form,
        }
    
        return render(request, "app/profile.html", context)
    

    【讨论】:

    • django docs 包含使正确的基于函数的视图进程成为表单所需的确切代码。这个答案是不正确的,因为它在表单成功提交时不会重定向。您应该始终重定向,即使它指向同一个视图。
    猜你喜欢
    • 1970-01-01
    • 2015-07-31
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 2013-07-26
    • 2021-10-19
    • 2011-10-02
    • 1970-01-01
    相关资源
    最近更新 更多