[
Показаны сообщения с ярлыком django. Показать все сообщения
Показаны сообщения с ярлыком django. Показать все сообщения

суббота, 24 декабря 2011 г.

Django 1.4 alpha release

На днях писал о кастомных фильтрах в админке: http://readability-counts.blogspot.com/2011/12/django-admin-listfilter.html. Все оказалось не совсем так - я смотрел trunk репозитория. И вот вышла Django 1.4 alpha с новой фичей, описанной в моем предыдущем посте. Там еще много всего интересного - изучайте!

четверг, 22 декабря 2011 г.

Django Admin и кастомный фильтр для list_filter

Это только набросок - нужно все опробовать на живом коде.

"Вдруг" родилась задача выводить кастомный список значений для фильтра в админке. Поясню, имеем следующую модель:
class NewsPost(models.Model):
    """Новость"""

    authors = models.ManyToManyField(User, blank = True, null = True)

В админке она представлена так:
class NewsPostAdmin(admin.ModelAdmin):
    """Представление Новости в админке"""

    # фильтрация новостей по автору
    list_filter = ('authors',)

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        """Специальная фильтрация для списка допустимых авторов

        Данная фильтрация распространяется только на поле authors в
        форме редактирования новости в админке
        """

        if db_field.name == 'authors':
            kwargs['queryset'] = User.objects.filter(is_staff=True)
        return super(PostAdmin, self).formfield_for_manytomany(
            db_field, request, **kwargs)

В итоге в форме редактирования новости в админке в качестве автора можно будет указать только пользователя со статусом Персонал (Staff), но для фильтра списка новостей будут выведены все пользователи системы.

Из документации по админке Django сказано, что в list_filter можно указывать только название поля:
Set list_filter to activate filters in the right sidebar of the change list page of the admin. This should be a list of field names, and each specified field should be either a BooleanFieldCharFieldDateFieldDateTimeFieldIntegerField or ForeignKey.
Fields in list_filter can also span relations using the __ lookup:
Но если посмотреть код в django.contrib.admin.views.main.ChangeList, метод get_filters() то увидим следующее:
...
filter_specs = []
if self.list_filter:
    for list_filter in self.list_filter:
        if callable(list_filter):
            # This is simply a custom list filter class.
            spec = list_filter(request, lookup_params,
                self.model, self.model_admin)
        else:
            ...

Оказывается в list_filter можно указать "какой-то" класс, экземпляр, которого будет создан для фильтрации. Классы эти можно увидеть вот тут:  django.contrib.admin.filters.

To be continued...

воскресенье, 21 августа 2011 г.

Утечка памяти в Django

Взято от сюда: http://stackoverflow.com/questions/1339293/python-memory-leak-debugging

Если вы пишите скрипт или management command для обслуживания сайта на Django, то можете наткнуться на то, что у вас "утекает" память. На самом деле это не совсем так - добавляется debug информация и логируются запросы. Чтобы этого избежать, сделайте следующее:

  1. выключите DEBUG в настройках;
  2. где-то в коде делайте db.reset_queries().

Если это не помогло, тогда да, ищите утечку.

понедельник, 1 августа 2011 г.

Поиск в Django (Haystack)

В большинстве проектов так или иначе требуется поиск. И тут, на мой взгляд, есть варианта действий:
  • написать свой поиск;
  • скормить сайт какой-нибудь поисковой системе;
  • воспользоваться готовым решением.
Первый вариант я бы отмел сразу - относительно просто до тех пор пока трафик на вашем ресурсе не пойдет вверх, тогда вам придется думать о хешировании, кешировании и прочих прелестях.

Скормить сайт поисковику, на мой взгляд, самый правильный вариант, но что делать если вы пишите внутреннее приложение без доступа извне?

Немного погуглив на эту тему, наткнулся на весьма интересный проект для Django: Haystack. То, что меня сразу "зацепило" а.к.а. возможности из коробки:
  • индексирование;
  • настраиваемые поисковые формы;
  • настраиваемые поисковые представления.
Еще одна вещь мне была поначалу непонятна: настраиваемые шаблоны для поиска. Как оказалось именно в этих шаблонах вся "фишка" haystack. Эти шаблоны никому никогда не показываются, но именно они индексируются.

Итак, давайте поподробнее посмотрим как это работает. Пусть имеется приложение blogs и следующие модели:

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __unicode__(self):
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()

    def __unicode__(self):
        return self.name

class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateTimeField()
    mod_date = models.DateTimeField()
    author = models.ForeignKey(Author)
    n_comments = models.IntegerField()
    n_pingbacks = models.IntegerField()
    rating = models.IntegerField()

    def __unicode__(self):
        return self.headline

Искать надо, скажем, записи (Entry), но пусть также находятся записи где поисковый запрос соответствует имени или email'у автора, а также названию или тегу блога. Т.е. поиск должен происходить не только по модели Entry, но и по Blog и Author. Вот тут нам и помогут те самые настраиваемые шаблоны для поиска.

Для этого создаем файл search_indexes.py в папке с приложением следующего содержания:
from haystack.indexes import *
from haystack import site

from blogs import models

class EntryIndex(RealTimeSearchIndex):
    # специальное поле - должно быть только одно в модели
    text = CharField(document=True, use_template=True)
    
    # поля из модели Entry
    headline = CharField(model_attr='headline')
    body_text = TextField(model_attr='body_text')  

    # поля модели Blog
    blog_name = CharField(model_attr='blog__name')
    blog_tagline = CharField(model_attr='blog__tagline')

    # поля модели Author
    author_name = CharField(model_attr='author__name')
    author_email = CharField(model_attr='author__email')

site.register(models.Entry, EntryIndex)

Теперь необходимо создать сам шаблон