P
P
patriot022016-05-09 15:26:53
Django
patriot02, 2016-05-09 15:26:53

How to upload an image from a form in django?

There is a user model, it has a field for a picture

class User_profile(models.Model):
    user = models.OneToOneField(User, unique=True)
    avatar = models.ImageField(upload_to='uploads')
    info = models.TextField()

and there is a form for processing
import urllib
class SignupForm(forms.Form):
    username = forms.CharField(
            widget=forms.TextInput( attrs={ 'class': 'form-control', 'placeholder': 'login', }),
            max_length=30, label=u'Логин'
            )
    email = forms.EmailField(
            widget=forms.TextInput( attrs={ 'class': 'form-control', 'placeholder': 'Ваша почта', }),
            required = True, max_length=254, label=u'E-mail',
            )
    password1 = forms.CharField(
            widget=forms.PasswordInput( attrs={ 'class': 'form-control', 'placeholder': '*****' }),
            min_length=6, label=u'Пароль'
            )
    password2 = forms.CharField(
            widget=forms.PasswordInput( attrs={ 'class': 'form-control', 'placeholder': '*****' }),
            min_length=6, label=u'Повторите пароль'
            )
    info = forms.CharField(
        widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': u'Молод и горяч',}),
        required=False, label=u'Пара слов о себе'
    )
    avatar = forms.FileField(
        widget=forms.ClearableFileInput(attrs={'class': 'ask-signup-avatar-input',}),
        required=False, label=u'Аватар'
    )

    def clean_username(self):
        username = self.cleaned_data.get('username', '')

        try:
            u = User.objects.get(username=username)
            raise forms.ValidationError(u'Такой пользователь уже существует')
        except User.DoesNotExist:
            return username

    def clean_password2(self):
        pass1 = self.cleaned_data.get('password1', '')
        pass2 = self.cleaned_data.get('password2', '')

        if pass1 != pass2:
            raise forms.ValidationError(u'Пароли не совпадают')

    def save(self):
        data = self.cleaned_data
        password = data.get('password1')
        u = User()

        u.username = data.get('username')
        u.password = make_password(password)
        u.email = data.get('email')
        u.is_active = True
        u.is_superuser = False
        u.save()

        up = User_profile()
        up.user = u
        up.info = data.get('info')

        if data.get('avatar') is None:
            image_url = 'http://127.0.0.1:8000/uploads/%s.png' % u.username
            content = urllib.urlretrieve(image_url)
            up.avatar.save('%s.png' % u.username, File(open(content[0])), save=True)
        else:
            avatar = data.get('avatar')
            up.avatar.save('%s_%s' % (u.username, avatar.name), avatar, save=True)

        up.save()

        return authenticate(username=u.username, password=password)

1st problem is that pycharm throws an error when submitting ac397cf3648f40ce866eca945b162e3e.pngwith the built-in server, there is no such problem.
The 2nd problem is that when uploading images, they become broken.
How to fix it?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
P
Pavel Aksenov, 2016-05-10
@patriot02

The class name class User_profile in pep8 is written as follows:
Regarding the error with urllib, Alexander answered .
The second problem is the magic that happens in the code.
It is better not to make the SignupForm form completely by handles, but to inherit from
It’s also better to split this form into two, respectively, the first one refers to User, and the second to UserProfile (or User_profile, but not according to pep8)
Saving the avatar should be left to Dzhangu, for this you need to slightly correct the model

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

from django.db import models


def avatar_upload_to(instance, filename):
    return os.path.join('uploads', instance.user.username + os.path.splitext(filename)[1])


class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True)
    avatar = models.ImageField(upload_to=avatar_upload_to)
    info = models.TextField()

Next, I give two forms that turned out after splitting the SignupForm
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from accounts.models import UserProfile


class SignupForm(UserCreationForm):

    username = forms.CharField(
        widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'login', }),
        max_length=30, label=u'Логин'
    )
    email = forms.EmailField(
        widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Ваша почта', }),
        required=True, max_length=254, label=u'E-mail',
    )
    password1 = forms.CharField(
        widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '*****'}),
        min_length=6, label=u'Пароль'
    )
    password2 = forms.CharField(
        widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '*****'}),
        min_length=6, label=u'Повторите пароль'
    )

    class Meta:
        model = User
        fields = ('username', 'email')


class UserProfileSignupForm(forms.ModelForm):

    info = forms.CharField(
        widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': u'Молод и горяч',}),
        required=False, label=u'Пара слов о себе'
    )
    avatar = forms.FileField(
        widget=forms.ClearableFileInput(attrs={'class': 'ask-signup-avatar-input',}),
        required=False, label=u'Аватар'
    )

    def clean_avatar(self):
        avatar = self.cleaned_data.get('avatar')
        if avatar is None:
            raise forms.ValidationError(u'Добавьте картинку')
        if 'image' not in avatar.content_type:
            raise forms.ValidationError(u'Неверный формат картинки')
        return avatar

    class Meta:
        model = UserProfile
        fields = ('info', 'avatar')

in settings.py you need to add paths to all media files
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')

MEDIA_ROOT = os.path.join(PROJECT_DIR, 'media')
MEDIA_URL = '/media/'

Hmm, I don't want to roll everything out here.
I made a repository, you can see it here

V
Vladimir, 2016-05-09
@vintello

different versions of python
, this option is for 2.7
, but you, according to the screenshot, have 3.5.1 installed
there, the format is different ,
either check the version in the code or synchronize

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question