slugify не працює з unicode стрічками

а щоб працював, є чудовий пакет Unidecode

і приклад:
from django.template.defaultfilters import slugify
import unidecode
from unidecode import unidecode
#...
task_object.slug = slugify(unidecode(u'%s' % name))

зміна queryset в формі

Є три моделі з наступними зв'язками і форма:

class Task(models.Model):
location = models.ForeignKey(Locations, related_name='Task_location')
buyer = models.ForeignKey(UserProfile, related_name='Task_buyer')

class Locations(models.Model):
user = models.ForeignKey('registration.UserProfile', \
verbose_name=_('user'), related_name="user_locations")

class UserProfile(User):

class TaskForm(ModelForm):

class Meta:
model = Task
fields = ('location', 'name', 'description')


Тобто, в таск привязаний до юзера і юзерського локейшена. Форма мені виводить всі локейшени всіх юзерів, що не є добре. Хочу щоб виводились лише рідні локейшени юзера.

Рішення просте. Перевизначити init TaskForm'и і змінити queryset поля location
У вюшці в конструктор TaskForm передаємо request.user, бо нам треба буде фільтрувати по ньому Locations
views.py
@login_required
@render_to('')
def task_add(request, template="tasks/add.html"):
if request.method == 'POST':
form = TaskForm(request.POST, user=request.user)
if form.is_valid():
task = form.save(request.user, 1)
TaskStatus.objects.create(task=task, task_status=1)
return redirect("home")
else:
form = TaskForm(user=request.user)
return {'form': form,}, template

forms.py
class TaskForm(ModelForm):

class Meta:
model = Task
fields = ('category', 'location', 'name', 'description', 'price')

def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(TaskForm, self).__init__(*args, **kwargs)
self.fields['location'].queryset=Locations.objects.filter(user=self.user)

def save(self, user=None, task_status=None, commit=True):
task_object = super(TaskForm, self).save(commit=False)
task_object.buyer = user
task_object.task_status = task_status
if commit:
task_object.save()
return task_object

повідомлення для користувача

Часто потрібно посилати користувачу якісь повідомлення про помилки чи успішні операції. Нутром почув, що є вже готове рішення і таки так. Переклад куска мануала по цьому: http://habrahabr.ru/blogs/django/87473/

розширення моделі User

Часто трапляється, що крім імені користувача потрібно зберегти ще багато даних, для цього треба розширювати вбудовану модель User. Оптимальне рішення: http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/

авторизація в соціальних мережах

Коротко і зрозуміло в себе в блозі розписав один з доробників socialauth, дописавши можливість авторизуватись на сервісах популярних в СНД.

sorl-thumbnail

https://github.com/sorl/sorl-thumbnail
Для створення аватарок та різних маніпуляцій з малюнками прямо з шаблона - в самий раз.

В моєму випадку є 2 аватарки, одна 100х100, друга 50х50, то друга створюється на льоту за допомогою sorl-thumbnail

приклад:
{% load thumbnail %}
{% thumbnail r4.from_user.avatar "50x50" crop="center" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}">
{% endthumbnail %}

методи в моделі та виклик їх з шаблонів

є дві моделі, в одній опис задачі, в іншу скаладються статуси до цієї задачі. Потрібно визначити поточний статус задачі, тобто зробити вибірку в TaskStatus по конкретній задачі і обчислити максимальне значення.

class Task(models.Model):
name = models.CharField(max_length=120)
category = models.ForeignKey('TaskCategory')
description = models.TextField()
price = models.DecimalField(max_digits=5, decimal_places=2, blank=True)
buyer = models.ForeignKey(Profile, related_name='buyer')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Meta:
verbose_name = _('Task')
verbose_name_plural = _('Tasks')
ordering = ['created_at']

def __unicode__(self):
return self.name

def current_status_str(self):
task_status = TaskStatus.objects.filter(task=self)
current_status = task_status.aggregate(Max('task_status'))
return TaskStatus.TASK_STATUS_VALUES[current_status['task_status__max']-1][1]

def current_status_int(self):
task_status = TaskStatus.objects.filter(task=self)
current_status = task_status.aggregate(Max('task_status'))
return current_status['task_status__max']

def get_absolute_url(self):
return reverse('tasks_details', args=[self.pk])

class TaskStatus(models.Model):
POSTED, ASSIGNED, COMPLETED, CLOSED = range(1,5)
TASK_STATUS_VALUES = (
(POSTED, 'Posted'),
(ASSIGNED, 'Assigned'),
(COMPLETED, 'Completed'),
(CLOSED, 'Closed'),
)
task = models.ForeignKey(Task)
task_status = models.IntegerField(choices=TASK_STATUS_VALUES, blank=True, null=True)

provider = models.ForeignKey(User, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)

def timesince(self, now=None):
return timesince_(self.created_at, now)

def __unicode__(self):
return unicode(self.task)

і в шаблоні звертаємось до потрібного метода
{% for task in tasks %}
{{ task }}
{{ task.current_status_str }}
{% empty %}
no tasks yet
{% endfor %}


і результат:

timesince і модна дата

зараз модно дату писати в такому форматі: Review to Юзернейм from Юзернейм 2 hours, 44 minutes ago

реалізація в моделі:
from django.utils.timesince import timesince as timesince_

class Review(models.Model):
to_user = models.ForeignKey('users.Profile', verbose_name=_('from user'), \
related_name="review_to_user")
from_user = models.ForeignKey('users.Profile', verbose_name=_('to user'), \
related_name="review_from_user")
timestamp = models.DateTimeField(_('timestamp'), auto_now_add=True)

class Meta:
verbose_name = _('rating')
verbose_name_plural = _('ratings')
ordering = ['timestamp']

def timesince(self, now=None):
return timesince_(self.timestamp, now)


def __unicode__(self):
return unicode("Review to %s from %s %s ago" % \
(self.to_user, self.from_user, self.timesince()))


def get_absolute_url(self):
return reverse('reviews_reviews', args=[self.to_user])

choices значення в шаблоні

class TaskStatus(models.Model):
POSTED, ASSIGNED, COMPLETED, CLOSED = range(1,5)
TASK_STATUS_VALUES = (
(POSTED, 'Posted'),
(ASSIGNED, 'Assigned'),
(COMPLETED, 'Completed'),
(CLOSED, 'Closed'),
)
task = models.ForeignKey(Task)
task_status = models.IntegerField(choices=TASK_STATUS_VALUES, blank=True, null=True)


Класичний вивід в шаблоні task_status видасть int значення.
Щоб вивести асоційоване ім'я, в шаблоні потрібно писати наступну конструкцію:
{% for ts in task_status %}
{{ ts.get_task_status_display}}
{% endfor %}

django debug

Простий і швидкий варіант переглянути вміст змінної, кортежу, об'єкту...:
import pprint


assert False, pprint.pformat(object)
assert False, pprint.pformat(object.__dict__)
assert False, pprint.pformat(object.__dict__.keys())
assert False, pprint.pformat(object.__dict__.values())

джоіни

є моделі:
class Task(models.Model):
name = models.CharField(max_length=120)
buyer = models.ForeignKey(Profile, related_name='buyer')

class TaskStatus(models.Model):
POSTED, ASSIGNED, COMPLETED, CLOSED = range(1,5)
TASK_STATUS_VALUES = (
(POSTED, 'Posted'),
(ASSIGNED, 'Assigned'),
(COMPLETED, 'Completed'),
(CLOSED, 'Closed'),
)
task = models.ForeignKey(Task)
task_status = models.IntegerField(choices=TASK_STATUS_VALUES, blank=True, null=True)


треба зробити вибірку з TaskStatus але відфільтрувати по Task.buyer, тобто зробити JOIN-запит. Порився трошки в гуглі, не особливо щось знайшов. От і думаю, вот ORM не така вже універсальна! Але стандартні засоби все ж є:
TaskStatus.objects.filter(task__buyer=request.user)

django fixtures

Наскільки зручна річ...
Коли проект розростається, додаються нові аплікейшени і роширюються моделі, інколи простіше витерти чи обнулити файл бази даних. Тоді з нуля потрібно заводити користувачів, постити якісь дані, на що йде додатковий час. Фікстури дозволяють при manage.py syncdb догружати потрібні дані.
Для цього в потрібному аплікейшені створюємо каталог fixtures і зберігаємо JSON (також можливі інші формати) файл даних з іменем initial_data.json
Для того щоб зробити повний дамп даних проекту, потрібно виконати manage.py dumpdata > dump.json Потім я в PyCharm привожу код до читабельного вигляду, вирізаю потрібні дані і роблю вищеописані дії.
Приклад:
[
{
"pk": 64,
"model": "auth.permission",
"fields": {
"codename": "add_attachment",
"name": "Can add attachment",
"content_type": 22
}
},
{
"pk": 65,
"model": "auth.permission",
"fields": {
"codename": "change_attachment",
"name": "Can change attachment",
"content_type": 22
}
},
{
"pk": 66,
"model": "auth.permission",
"fields": {
"codename": "delete_attachment",
"name": "Can delete attachment",
"content_type": 22
}
},
{
"pk": 67,
"model": "auth.permission",
"fields": {
"codename": "delete_foreign_attachments",
"name": "Can delete foreign attachments",
"content_type": 22
}
},
{
"pk": 1,
"model": "auth.group",
"fields": {
"name": "attachments",
"permissions": [64, 65, 66, 67]
}
},
]

чим додаємо гурт і права до нього

керування користувачами, гуртами та правами

Досить мало про це написано в документації.
Наглядний приклад: http://parand.com/say/index.php/2010/02/19/django-using-the-permission-system/

int значення в radio форму



class ReviewForm(ModelForm):
RATING_CHOICES = ((1, '1'), (2, '2'), (3, '3'), (4, '4'), (5, '5'),)
rate = forms.TypedChoiceField(choices=RATING_CHOICES, \
widget=forms.RadioSelect, coerce=int)

def clean_rate(self):
if self.cleaned_data['rate'] >= 1 and self.cleaned_data['rate'] <= 5:
return self.cleaned_data['rate']
else:
raise forms.ValidationError(_("Rating error"))

class Meta:
model = Reviews
fields = ('rate', 'message', 'content_type', 'object_id')
widgets = {
'content_type' : forms.HiddenInput(),
'object_id' : forms.HiddenInput()
}

Передавання у формах значень у вигляді hidden полей

Є модель
class Reviews(models.Model):
object_id = models.PositiveIntegerField(_('object id'))
content_type = models.ForeignKey(ContentType, verbose_name=_('content type'))
object = GenericForeignKey('content_type', 'object_id')
rate = models.DecimalField(decimal_places=1, max_digits=2)
user = models.ForeignKey(User, verbose_name=_('user'))
message = models.TextField(_('message'))
timestamp = models.DateTimeField(_('timestamp'), auto_now_add=True)
def __unicode__(self):
return unicode(self.user)

при роботі з формами треба object_id і object_id передавати у hidden полях і також ініціалізувати їх при створенні форми.
forms.py
class ReviewForm(ModelForm):

class Meta:
model = Reviews
fields = ('rate', 'message', 'content_type', 'object_id')
widgets = {
'content_type' : forms.HiddenInput(),
'object_id' : forms.HiddenInput()
}


views.py
    if request.method == "POST":
form = ReviewForm(request.POST)
if form.is_valid():
r = form.save(commit=False)
r.user = request.user
r.save()
return redirect('home')
else:
ct = ContentType.objects.get_for_model(user)
form = ReviewForm(initial={'content_type': ct.pk, 'object_id': user.id})

coercing to Unicode: need string or buffer, Task found

Цікаву САБЖ помилку дебажив.
class Task(models.Model):
name = models.CharField(max_length=120)
description = models.TextField()
price = models.DecimalField(max_digits=5, decimal_places=2)
buyer = models.ForeignKey(User, related_name='buyer')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __unicode__(self):
return self.name

class TaskStatus(models.Model):
POSTED, ASSIGNED, COMPLETED, CLOSED = range(1,5)
TASK_STATUS_VALUES = (
(POSTED, 'Posted'),
(ASSIGNED, 'Assigned'),
(COMPLETED, 'Completed'),
(CLOSED, 'Closed'),
)
task = models.ForeignKey(Task)
task_status = models.IntegerField(choices=TASK_STATUS_VALUES, blank=True, null=True)
provider = models.ForeignKey(User, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return self.task


лікується:
    def __unicode__(self):
return unicode(self.task)