首页 > 解决方案 > 为什么图片不能用 django2 表单上传?

问题描述

我正在尝试使用 ModelForm 类制作一个表格,供一家小公司招聘的人员使用。所以我需要他们的身份证(正面和背面)和他们的生活卡的照片。问题是当我发送表格时,从我的计算机中选择照片后,它没有在数据库中注册(甚至没有路径),并且它们没有复制到所需的媒体文件夹。不利的是,如果我从管理员那里进行操作,它可以工作,我什至可以在浏览器中打开图像。但是,它们仍然没有上传到媒体文件夹。

模型.py:


from django.db import models
from django.contrib.auth.models import User


class UserExtention (models.Model):
    user = models.OneToOneField(User, on_delete = models.CASCADE, null=True, verbose_name='utilisateur')
    phone_number = models.CharField (max_length = 10, null = True, blank=True, verbose_name='numéro de téléphone')
    postal_code = models.IntegerField (null = True, blank=True, verbose_name='code postal')
    town = models.CharField (max_length=50, null=True, blank=True, verbose_name='ville')
    address = models.CharField (max_length=500, null=True, blank=True, verbose_name='adresse')
    id_card_recto = models.ImageField (upload_to = 'pictures/id_card_recto', null=True, blank=True, verbose_name="photo du recto de la carte d'identité") 
    id_card_verso = models.ImageField (upload_to = 'pictures/id_card_verso', null=True, blank=True, verbose_name="photo du verso de la carte d'identité")
    vital_card = models.ImageField (upload_to = 'pictures/vital_card', null=True, blank=True, verbose_name="photo de la carte vitale")
    hours_number = models.IntegerField (null=True, blank=True, verbose_name="nombre d'heure effectuée par le salarié")


    def __str__(self):
        return "Profil de {}".format(self.user.username)

表格.py:


from django import forms
from .models import UserExtention
from django.contrib.auth.models import User

class UserForm(forms.ModelForm):
    class Meta:
        model = User
        fields = (
            'password',
            'username',
            'first_name',
            'last_name',
            'email',
            )

class UserExtentionForm(forms.ModelForm):
    class Meta:
        model = UserExtention
        exclude = ('user', 'hours_number')


视图.py:


from django.shortcuts import render
from .forms import UserForm, UserExtentionForm

def registration (request):
    form = UserForm(request.POST or None, request.FILES)
    form2 = UserExtentionForm(request.POST or None)
    envoi = False
    if form.is_valid() and form2.is_valid():
        user = form.save()
        user_extention = form2.save(commit = False)
        user_extention.user = user
        user_extention.save()
        envoi = True

    return render (request, 'registration/registration.html', locals())

模板:


<h1>Ceci est la page principale de l'application nommée "Registration"</h1>
{% if not envoi %}
<form action="{% url "registration" %}" enctype="multipart/form-data" method="post">
    {% csrf_token %}
    {{ form.as_p}}
    {{ form2.as_p}}
    <input type="submit" value="submit">    
</form>
{% else %}
<p>Votre inscription a bien été prise en compte, vous pouvez à présent vous connecter dans l'onglet <a href="#">connexion</a></p>
{% endif %}

STATIC_URL = '/静态/'

STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static"), )

MEDIA_ROOT = '/媒体/'

MEDIA_URL = '/媒体/'

感谢您的回答!

标签: djangopython-3.xdjango-staticfiles

解决方案


您拥有媒体表单字段的表单是UserExtentionForm,但在您的代码中,您request.FILES只传递给UserForm没有此类媒体字段的 。

def registration (request):
    if request.method == 'POST':
        form = UserForm(request.POST, request.FILES)
        form2 = UserExtentionForm(request.POST, request.FILES)
        if form.is_valid() and form2.is_valid():
            user = form.save()
            user_extention = form2.save(commit = False)
            user_extention.user = user
            user_extention.save()
            return redirect('some-view-name')
    else:
        form = UserForm()
        form2 = UserExtentionForm()
    return render (
        request,
        'registration/registration.html',
        {'form': form, 'form2': form2}
    )

然而,您的观点包含一些严重的反模式,现在(部分)被提议的解决方案所缓解:

  1. 你不应该使用request.POST or None因为一个有效的 POST 请求可以是空的,但它仍然是一个 POST 请求;
  2. 如果 POST 请求成功,您应该进行重定向,以实现Post/Redirect/Get模式 [wiki];和
  3. 请不要使用locals()因为它会将所有变量传递给模板,即使是未定义的变量。此外,由于不清楚传递给模板的内容,稍后您可能会想从视图中删除一些变量以进行优化,并且 IDE 不会发出警告/错误,这些变量在模板中仍然是必需的。

如果要添加提交成功的消息,我建议你使用Django 的消息传递框架[Django-doc],而不是通过上下文传递变量。该框架旨在发布消息,无论模板本身如何,并防止多次显示相同的消息。


推荐阅读