четверг, 3 сентября 2009 г.

Тонкости программирования Django для новичков

Вчера наткнулся на статью Rama Vadakattu Top 10 tips to a new django developer о том что должны знать программисты новички на Django. Мой опыт не так велик в Django, но что бы собрать подобные знания и выработать навыки понадобился прочтение не одной умной статьи. Не со всеми советами я согласен, но каждый программист Django должен знать описанные моменты. Советую прочитать оригинал, ну а "ленивым" полезно будет дочитать до конца.

1. Не указывайте имя проекта в импорте

Предположим что у вас есть приложение "vasya" в проекте "my" не указывайте следующим образом

from my.vasya.models import Hero

Вы не сможете повторно использовать это приложение, а сменить имя проекта будет сущей проблемой. Сделайте так:

from vasya.models import Hero

Ну а для сохранения работоспособности необходимо добавить в пути питона директорию вашего проложения следующим образом:

import syssys.path.insert(0, <путь к папкам app>)

Не программируйте жестко пути MEDIA_ROOT и TEMPLATE_DIRS

Не присваивайте следующим образом параметры MEDIA_ROOT и TEMPLATE_DIRS в файле setting.py:

TEMPLATE_DIRS = ("/home/html/project/templates")
MEDIA_ROOT = "/home/html/project/appmedia/"

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

SITE_ROOT = os.path.realpath(os.path.dirname(__file__))
MEDIA_ROOT = os.path.join(SITE_ROOT, 'appmedia')
TEMPLATE_DIRS = os.path.join(SITE_ROOT, 'templates')

Техника от Rob Hudson, детальная инфомация по следующей ссылке.

Не программируйте жестко пути к статическим файлам

Когда вам нужно сделать ссылку на статические ресурсы(javascript, css, картинки) не пользуйтесь следующим способом (MEDIA_URL = “/appmedia/”):

<link rel="stylesheet" type="text/css" href="/appmedia/wysiwyg/jHtmlArea.css" /><script type="text/javascript" src="/appmedia/wysiwyg/jHtmlArea.js"></script>

Проблема появится тогда, когда вы захотите перенести статические ресурсы на другой сервер. Избавится от нее вам поможет использование переменной {{MEDIA_URL}} которой необходимо присвоить значение "/appmedia/" в файле settings.py:

<link rel="stylesheet" type="text/css" href="{{MEDIA_URL}}wysiwyg/jHtmlArea.css" /><script type="text/javascript" src="{{MEDIA_URL}}wysiwyg/jHtmlArea.js"></script>

А как же получить переменные окружения(сontext variable)?
Просто :). Что бы добавить переменные(например, пользователя или запрашиваемую страницу) в шаблон воспользуйтесь добавлением RequestContext(request) в метод render_to_response:

return render_to_response("my_app/my_template.html", {'some_var': 'foo'}, context_instance=RequestContext(request))

Подробная информация.

Не пишите бизнес логику в функциях представлений

Не очень хорошая идея писать бизнес логику в представлениях (например, логика добавляющая сумму P на ваш банковский счет X, и отнимающая P с вашего счета Y.)

Вы спросите почему?
1. Нет возможности написать unit тесты.
2. Нет возможности повторного использования кода.

Так куда помещать такую логику?
Хорошей идеей будет поместить ее в модель или в дополнительную функцию.

Менять DEBUG=False при переносе версии на рабочий сайт нудно

Часто мы забываем изменить DEBUG на значение False при переносе вернии на рабочий сайт. Да и нужно это.

Исправить эту ситуацию можно 2-я способами:
1. Проверять на имя домена следующим образом:

import socketif socket.gethostname() == 'productionserver.com':  DEBUG = Falseelse:  DEBUG = True

Первым озвучил ее Jokull. Подробнаи информация.

2. Использовать дополнительный файл конфигурации для локальной среды разработки, в котором и можно переопределить все дополнительные параметры.

#Filename settings_debuy.py
#It contains all variables from settings and it overrides the DEBUG variable to True
#we use settings_debug.py to run the server locally python manage.py runserver settings=settings_debug.pyfrom settings import *DEBUG = True
#you can also add other things which helps you to do the debugging easily
#like Debug toolbar etc...

Детальная информация

Загружать теги шаблонов сторонних приложений один раз

Перед использованием тегов в шаблонах необходимо сделать:

{% load template_tags %}

Данный код мы должны прописать в каждом шаблоне в котором мы хотим использовать данные теги. Исправить это мы можем добавив следующий код:

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

Поместите этот код в любой файл который загружается на старте приложения(settings.py,urls.py,любой файл models.py в приложениях). Это позволит использовать данные теги без объявления загрузок в шаблонах.

Urls.py

Не описывайте все вашии урлы в project/urls.py

urlpatterns = patterns('',
     url(r'^askalumini/question/$','.....registerInstitution',name='iregister'),
     url(r'^askalumin/answer/$','someview.....',name='newmemberurl'),
     url(r'^institution/member/$','someview.....',name="dashboardurl"),
     url(r'^institution/faculty/$','editInstitute',name="editinstituteurl"),
     url(r'^memeber/editprofile/$','editProfile',name="editprofileurl"),
     url(r'^member/changepassword/$','changePassword',name="changepasswordurl"),
     url(r'^member/forgotpassword/$','forgotPassword',name="forgotpasswordurl"),
     url(r'^member/changepicture/$','changePicture',name="changepictureurl"),
     url(r'^member/logout/$','memeberlogout',name="logouturl"),
)

Следующий код позволить вам реализовывать приложения многократно. В файле project/urls.py описываем следующим образом:

urlpatterns = patterns('',
     # Example:
     (r'^$', include('institution.urls')),
     (r'^institution/', include('institution.urls')),
     (r'^askalumini/', include('askalumini.urls')),
     (r'^member/', include('member.urls'))
)

а в каждом приложении так же создайте файлы urls.py и пропишите соответствующие url-ы в каждом из них(пример для приложения askalumini)

urlpatterns = patterns('askalumini.views',
     url(r'^$','askHome',name='askaluminiurl'),
     url(r'^questions/(?P\d+)/$', 'displayQuestion', name= 'askquestiondisplay'),
     url(r'^askquestions/$','askQuestion',name='askquestionurl'),
     url(r'^postcomment/$','postComment',name="askquestioncomment")
)

Используйте наименование Url-ов для идентификации

При описании урлов мы указали параметр name. Данное наименование поможет разумно формировать url в моделях, представлениях и шаблонах.

Не программируйте жестко url-ы

Почему?

Если вы измените структуру урлов в файле url.py вам понадобится сделать такие же изменения во всех местах где они были использованы.

view.py

Вместо того что бы жестко прописать урл следующим образом

HttpResponseRedirect("/askalumini/questions/54")

используйте функцию reverse

from django.core.urlresolvers
import reverse

HttpResponseRedirect(reverse('askquestiondisplay', kwargs{'questionno':q.id}))

models.py

В файле models.py к дополнению функции reverse вы также можете использовать models.permalink декоратор.

@models.permalinkdef
 get_absolute_url(self):
     return ('profileurl2',(),{'userid': self.user.id})

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

templates.py

В шаблонах вы можете воспользоваться тегом url

{% url askquestiondisplay  345 %} Ask Question 

Отладка

а) Воспользуйтесь django-debug-toolbar для доступа к следующей информации:
1. Сколько sql запросов выполняется? За какое время?
2. Имя шаблона, логгирование, куки/сессия и т.д.
Описание всех возможностей можно найти по следующей ссылке

б) Воспользуйтесь отладчиком Werkzeug, который позволит открыть консоль python-а на странице отображения ошибки и поможет быстро найти ошибку.
Детальная информация

в) Используйте полезной утилитой для отладки, pdb.

Если знаете про Pinax используйте его

Django способствует повторному использованию приложений. Pinax - проект который включает уже инфраструктуру повторно используемых приложений.
В одно время я попытался его использовать так как есть. Интересное интеграционное решение, являющееся деревом разнообразных многократно используемых проектов. Не понравилось только то, что этим "ящиком с приложениями" тяжело управлять. Попробуйте исключить пару ненужных модулей и сразу будет понятно, что все же интеграция получилась слишком тесной.

Для более детальной информации обратитесь на сайт разработчиков http://pinaxproject.com/.

Необходимо знать и о других приложениях

1. Миграция

Как изменять версию приложения/БД на сайте при появлении следующих версий проекта в котором уже изменилась структура приложения/БД? Этот процесс и называется миграцией.
Есть несколько приложений которые вам помогут в этом:
- django-evolutions - легкая в использовании, все делает автоматически, но не надежна
- South - более надежна, но необходимо будет разбираться.

2. Шаблоны

Если вы считаете что язык шаблонов Django очень узкий тогда вы можете воспользоваться следующими:
- template-utils
- Jinja

3. Другие приложения

- django command extensions
- Sorl

Нашли что то новое узнали для себя?

Комментариев нет:

Отправить комментарий