Python Django 1.7 request.FILES';无';未验证(是否有效()

Python Django 1.7 request.FILES';无';未验证(是否有效(),python,django,file,validation,django-1.7,Python,Django,File,Validation,Django 1.7,因此,我扩展了用户模型,添加了一些字段,并且在图像(化身)帖子部分遇到了问题。首先是一个显示用户信息的配置文件页面,以及编辑用户信息的链接。 进入“editprofile”页面后,将加载表单并使用现有数据预填充表单。上传化身文件后,一切正常。但是当没有上传头像时(无论userprofile是否已经有头像),is_valid()方法会失败,如下所示: Request Method: POST Django Version: 1.7.4 Exception Type: Typ

因此,我扩展了用户模型,添加了一些字段,并且在图像(化身)帖子部分遇到了问题。首先是一个显示用户信息的配置文件页面,以及编辑用户信息的链接。 进入“editprofile”页面后,将加载表单并使用现有数据预填充表单。上传化身文件后,一切正常。但是当没有上传头像时(无论userprofile是否已经有头像),is_valid()方法会失败,如下所示:

Request Method:     POST
Django Version:     1.7.4
Exception Type:     TypeError
Exception Value:     invalid file: None
Exception location:  /usr/local/lib/python3.4/dist-packages/django/core/files/images.py in get_image_dimensions, line 46
我的问题是:如何在request.FILES中使用空字段(值None)通过验证

这是我的密码

型号.py

from django.db import models
from django.contrib.auth.models import User
from famsite import settings
from sorl.thumbnail import ImageField

class UserProfile(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    birth_date = models.DateField('Date of birth', null=True)
    phone1 = models.CharField('Primary phone', null=True, blank=True, max_length=15)
    phone2 = models.CharField('Secondary phone', null=True, blank=True, max_length=15)
    address = models.CharField('Address', null=True, blank=True, max_length=256)
    avatar = ImageField('Avatar', upload_to='usrprofile/', blank=True)
from django import forms
from django.core.files.images import get_image_dimensions
from django.utils.translation import ugettext as u_
from django.forms.extras.widgets import SelectDateWidget
import datetime

from usrprofile.models import UserProfile

class UserProfileForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        exclude = ['user']
        fields = ['birth_date', 'phone1', 'phone2', 'email', 'address', 'avatar']

    birth_date = forms.DateField(widget=SelectDateWidget(years=[y for y in range(1950, datetime.date.today().year)]))
    email = forms.EmailField()


    def clean_avatar(self):
        avatar = self.cleaned_data['avatar']

        try:
            w, h = get_image_dimensions(avatar)

            #validate dimensions
            max_width = max_height = 100
            if w > max_width or h > max_height:
                raise forms.ValidationError(
                    u_('Please use an image that is '
                     '%s x %s pixels or smaller.') % (max_width, max_height))

            #validate content type
            main, sub = avatar.content_type.split('/')
            if not (main == 'image' and sub in ['jpeg', 'pjpeg', 'gif', 'png']):
                raise forms.ValidationError(u_('Please use a JPEG, '
                    'GIF or PNG image.'))

            #validate file size
            if len(avatar) > (20 * 1024):
                raise forms.ValidationError(
                    u_('Avatar file size may not exceed 20k.'))

        except AttributeError:
            """
            Handles case when we are updating the user profile
            and do not supply a new avatar
            """
            pass

        return avatar
from django.shortcuts import get_object_or_404, render, render_to_response
from django.http import HttpResponseRedirect, HttpResponseForbidden, HttpResponse
from django.core.urlresolvers import reverse
from django.views import generic
from django import forms
from django.template import RequestContext
from sorl.thumbnail import get_thumbnail
from usrprofile.models import UserProfile
from usrprofile.forms import *



class IndexView(generic.ListView):
    model = UserProfile
    template_name = 'usrprofile/profile.html'


def edit(request):
    user = request.user
    if request.method == 'POST':
#deletes old file in case of new file upload
        form_aux = UserProfileForm(request.POST, request.FILES)
        if form_aux.is_valid() and 'avatar' in request.FILES:
            user.userprofile.avatar.delete()
#check if form has changed
#if form has changed, check if form is valid
#if form is valid, save data, associate with userprofile, save data to server        
        form = UserProfileForm(request.POST, request.FILES)
        if form.has_changed():
            if form.is_valid():
                profile = form.save(commit=False)
                profile.user = user
                profile.save()
                return render_to_response('usrprofile/profile.html', RequestContext(request))
    else:
#if GET method, populate form with existing data
        profile = user.userprofile
        form = UserProfileForm(instance=profile, initial={'email': user.email})

    return render_to_response('usrprofile/editprofile.html', RequestContext(request, {'form' : form}))
forms.py

from django.db import models
from django.contrib.auth.models import User
from famsite import settings
from sorl.thumbnail import ImageField

class UserProfile(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    birth_date = models.DateField('Date of birth', null=True)
    phone1 = models.CharField('Primary phone', null=True, blank=True, max_length=15)
    phone2 = models.CharField('Secondary phone', null=True, blank=True, max_length=15)
    address = models.CharField('Address', null=True, blank=True, max_length=256)
    avatar = ImageField('Avatar', upload_to='usrprofile/', blank=True)
from django import forms
from django.core.files.images import get_image_dimensions
from django.utils.translation import ugettext as u_
from django.forms.extras.widgets import SelectDateWidget
import datetime

from usrprofile.models import UserProfile

class UserProfileForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        exclude = ['user']
        fields = ['birth_date', 'phone1', 'phone2', 'email', 'address', 'avatar']

    birth_date = forms.DateField(widget=SelectDateWidget(years=[y for y in range(1950, datetime.date.today().year)]))
    email = forms.EmailField()


    def clean_avatar(self):
        avatar = self.cleaned_data['avatar']

        try:
            w, h = get_image_dimensions(avatar)

            #validate dimensions
            max_width = max_height = 100
            if w > max_width or h > max_height:
                raise forms.ValidationError(
                    u_('Please use an image that is '
                     '%s x %s pixels or smaller.') % (max_width, max_height))

            #validate content type
            main, sub = avatar.content_type.split('/')
            if not (main == 'image' and sub in ['jpeg', 'pjpeg', 'gif', 'png']):
                raise forms.ValidationError(u_('Please use a JPEG, '
                    'GIF or PNG image.'))

            #validate file size
            if len(avatar) > (20 * 1024):
                raise forms.ValidationError(
                    u_('Avatar file size may not exceed 20k.'))

        except AttributeError:
            """
            Handles case when we are updating the user profile
            and do not supply a new avatar
            """
            pass

        return avatar
from django.shortcuts import get_object_or_404, render, render_to_response
from django.http import HttpResponseRedirect, HttpResponseForbidden, HttpResponse
from django.core.urlresolvers import reverse
from django.views import generic
from django import forms
from django.template import RequestContext
from sorl.thumbnail import get_thumbnail
from usrprofile.models import UserProfile
from usrprofile.forms import *



class IndexView(generic.ListView):
    model = UserProfile
    template_name = 'usrprofile/profile.html'


def edit(request):
    user = request.user
    if request.method == 'POST':
#deletes old file in case of new file upload
        form_aux = UserProfileForm(request.POST, request.FILES)
        if form_aux.is_valid() and 'avatar' in request.FILES:
            user.userprofile.avatar.delete()
#check if form has changed
#if form has changed, check if form is valid
#if form is valid, save data, associate with userprofile, save data to server        
        form = UserProfileForm(request.POST, request.FILES)
        if form.has_changed():
            if form.is_valid():
                profile = form.save(commit=False)
                profile.user = user
                profile.save()
                return render_to_response('usrprofile/profile.html', RequestContext(request))
    else:
#if GET method, populate form with existing data
        profile = user.userprofile
        form = UserProfileForm(instance=profile, initial={'email': user.email})

    return render_to_response('usrprofile/editprofile.html', RequestContext(request, {'form' : form}))
视图.py

from django.db import models
from django.contrib.auth.models import User
from famsite import settings
from sorl.thumbnail import ImageField

class UserProfile(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    birth_date = models.DateField('Date of birth', null=True)
    phone1 = models.CharField('Primary phone', null=True, blank=True, max_length=15)
    phone2 = models.CharField('Secondary phone', null=True, blank=True, max_length=15)
    address = models.CharField('Address', null=True, blank=True, max_length=256)
    avatar = ImageField('Avatar', upload_to='usrprofile/', blank=True)
from django import forms
from django.core.files.images import get_image_dimensions
from django.utils.translation import ugettext as u_
from django.forms.extras.widgets import SelectDateWidget
import datetime

from usrprofile.models import UserProfile

class UserProfileForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        exclude = ['user']
        fields = ['birth_date', 'phone1', 'phone2', 'email', 'address', 'avatar']

    birth_date = forms.DateField(widget=SelectDateWidget(years=[y for y in range(1950, datetime.date.today().year)]))
    email = forms.EmailField()


    def clean_avatar(self):
        avatar = self.cleaned_data['avatar']

        try:
            w, h = get_image_dimensions(avatar)

            #validate dimensions
            max_width = max_height = 100
            if w > max_width or h > max_height:
                raise forms.ValidationError(
                    u_('Please use an image that is '
                     '%s x %s pixels or smaller.') % (max_width, max_height))

            #validate content type
            main, sub = avatar.content_type.split('/')
            if not (main == 'image' and sub in ['jpeg', 'pjpeg', 'gif', 'png']):
                raise forms.ValidationError(u_('Please use a JPEG, '
                    'GIF or PNG image.'))

            #validate file size
            if len(avatar) > (20 * 1024):
                raise forms.ValidationError(
                    u_('Avatar file size may not exceed 20k.'))

        except AttributeError:
            """
            Handles case when we are updating the user profile
            and do not supply a new avatar
            """
            pass

        return avatar
from django.shortcuts import get_object_or_404, render, render_to_response
from django.http import HttpResponseRedirect, HttpResponseForbidden, HttpResponse
from django.core.urlresolvers import reverse
from django.views import generic
from django import forms
from django.template import RequestContext
from sorl.thumbnail import get_thumbnail
from usrprofile.models import UserProfile
from usrprofile.forms import *



class IndexView(generic.ListView):
    model = UserProfile
    template_name = 'usrprofile/profile.html'


def edit(request):
    user = request.user
    if request.method == 'POST':
#deletes old file in case of new file upload
        form_aux = UserProfileForm(request.POST, request.FILES)
        if form_aux.is_valid() and 'avatar' in request.FILES:
            user.userprofile.avatar.delete()
#check if form has changed
#if form has changed, check if form is valid
#if form is valid, save data, associate with userprofile, save data to server        
        form = UserProfileForm(request.POST, request.FILES)
        if form.has_changed():
            if form.is_valid():
                profile = form.save(commit=False)
                profile.user = user
                profile.save()
                return render_to_response('usrprofile/profile.html', RequestContext(request))
    else:
#if GET method, populate form with existing data
        profile = user.userprofile
        form = UserProfileForm(instance=profile, initial={'email': user.email})

    return render_to_response('usrprofile/editprofile.html', RequestContext(request, {'form' : form}))
editprofile.html

{% extends "base.html" %}
{% load i18n %}

<html>
<head>
    <title>{% block title %}{% trans "Profile edition" %}{% endblock %}</title>
</head>
<body>

<div id="content">
    {% block content %}

        <form id="form" method="POST" action="" enctype="multipart/form-data">
            {% csrf_token %}
            {{ form.as_p }}
            <input type="submit" name="submit" value="Save" />
        </form>

    {% endblock %}

</div>

</body>
</html>
{%extends“base.html”%}
{%load i18n%}
{%block title%}{%trans“概要文件版本”%}{%endblock%}
{%block content%}
{%csrf_令牌%}
{{form.as_p}}
{%endblock%}

没有
必需的
参数
图像字段
(既不是Django的参数,也不是sorl.thumbnail的参数)。在模型定义中,而不是

avatar = ImageField('Avatar', upload_to='usrprofile/', required=False)
试一试


更改后是否迁移了数据库?因为在get_image_dimensions第46行中有“异常位置:/usr/local/lib/python3.4/dist-packages/django/core/files/images.py”;这可能是因为我缺少一些库(但枕头安装正确)?好的,我终于找到了问题,问题出在我表单的这一行。py:“try:w,h=get\u image\u dimensions(avatar)”。我通过将除AttributeError改为TypeError外的其他方式进行了更正。解决了,thnx用于大脑刺激:),在这方面浪费了8个小时:(