Django 1.7 request.FILES'None'未验证(is_valid())

时间:2015-02-26 12:31:41

标签: python django file validation django-1.7

所以我扩展了User模型以添加一些字段,并且在图像(头像)POST部分遇到麻烦。首先是一个显示用户信息的配置文件页面,以及编辑后者的链接。 进入“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)传递验证?

这是我的代码。

models.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)

forms.py

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

views.py

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>

1 个答案:

答案 0 :(得分:1)

required没有ImageField个参数(Django和sorl.thumbnail都没有)。在您的模型定义中,而不是

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

avatar = ImageField('Avatar', upload_to='usrprofile/', blank=True)