Django. Загрузка изображений. MultiValueDictKeyError. Что делать?

Пытаюсь сделать загрузку изображения в Django.
Создаю класс в модели с полем FileField:
class UserProfile(models.Model):
	user = models.OneToOneField(User, unique=False)
	picture = models.FileField(upload_to='media/images/', blank=True, null=True)

	def __unicode__(self):
		return unicode(self.picture.name)

в forms.py:
class ProfileForm(forms.ModelForm):
	class Meta:
		model = UserProfile
		fields = ['picture']

во view.py:
def signup(request, user_id=None, template_name='signup.html'):
     ...
     if request.method == 'POST':
          ...
          profileForm = ProfileForm(request.POST, request.FILES)
	  if profileForm.is_valid():
		print("profileForm is valid!")
		print(request.POST)
		pic = UserProfile(picture=request.FILES['picture'])
		pic = profileForm.save(commit=False)
		pic.user = request.user
		pic.save()
		message = "File %s is uploaded" % pic
		print(message)
	 else:
		print("NOT VALID!")

и шаблон:
<form action="" method="POST" enctype="multi-part/formdata">
        <table>
            {{ profileForm.as_table }}
        </table>
        {% csrf_token %}
        <input type="submit" name="submit" value="Submit">
    </form>

ругается на: request.FILES['picture']
Traceback:
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/user/1/edit/

Django Version: 1.6.1
Python Version: 3.3.3
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'blog')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware')

Traceback:
File "C:\Python33\lib\site-packages\django\core\handlers\base.py" in get_response
  114.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Django\sandpit\blog\views.py" in signup
  147. 			pic = UserProfile(picture=request.FILES['picture'])
File "C:\Python33\lib\site-packages\django\utils\datastructures.py" in __getitem__
  301.             raise MultiValueDictKeyError(repr(key))

Exception Type: MultiValueDictKeyError at /user/1/edit/
Exception Value: "'picture'"

Хотя в QueryDict показывает имя файла: <QueryDict: ... , 'picture': ['2.jpeg'], ... >
Подскажите, пожалуйста, что не так?
  • Вопрос задан
  • 8958 просмотров
Пригласить эксперта
Ответы на вопрос 5
@marazmiki
Укротитель питонов
Продублирую на всякий случай:

<form action="" method="POST" enctype="multi-part/formdata">


С точностью, да наоборот. Этот тип называется multipart/form-data
Ответ написан
@leclecovich
У Вас в словаре request.FILES нет ключа picture. Попробуйте вот так:
value = request.FILES.get('picture')
if value:
    pic = UserProfile(picture=value)
    # ...
             
else:
    # ...


А еще почитайте документацию, там несколько иной подход.
Ответ написан
@VadimChin
как все сложно у вас
class UserProfile(models.Model):
    user = models.ForeignKey(User)
    picture = models.ImageField(upload_to='images', blank=True, null=True)

    def __unicode__(self):
        return unicode(self.picture.name)

class ViewSuccess(TemplateView):
     template_name = 'view_success.html'

class ViewSignup(CreateView):
     template_name = 'view_signup.html'
     success_url = reverse_lazy('view_success')
     model = UserProfile


urls.py
url(r'^$', 
    url(r'^signup/$', ViewSignup.as_view(), name='view_signup'),
    url(r'^success/$', ViewSuccess.as_view(), name='view_success'), )
Ответ написан
@FireGM
Тоже только что мучился. Не знаю как, но этот говнокод работает.
@login_required
def products_edit(request, product):
    cont = {}
    form = ProductForm()
    if request.POST:
        form = ProductForm(request.POST, request.FILES)
        if form.is_valid():
            try:
                product = Product.objects.get(slug=product, refract=True)
                product.name = form.cleaned_data['name']
                product.description = form.cleaned_data['description']
                product.price = form.cleaned_data['price']
                product.razdel = form.cleaned_data['razdel']
                product.refract = False
                product.save()
                cont['message'] = u'Всё сохранено'
            except:
                product = form.save()
                product.img = request.FILES['img']
                cont['message'] = u'Новое изделие добавлено'
    else:
        try:
            product_ed = Product.objects.get(slug=product, refract=True)
            cont['product_ed'] = product_ed
            cont['form'] = ProductForm(instance=product_ed)
        except Product.DoesNotExist:
            cont['form'] = form
            cont['message'] = u'Не найден такой продукт, будет создан новый'
    return render_to_response('admining/product_edit.html', cont, context_instance=RequestContext(request))
Ответ написан
Комментировать
@ATNC
Full-stack web\python developer
Попробуйте сделать что-то на подобии такого:
добавьте в клас UserProfile
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])

Эта конструкция даст возможность для доступа к профайлу через атрибут profile. Например, user.profile.picture

Потом во вьюхе добавьте
if request.POST:
        form = UserProfileForm(request.POST, request.FILES, instance=request.user.profile)
        if form.is_valid():
            form.save()
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы