Django models.ImageField не загружает файлы

Добрый час я потратил на вот обычную беду, вроде всё сделано верно, но форма передаёт имя файла. а сам файл на сервере не появляется, в дебаг-тулбар был SQL запрос на INSERT а поле bla bla avatar = WHERE blabla= blabla

В итоге я стал понимать что форма шлёт только текстовые поля. и файлы не передаёт на сервер. и сервер ругается мол имя пришло а картинки нету!!!
Говорит
[cc lang=”python”]The ‘avatar’ attribute has no file associated with it.[/cc]

Вот оно и тут… всё дело в свойствах формы, мне не хватало
[cc lang=”html”]enctype=”multipart/form-data”[/cc]

Расширение профиля пользователя django

в Django я по прежнему новичок, но что-то стараюсь понять и запомнить.

стояла задача расширить профиль пользователя дополнительными полями, статей на эту тему пресс и малелькая тележка, но не получалось, то у кого-то на сайте парсер html сильно злой и код надо было переписывать, у кого-то были ошибки в примерах и т.п.

но как-то оно получилось, попробую собрать все мысли в кучу в эту статью.

Многие знают о django-registration и вот от автора этого замечательного приложения существует django-profiles котором я и воспользовался.

устанавливаем django-profiles
[cc lang=”bash”]easy_install django-profiles[/cc]

в models.py создадим модель профиля, которая наследуется от штатной User и добавим в ней нужное нам поле

[cc lang=”python”]
from django.contrib.auth.models import User


class UserProfile(models.Model):
# поле для связки со встроенной моделью пользователя Django
user = models.ForeignKey(User, unique=True)
# наше новое поле
about = models.TextField(blank=True)[/cc]

Далее в settings.py надо указать кто будет новым AUTH_PROFILE_MODULE

[cc lang=”python”]AUTH_PROFILE_MODULE = ‘list.UserProfile'[/cc]
где list это ваше приложение в котором расположена модель расширяющая пользователя

в принципе на этом можно закончить, ибо обращаться теперь можно к
[cc lang=”bash”]{{ user.get_profile.about }}[/cc]
только нужно обратить внимание что надо пользоваться не context а RequestContext
и указать это в
TEMPLATE_CONTEXT_PROCESSORS файла settings.py

[cc lang=”python”]TEMPLATE_CONTEXT_PROCESSORS = (

‘django.contrib.auth.context_processors.auth’,

) [/cc]

но мы идём дальше

Теперь нам надо подключить django-profiles для просмотра\редактирования профиля

в файле urls.py
подключаем

[cc lang=”python”] …
(r’^profiles/’, include(‘profiles.urls’)),
…[/cc]

в settings.py также подключим приложение

[cc lang=”python”]INSTALLED_APPS = (

‘profiles’,
)
[/cc]

теперь создадим таблицы в базе

[cc lang=”python”]python manage.py syncdb[/cc]

приложение profiles использует вот такие шаблоны

[cc lang=”bash”]
profiles/create_profile.html
profiles/edit_profile.html
profiles/profile_detail.html
profiles/profile_list.html[/cc]

по названию понятно что к чему

для начала отредактируем edit_profile.html
[cc lang=”html”]{% extends “base.html” %}
{% block title %}Edit Profile{% endblock %}

{% block content %}

Edit contact info for {{ user }}

{{ form }}

{% endblock content %}[/cc]

сохраняем, теперь можно обратиться к /profiles/edit/ то должно открыться форма редактирования профиля.

бывают ситуации, что в профиле есть какие-то поля, что запрещено редактировать пользователю, реализуется это довольно просто

создаём класс формы, наследуемой от общей формы, в котором перечисляем, то что нам исключить от вывода пользователю
forms.py

[cc lang=”python”]from django.db import models
from django.forms import ModelForm
from PROJ.apps.APP.models import UserProfile

………
class ProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
exclude = (‘user’,’last_name’,)
[/cc]
from PROJ.apps.APP.models import UserProfile
проект и приложение где расположена расширенная модель

теперь в urls.py надо указать, что страницу редактирования профиля надо открывать с нужной нам формой

[cc lang=”python”]from PROJ.APP.forms import ProfileForm
……..
(‘^profiles/edit’, ‘profiles.views.edit_profile’, {‘form_class’: ProfileForm,}),
(r’^profiles/’, include(‘profiles.urls’)),
…….[/cc]
Должно получиться примерно так.. проверяем на странице редактирования профиля (/profiles/edit/).

Теперь сделаем страницу отображения профиля profile/profile_detail.html

вывести можно что угодно из профиля вот так
[cc lang=”python”]

Address 2:
{{ profile.address2 }}

[/cc]
где address2 это дополнительное поле
список пользователей с профилями можно вывести вот так

profiles/profile_list.html
[cc lang=”python”]
{% extends “base.html” %}
{% block content %}

Список пользователей

{% for p in object_list %}
{{ p.user }}
{% endfor %}
{% endblock %}
[/cc]

Теперь задача такая, сейчас профиль и пользователь живут почти своей жизнью, при регистрации пользователя профиль сам не создаётся это мы сейчас и решим сигналами.

в models.py добавим

[cc lang=”python”]
from django.db.models import signals
from bucket.signals import create_profile

# When model instance is saved, trigger creation of corresponding profile
signals.post_save.connect(create_profile, sender=User)[/cc]

создадим файл, если он не создан signals.py:

[cc lang=”python”]def create_profile(sender, instance, signal, created, **kwargs):
“””When user is created also create a matching profile.”””

from PROJ.apps.APP.models import UserProfile

if created:
UserProfile(user = instance).save()
# Do additional stuff here if needed, e.g.
# create other required related records
[/cc]

вот и всё, при регистрации нового пользователя автоматически будет создаваться к нему профиль, если у вас уже сейчас много пользователей, то создать для каждого профиль можно вот так

[cc lang=”python”]$ python manage.py shell

from django.contrib.auth.models import User
from bucket.models import Profile

users = User.objects.all()
for u in users:
try:
p = u.get_profile()
except p.DoesNotExist:
Profile(user = u).save()[/cc]

ещё коснусь вопроса редактирования своего email в профиль, пока ещё не совсем разобрался с этим.

пока есть только пример, делается это анналогично через forms.py

[cc lang=”python”]class ProfileForm(ModelForm):

def __init__(self, *args, **kwargs):
super(ProfileForm, self).__init__(*args, **kwargs)
try:
self.fields[’email’].initial = self.instance.user.email
# self.fields[‘first_name’].initial = self.instance.user.first_name
# self.fields[‘last_name’].initial = self.instance.user.last_name
except User.DoesNotExist:
pass

email = forms.EmailField(label=”Primary email”,help_text=”)

class Meta:
model = Profile
exclude = (‘user’,)

def save(self, *args, **kwargs):
“””
Update the primary email address on the related User object as well.
“””
u = self.instance.user
u.email = self.cleaned_data[’email’]
u.save()
profile = super(ProfileForm, self).save(*args,**kwargs)
return profile[/cc]

надеюсь вернусь к этому вопросу

fsck.ext4: Memory allocation failed while retrying to read bitmaps for /dev/md0 e2fsck: aborted

Вот такой заголовок текст мне кинул мой NAS на debian выполняющий роль Бэкап хранилища…

[cc lang=”bash”]fsck.ext4: Memory allocation failed while retrying to read bitmaps for /dev/md0 e2fsck: aborted[/cc]

При этом отказывался грузиться, потерю бэкап сервера я заметил не сразу, может недельку без него прожил.. а не дай бог в это время что-то случилось?

так вот гугл толком ничгео не сказал, но если прочитать сообщение стало понятно, что он не смог вгрузить битовую карту 4Тб хранилища из-за мелкого размера оперативки(500) и swap(100!!!)
Хотя разметку диска дебиан делал автоматически.
так вот ладно грузимся дальше начинаем понимать, вижу что кончается опера и ивсё виснет htop не успевает показать что swap тоже кончается, пробую увеличить swap

создаю файл на 1Гб
[cc lang=”bash”]dd if=/dev/zero of=/swapfile ibs=10485760 count=100[/cc]
создаю файловую систему
[cc lang=”bash”]mkswap /swapfile[/cc]
подключаю новый файл как файл подкачки
[cc lang=”bash”]swapon /swapfile[/cc]
вот так смотрю что у меня с подкачкой?
[cc lang=”bash”]# swapon -s
Filename Type Size Used Priority
/dev/sda5 partition 92152 37880 -1
/swapfile file 981296 144 -2
[/cc]

ну и всё запускаю заново проверку FS и она продолжается успешно…

Маленькая точка в SAPE

И так, господа, покажу вам ацки мотивирующий скрин с моей учётки в сапе.

Вот такая сухая циферка. за какой срок? можно в моём блоге посмотреть прошлые записи, я думаю что-то в районе года.

кто-то скажет мало, кто-то скажет много. каждый решит сам.

PS недавно ко мне постучалась ещё одна “сапа” и предложила сотрудничать с ними. предложили фиксированную плату в месяц, я согласился, посмотрим что из этого получится, о результатах напишу, скоро пройдёт первый месяц 😉

Radio Tray (плеер для online Radio) + Проблема с кодировкой

Люблю я всякие мелкие но страшно полезные утилитки, лёгкая, простоя, умеет делать 1 вещь, но делает это отлично!

и так
Radio Tray

Сидит в трее и афигенно играет радио, отличная буферизация, написана на питоне использует оч популярную библиотеку потокового воспроизведения.

скрин

под современными убунтами последнюю версию можно установить вот так

[cc lang=”bash”]sudo add-apt-repository ppa:eugenesan/ppa
sudo apt-get update
sudo apt-get install radiotray[/cc]

дальше в каталоге мультимедии у нас появится данная пиктограмма, запускаем, добавляем любимое
“Наше Радио”
но вот беда, кракозябры при отображении треков.

Не беда, открываем вот этот файл

[cc lang=”bash”]sudo gedit /usr/share/pyshared/radiotray/StateMediator.py[/cc]

Находим строчку
[cc lang=”python”]def notifySong(self, data):[/cc]

После неё идёт строка
[cc lang=”python”]newMetadata = str(data)[/cc]
Вот её надо заменить на вот такую строку
[cc lang=”bash”]newMetadata = str(data).encode(‘latin-1’).decode(‘cp1251’).encode(‘utf8’)[/cc]

У меня получилось примерно вот так.

PS Обратим внимание, что код на Python и отступы в нём не ТАБ а пробелы, в данной строке 8 пробелов.
с табами может не работать 😉