[

суббота, 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...

среда, 7 декабря 2011 г.

Скрипт-лоттерея

Для чего его использовать - ваша воля. Мы же его использовали для распределения смен технической поддержки на НГ.


# coding: utf-8
import random
import readline


def get_random_workers():
    """Start lottery"""

    # Список людей
    people = []

    # Заполним список участников
    while 1 == 1:
        name = raw_input("Введите имя сотрудника (пустая строка для завершения): ")
        name = name.strip()
        if name == '':
            break
        people.append(name)

    # проверим, что участники введены
    if not people:
        print("Нет участников для нашей лоттереи :( жаль.")
        sys.exit()

    # Случайный выбор из списка
    print("\nА сейчас... победители!")
    print("Нажмите Enter для получения следующего \"счастливчика\" или q для завершения")
    while 1 == 1:
        s = raw_input()
        if s == 'q':
            break
        random.seed()
        print(random.choice(people))

    # конец
    print("\nДо встречи перед следующими праздниками!")

if __name__ == '__main__':
    get_random_workers()

Баги:

  1. raw_input() отказывается читать кирилицу, хотя везде все UTF-8. можно переопределить sys.stdin - экземпляр StreamReader.