@patriot02

Как загрузить изображение с формы в django?

Есть модель пользователя, в ней поле для картинки
class User_profile(models.Model):
    user = models.OneToOneField(User, unique=True)
    avatar = models.ImageField(upload_to='uploads')
    info = models.TextField()

и есть своя форма для обработки
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)

1я проблема что pycharm выдает ошибку при отправке ac397cf3648f40ce866eca945b162e3e.png со встроенным сервером такой проблемы нету.
2я проблема, то что при загрузке изображений они становятся битыми
Как исправить?
  • Вопрос задан
  • 2067 просмотров
Решения вопроса 1
Название класса class User_profile в pep8 написано следущее:
Class names should normally use the CapWords convention.

По поводу ошибки с urllib ответил Alexander .
Вторая проблема заключается в магии которая происходит в коде.
Форму SignupForm лучше не делать полностью ручками, а унаследовать от
from django.contrib.auth.forms import UserCreationForm

Так же эту форму лучше разбирь на две, соответственно первая относится к User, а вторая к UserProfile(или User_profile, но так не по pep8)
Сохранение аватарки оставить на Джангу, для этого надо немного поправить модель
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()

Далее сделать привожу две формы, которые получились после разделения 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')

в settings.py надо добавить пути ко всем медиа файлам
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')

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

Мда, все сюда выкатывать не хочется.
Сделал репозиторий, можно посмотреть тут
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
разные версии python
этот вариант для 2.7
content = urllib.urlretrieve(image_url)
у вас же, суда по скриншоту , установлен 3.5.1
там формат другой
content = urllib.request.urlretrieve(image_url)
либо проверяйте версию в коде либо синхронизируйтесь
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Похожие вопросы