Любимые советы и особенности Django?

Вдохновленный серией вопросов "Скрытые особенности...", мне любопытно услышать о ваших любимых советах по Django или менее известных, но полезных функциях, о которых вы знаете.

  • Пожалуйста, включайте только один совет за ответ.
  • Добавьте требования к версии Django, если они есть.

55 ответов

Я просто собираюсь начать с подсказки от себя:)

Используйте os.path.dirname() в settings.py, чтобы избежать жестко закодированных каталогов.

Не указывайте путь в вашем файле settings.py, если вы хотите запустить свой проект в разных местах. Используйте следующий код в файле settings.py, если ваши шаблоны и статические файлы находятся в каталоге проекта Django:

# settings.py
import os
PROJECT_DIR = os.path.dirname(__file__)
...
STATIC_DOC_ROOT = os.path.join(PROJECT_DIR, "static")
...
TEMPLATE_DIRS = (
    os.path.join(PROJECT_DIR, "templates"),
)

Кредиты: я получил этот совет из фильма " Джанго с нуля".

Установите Django Command Extensions и pygraphviz, а затем введите следующую команду, чтобы получить действительно красивую визуализацию модели Django:

./manage.py graph_models -a -g -o my_project.png

Используйте Django-раздражает render_to декоратор вместо render_to_response,

@render_to('template.html')
def foo(request):
    bars = Bar.objects.all()
    if request.user.is_authenticated():
        return HttpResponseRedirect("/some/url/")
    else:
        return {'bars': bars}

# equals to
def foo(request):
    bars = Bar.objects.all()
    if request.user.is_authenticated():
        return HttpResponseRedirect("/some/url/")
    else:
        return render_to_response('template.html',
                              {'bars': bars},
                              context_instance=RequestContext(request))

Отредактировано, чтобы указать, что возвращение HttpResponse (например, перенаправление) приведет к короткому замыканию декоратора и будет работать так, как вы ожидаете.

Есть набор пользовательских тегов, которые я использую по всем шаблонам моего сайта. Ища способ его автозагрузки (СУХОЙ, помните?), Я нашел следующее:

from django import template
template.add_to_builtins('project.app.templatetags.custom_tag_module')

Если вы поместите это в модуль, который загружен по умолчанию (например, ваш основной urlconf), у вас будут теги и фильтры из вашего модуля пользовательских тегов, доступные в любом шаблоне, без использования {% load custom_tag_module %},

Аргумент передан template.add_to_builtins() может быть любой путь модуля; Ваш модуль пользовательских тегов не должен жить в определенном приложении. Например, это также может быть модуль в корневом каталоге вашего проекта (например, 'project.custom_tag_module').

Virtualenv + Python = спасатель жизни, если вы работаете над несколькими проектами Django и существует вероятность того, что все они не зависят от одной и той же версии Django/ приложения.

Не кодируйте свои URL жестко!

Вместо этого используйте имена URL, а reverse Функция, чтобы получить сам URL.

Когда вы определяете свои сопоставления URL-адресов, присвойте им имена.

urlpatterns += ('project.application.views'
   url( r'^something/$', 'view_function', name="url-name" ),
   ....
)

Убедитесь, что имя уникально для каждого URL.

У меня обычно есть согласованный формат "project-appplication-view", например "cbx-forum-thread" для представления потока.

ОБНОВЛЕНИЕ (бесстыдно крадет дополнение аяза):

Это имя может использоваться в шаблонах с url тег.

Используйте панель инструментов отладки django. Например, он позволяет просматривать все запросы SQL, выполняемые во время рендеринга, и вы также можете просматривать трассировку стека для любого из них.

Не пишите свои собственные страницы входа. Если вы используете django.contrib.auth.

Настоящий, грязный секрет заключается в том, что если вы также используете django.contrib.admin и django.template.loaders.app_directories.load_template_source есть в ваших загрузчиках шаблонов, вы также можете получить свои шаблоны бесплатно!

# somewhere in urls.py
urlpatterns += patterns('django.contrib.auth',
    (r'^accounts/login/$','views.login', {'template_name': 'admin/login.html'}),
    (r'^accounts/logout/$','views.logout'),
)

Контекстные процессоры потрясающие.

Скажем, у вас другая модель пользователя, и вы хотите включить ее в каждый ответ. Вместо этого:

def myview(request, arg, arg2=None, template='my/template.html'):
    ''' My view... '''
    response = dict()
    myuser = MyUser.objects.get(user=request.user)
    response['my_user'] = myuser
    ...
    return render_to_response(template,
                              response,
                              context_instance=RequestContext(request))

Контекстные процессы дают вам возможность передавать любую переменную в ваши шаблоны. Я обычно ставлю свой в 'my_project/apps/core/context.py:

def my_context(request):
    try:
        return dict(my_user=MyUser.objects.get(user=request.user))
    except ObjectNotFound:
        return dict(my_user='')

В вашем settings.py добавьте следующую строку в ваш TEMPLATE_CONTEXT_PROCESSORS

TEMPLATE_CONTEXT_PROCESSORS = (
    'my_project.apps.core.context.my_context',
    ...
)

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

Также сигналы выигрывают.

Я написал пост в блоге об этом несколько месяцев назад, так что я просто собираюсь вырезать и вставить:

Из коробки Django дает вам несколько невероятно полезных сигналов. У вас есть возможность делать что-то до и после сохранения, инициализации, удаления или даже во время обработки запроса. Итак, давайте отойдем от концепций и продемонстрируем, как они используются. Скажем, у нас есть блог

from django.utils.translation import ugettext_lazy as _
class Post(models.Model):
    title = models.CharField(_('title'), max_length=255)
    body = models.TextField(_('body'))
    created = models.DateTimeField(auto_now_add=True)

Таким образом, вы захотите уведомить одну из многих служб pinging для блогов, о которых мы сделали, новое сообщение, перестроить кеш самых последних сообщений и написать в Твиттере об этом. Хорошо с сигналами у вас есть возможность делать все это без добавления каких-либо методов в класс Post.

import twitter

from django.core.cache import cache
from django.db.models.signals import post_save
from django.conf import settings

def posted_blog(sender, created=None, instance=None, **kwargs):
    ''' Listens for a blog post to save and alerts some services. '''
    if (created and instance is not None):
        tweet = 'New blog post! %s' instance.title
        t = twitter.PostUpdate(settings.TWITTER_USER,
                               settings.TWITTER_PASSWD,
                               tweet)
        cache.set(instance.cache_key, instance, 60*5)
       # send pingbacks
       # ...
       # whatever else
    else:
        cache.delete(instance.cache_key)
post_save.connect(posted_blog, sender=Post)

Теперь мы определяем эту функцию и используем сигнал post_init для подключения функции к модели Post и выполнения ее после сохранения.

Когда я только начинал, я не знал, что существует Paginator, убедитесь, что вы знаете о его существовании!!

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

from IPython.Shell import IPShellEmbed; IPShellEmbed()()

Затем обновите страницу, перейдите в окно вашего сервера запуска, и вы попадете в интерактивное окно IPython.

У меня есть фрагмент, настроенный в TextMate, поэтому я просто набираю ipshell и нажимаю вкладку. Я не мог жить без этого.

Запустите SMTP-сервер разработки, который будет просто выводить все, что отправлено на него (если вы не хотите фактически устанавливать SMTP на свой dev-сервер).

командная строка:

python -m smtpd -n -c DebuggingServer localhost:1025

Из документации django-admin:

Если вы используете оболочку Bash, рассмотрите возможность установки сценария завершения bash Django, который находится в extras/django_bash_completion в распределении Джанго. Это позволяет завершить вкладку django-admin.py а также manage.py команды, так что вы можете, например...

  • Тип django-admin.py,
  • Нажмите [TAB], чтобы увидеть все доступные опции.
  • Тип sql, затем [TAB], чтобы увидеть все доступные опции, имена которых начинаются с sql,

./manage.py runserver_plus Facilty, который поставляется с django_extensions, действительно потрясающий.

Он создает расширенную страницу отладки, которая, помимо прочего, использует отладчик Werkzeug для создания интерактивных консолей отладки для каждой точки в стеке (см. Скриншот). Это также обеспечивает очень удобный метод отладки dump() для отображения информации об объекте / кадре.

Для установки вы можете использовать pip:

pip install django_extensions
pip install Werkzeug

Затем добавьте 'django_extensions' на ваш INSTALLED_APPS кортеж в settings.py и запустите сервер разработки с новым расширением:

./manage.py runserver_plus

Это изменит способ отладки.

При попытке обмена данными между Django и другим приложением, request.raw_post_data хороший друг Используйте его для получения и пользовательской обработки, скажем, данных XML.

Документация: http://docs.djangoproject.com/en/dev/ref/request-response/

Мне нравится использовать отладчик Python pdb для отладки проектов Django.

Это полезная ссылка для изучения того, как его использовать: http://www.ferg.org/papers/debugging_in_python.html

Используйте Jinja2 вместе с Django.

Если вы находите язык шаблонов Django чрезвычайно ограничивающим (как я!), Вам не нужно зацикливаться на нем. Django является гибким, и язык шаблонов слабо связан с остальной частью системы, поэтому просто подключите другой язык шаблонов и используйте его для отображения ваших ответов http!

Я использую Jinja2, это почти как расширенная версия языка шаблонов django, он использует тот же синтаксис и позволяет использовать выражения в операторах if! больше не нужно создавать собственные if-теги, такие как if_item_in_list! ты можешь просто сказать %{ if item in list %}, или же {% if object.field < 10 %},

Но это не все; у него есть много других функций, облегчающих создание шаблонов, но я не могу их здесь описать.

Добавлять assert False по вашему мнению, код для выгрузки отладочной информации.

Это добавляет к ответу выше об именах URL Django и обратной рассылке URL.

Имена URL также могут быть эффективно использованы в шаблонах. Например, для данного шаблона URL:

url(r'(?P<project_id>\d+)/team/$', 'project_team', name='project_team')

Вы можете иметь следующее в шаблонах:

<a href="{% url project_team project.id %}">Team</a>

Поскольку "представления" Django должны быть только вызываемыми, которые возвращают HttpResponse, вы можете легко создавать представления на основе классов, как в Ruby on Rails и других средах.

Есть несколько способов создания представлений на основе классов, вот мой любимый:

from django import http

class RestView(object):
    methods = ('GET', 'HEAD')

    @classmethod
    def dispatch(cls, request, *args, **kwargs):
        resource = cls()
        if request.method.lower() not in (method.lower() for method in resource.methods):
            return http.HttpResponseNotAllowed(resource.methods)
        try:
            method = getattr(resource, request.method.lower())
        except AttributeError:
            raise Exception("View method `%s` does not exist." % request.method.lower())
        if not callable(method):
            raise Exception("View method `%s` is not callable." % request.method.lower())
        return method(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        return http.HttpResponse()

    def head(self, request, *args, **kwargs):
        response = self.get(request, *args, **kwargs)
        response.content = ''
        return response

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

Как только вы настроите свои представления, ваш urls.py будет выглядеть примерно так:

from django.conf.urls.defaults import *
from views import MyRestView

urlpatterns = patterns('',
    (r'^restview/', MyRestView.dispatch),
)

Вместо того, чтобы использовать render_to_response чтобы связать ваш контекст с шаблоном и отобразить его (именно это обычно показывают документы Django), используйте общий вид direct_to_template, Это делает то же самое, что render_to_response делает, но также автоматически добавляет RequestContext в контекст шаблона, неявно позволяя использовать контекстные процессоры. Вы можете сделать это вручную, используя render_to_response а зачем? Это просто еще один шаг, чтобы запомнить и еще один LOC. Помимо использования контекстных процессоров, наличие RequestContext в вашем шаблоне позволяет вам делать такие вещи, как:

<a href="{{MEDIA_URL}}images/frog.jpg">A frog</a> 

что очень полезно. На самом деле +1 на общие взгляды в целом. Документы Django в основном показывают их как ярлыки, даже не имея файла views.py для простых приложений, но вы также можете использовать их в своих собственных функциях просмотра:

from django.views.generic import simple

def article_detail(request, slug=None):
    article = get_object_or_404(Article, slug=slug)
    return simple.direct_to_template(request, 
        template="articles/article_detail.html",
        extra_context={'article': article}
    )

У меня недостаточно репутации, чтобы ответить на рассматриваемый комментарий, но важно отметить, что если вы собираетесь использовать Jinja, он НЕ поддерживает символ "-" в именах блоков шаблона, в то время как Django делает. Это вызвало у меня много проблем и потраченное время, пытаясь отследить очень неясное сообщение об ошибке, которое оно генерировало.

Все знают, что есть сервер разработки, который вы можете запустить с помощью "manage.py runserver", но знаете ли вы, что существует также представление разработки для обслуживания статических файлов (CSS / JS / IMG)?

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

Но при разработке вы можете не захотеть устанавливать Apache + mod_wisgi, это тяжело. Затем вы можете просто добавить следующее в urls.py:

(r'^site_media/(?P<path>.*)$', 'django.views.static.serve',
        {'document_root': '/path/to/media'}),

Ваш CSS / JS / IMG будет доступен по адресу www.yoursite.com/site_media/.

Конечно, не используйте его в производственной среде.

django.db.models.get_model позволяет вам получить модель, не импортируя ее.

Джеймс показывает, насколько это удобно: "Советы Django: лучше напишите теги шаблона - Итерация 4".

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

{% load webdesign %}
{% lorem 5 p %}

Я узнал об этом из документации для приложения sorl-thumbnails. Вы можете использовать ключевое слово "as" в тегах шаблона, чтобы использовать результаты вызова в другом месте вашего шаблона.

Например:

{% url image-processor uid as img_src %}
<img src="{% thumbnail img_src 100x100 %}"/>

Это упомянуто мимоходом в документации шаблона тега Django, но только в отношении циклов. Они не кричат, что вы можете использовать это в другом месте (где угодно?).

PyCharm IDE - хорошая среда для написания кода и особенно для отладки со встроенной поддержкой Django.

django.views.generic.list_detail.object_list - предоставляет все логические и шаблонные переменные для разбиения на страницы (одна из тех, что я написал, что это тысяча раз, теперь дружеские отношения). Обертывание позволяет учесть любую логику, которая вам нужна. Этот драгоценный камень сэкономил мне много часов на отладку отдельных ошибок на моих страницах "Результаты поиска" и в процессе делает код более чистым.

Используйте xml_models для создания моделей Django, которые используют бэкэнд XML REST API (вместо SQL). Это очень полезно, особенно при моделировании сторонних API - вы получаете тот же синтаксис QuerySet, к которому вы привыкли. Вы можете установить его из PyPI.

XML из API:

<profile id=4>
    <email>joe@example.com</email>
    <first_name>Joe</first_name>
    <last_name>Example</last_name>
    <date_of_birth>1975-05-15</date_of_birth>
</profile>

А теперь в питоне:

class Profile(xml_models.Model):
    user_id = xml_models.IntField(xpath='/profile/@id')
    email = xml_models.CharField(xpath='/profile/email')
    first = xml_models.CharField(xpath='/profile/first_name')
    last = xml_models.CharField(xpath='/profile/last_name')
    birthday = xml_models.DateField(xpath='/profile/date_of_birth')

    finders = {
        (user_id,):  settings.API_URL +'/api/v1/profile/userid/%s',
        (email,):  settings.API_URL +'/api/v1/profile/email/%s',
    }

profile = Profile.objects.get(user_id=4)
print profile.email
# would print 'joe@example.com'

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

(Отказ от ответственности: хотя я не являюсь автором этой библиотеки, я теперь коммиттер, сделавший несколько незначительных коммитов)

Используйте миграцию базы данных. Используйте Юг.

Другие вопросы по тегам