Что нового нас ожидает в Django 1.7

    В данном посте представлен обзор новшеств и особенностей популярного среди Python разработчиков фреймворка Django 1.7. Релиз позиционируется как сообществом, так и основными разработчиками — как наиболее значимый релиз, с момента выхода в свет Django 1.0.

    image


    Новшества в версии 1.7


    Прекращение поддержки Python 2.6. Теперь поддерживается версия Python 2.7 и выше. Заявлена поддержка Python 3.4.
    Добавлена нативная поддержка миграций непосредственно в сам фреймворк. Можно поблагодарить за это автора популярной батарейки South — Andrew Godwin-а.

    Команда syncdb объявлена как устаревшая, и будет удалена в Django 1.9. До тех пор syncdb является псевдонимом команды migrate, которая обеспечивает как выполнение миграций, так и старое поведение syncdb.
    Фикстуры initial_data более не инициализируются по умолчанию для приложений с миграциями. Предлагается воспользоваться загрузкой фикстур на уровне самих миграций.

    Механизм загрузки приложения — был подвергнут полному рефакторингу. В результате можно отказаться от models.py, который ранее идентифицировал приложение и был обязательным.
    Новые методы подклассов Field. Главная особенность — это обязательный метод deconstruct(). К сожалению в этом вина включения миграций в состав Django. Если Вы наследуетесь от стандартных полей и не переопределяете метод __init__, то заботиться Вам об этом не придется.

    Появилась возможность вызовов QuerySet-ов напрямую из менеджера:

    class FoodQuerySet(models.QuerySet):
        def pizzas(self):
            return self.filter(kind='pizza')
    
        def vegetarian(self):
            return self.filter(vegetarian=True)
    
    class Food(models.Model):
        kind = models.CharField(max_length=50)
        vegetarian = models.BooleanField()
        objects = FoodQuerySet.as_manager()
    
    Food.objects.pizzas().vegetarian()
    

    Возможность указать необходимый менеджер при использовании связывания моделей:
    class Blog(models.Model):
        pass
    
    class Entry(models.Model):
        blog = models.ForeignKey(Blog)
    
        objects = models.Manager()  # Default Manager
        entries = EntryManager()    # Custom Manager
    
    b = Blog.objects.get(id=1)
    b.entry_set(manager='entries').all()
    


    Новая система, для проверки проекта(System check), которая при запуске опеделяет проблемы и подсказывает что и как необходимо исправить. Для проверки, используется новая команда check, пришедшая на замену устаревшей команде validate.
    Новый Prefetch для продвинутых операций prefetch_related. Теперь можно настроить предварительную выборку используя QuerySet-ы.

    Поддержка текущего часового пояса в панели администратора, при работе с виджетом даты. Прежде использовался часовой пояс браузера. При расхождении времени в браузере и на сервере — выводится визуальная подсказка.

    Курсор баз данных, теперь может использоваться в качестве контекст менеджера, что является сокращением для:

    c = connection.cursor()
    try:
        c.execute(...)
    finally:
        c.close()
    


    Возможность определения собственных типов поиска, для фильтрации при использовании ORM.

    from django.db.models import IntegerField
    from django.db.models import Transform
    
    class AbsoluteValue(Transform):
        lookup_name = 'abs'
    
        def as_sql(self, qn, connection):
            lhs, params = qn.compile(self.lhs)
            return "ABS(%s)" % lhs, params
    
    IntegerField.register_lookup(AbsoluteValue)
    
    # Использование
    Experiment.objects.filter(change__abs=27)
    
    # В результате получим
    # SELECT ... WHERE ABS("experiments"."change") = 27
    


    Другие интересные изменения


    django.contrib.admin
    • Появилась возможность реализовать собственные site_header, site_title, и index_title, без необходимости переопределения шаблона.
    • Метод ModelAdmin.get_fields() может быть преопределен, для настройки значений ModelAdmin.fields.
    • В дополнение к существующему синтаксису admin.site.register, можно использовать новый декоратор register().
    • Можно задать ModelAdmin.list_display_links = None, для того что бы отключить ссылки в grid-е
    • Для контроля кнопки «Посмотреть на сайте», можно определить свой ModelAdmin.view_on_site.
    • Возможность указать сортировку для ModelAdmin.list_display, подставляя дефис в admin_order_field.
    • Метод ModelAdmin.get_changeform_initial_data() может быть переопределен, для изменения данных формы.


    django.contrib.auth
    • **kwargs передаваемые в email_user(), так же передаются и в send_mail().
    • декоратор permission_required() может получать на вход список разрешений или же только одно разрешение.
    • возможно переопределить новый метод AuthenticationForm.confirm_login_allowed(), для быстрой и легкой настройки политики авторизации.
    • django.contrib.auth.views.password_reset() принимает необязательный параметр html_email_template_name. Параметр используется для отправки html писем, при сбросе пароля .
    • добавлен метод AbstractBaseUser.get_session_auth_hash(). Если пользовательская модель унаследована от AbstractBaseUser, то изменение пароля пользователя приведет к сбросу его устаревших сесссий.


    django.contrib.sites


    E-mail
    • В send_mail() добавлен параметр html_message, для отправки сообщений типа text/html.
    • SMTP бекенд получил возможность установить параметр тайм-аута.


    Загрузка файлов
    • Добавлен атрибут UploadedFile.content_type_extra, который содержит дополнительные параметры, передаваемые в заголовоке типа содержимого при загрузке файлов.
    • Новая настройка FILE_UPLOAD_DIRECTORY_PERMISSIONS позволяет задавать права на создаваемые директории при загрузке файлов. Ту же настройку непосредственно для файлов, выполняет FILE_UPLOAD_PERMISSIONS.
    • FileField.upload_to теперь является необязательным.


    Формы
    • Textarea теперь включает атрибут max_length, если в модели определен max_length.
    • Field.choices позволяет задать value для пустого значения. По умолчанию "-------".
    • В формах в методе clean() более не требуется возвращать self.cleaned_data.
    • Появилась возможность удалить поля из формы, путем установки их имени в None.
    • Новый метод add_error() позволяет задавать ошибки для конкретных полей.
    • Добавлена возможность задавать и выводить ошибки к ограничителям вида unique, unique_for_date, и unique_together.


    Интернационализация
    • Атрибут django.middleware.locale.LocaleMiddleware.response_redirect_class позволяет настроить переадресацию.
    • LocaleMiddleware хранит выбранный язык пользователем язык в _language. Получить доступ, можно используя константу LANGUAGE_SESSION_KEY.
    • Тег blocktrans удаляет атрибут trimmed. Данная опция удаляет символы новой строки с начала и до конца, обьеденяя их через пробел. Что удобно для генерации файлов локали.
    • Улучшен makemessages.
    • Были добавлены следущие языковые константы: LANGUAGE_COOKIE_AGE, LANGUAGE_COOKIE_DOMAIN and LANGUAGE_COOKIE_PATH.


    Команды управления
    • Возможность отключить цветной вывод в консоль.
    • Добавлена возможность дампа данных с первичными ключами при сериализации.
    • Нет необходимости указывать название кеш таблицы при использовании createcachetable. Теперь Django это делает сама, с учетом настройки кеша в настройках проекта.
    • Команда runserver была улучшена. Теперь при установленном pyinotify, скорость релоада стала выше, и меньше потребляет батарею на ноутах. Так же сервер релоадиться при использовании команды compilemessages. Выводятся в консоль все запросы к статике, которые прежде фильтровались.


    Модели
    • Новый метод QuerySet.update_or_create().
    • Новая Meta опция default_permissions, которая позволяет настроить операции создания/изменения/удаления.
    • Обнаружение OneToOneField при наследовании в абстрактных классах.
    • Добавлена возможность использовать None в качестве значения запроса при использовании iexact.
    • Возможность использования единого списка в index_together при указании одного набора полей(не список в списках).
    • Числовые поля теперь проверяются в зависимости от БД. Ранее могло приводить к ошибке.


    Запросы и ответы
    • Новый атрибут HttpRequest.scheme определяет схему запроса (http или https).
    • redirect() поддерживает относительный URL.
    • Новый подкласс HttpResponse — JsonResponse.

    Утилиты


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

    Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

    Метки:
    Поделиться публикацией
    Похожие публикации
    Комментарии 14
    • +1
      Появилась возможность вызовов QuerySet-ов напрямую из менеджера:

      Давно пора. Клепать по менеджеру на каждый чих совсем не дело, особенно, когда это просится сделать через classmethod. Пытался пользоваться 1.7 — не договорился с миграцией, репорты висят, еще не фиксили на тот момент. И новый префетч клевый, да.
      • 0
        На тему QuerySet'ов, когда я ковырял исходники трансифекса, нашел там занятную штуку:
        class ChainerManager(models.Manager):
            """
            Reference: http://djangosnippets.org/snippets/562/
            """
            def __init__(self, qs_class=models.query.QuerySet):
                super(ChainerManager, self).__init__()
                self.queryset_class = qs_class
        
            def get_query_set(self):
                return self.queryset_class(self.model)
        
            def __getattr__(self, attr, *args):
                try:
                    return getattr(self.__class__, attr, *args)
                except AttributeError:
                    return getattr(self.get_query_set(), attr, *args)
        


        Что позволяло делать:

        NewsQuerySet(models.query.QuerySet):
            def live(self):
                return self.filter(state='published')
        
            def interesting(self):
                return self.filter(interesting=True)
        
        NewsItem(models.Model):
            objects = ChainerManager(NewsQuerySet)
        
        ChainerManager(NewsQuerySet).live().interesting()
        [<NewsItem: ...>]
        # ну или так:
        NewsItem.objects.filter().live().interesting()
        
        • +1
          Моя ленивый, моя лень забивать objects, да еще добавлять filter().live():

          class Boobs(models.Model):
              …
              @classproperty
              def medium(cls):
                  return cls._default_manager.filter(…)
          
          Boobs.medium.latest()
          
      • +2
        > Курсор баз данных, теперь может использоваться в качестве контекст менеджера:
        А в коде, который написан под этим утверждением, context manager даже и не пахнет.
        • +1
          Спасибо. Дописал недостающую часть.
        • +9
          А как отечественные django-девелоперы относятся к грядущей замене терминов master/slave на leader / follower в django?
          github.com/django/django/pull/2692
        • +1
          Новая мидлварь django.contrib.sites.middleware.CurrentSiteMiddleware позволяет установливать текущий сайт при каждом запросе.

          А обещали, что sites сдохнет…

          Новый подкласс HttpResponse — JsonResponse.

          Наконец-то.
        • 0
          Ребят, а есть ли хорошая/улучшенная поддержка нереляционных БД, вроде MongoDB? Чтобы админка работала сразу и без дополнительных установок плагинов
        • 0
          Пример с кверисетами странный — я обычно то же самое дело в кастомном менеджере, унаследованном от штатного.
          • +1
            Печально, что сам South конфликтует с 1.7

            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.