Comments 65
Радует что Django в последнее время набирает обороты. Причем вполне заслужено.
Сейчас, правда, все немного замерли в ожидании релиза 1.7.
А статью в закладки и перечитать еще несколько раз.
Сейчас, правда, все немного замерли в ожидании релиза 1.7.
А статью в закладки и перечитать еще несколько раз.
Я настройки храню в отдельных файлах в подмодуле `settings`. Просто чтобы было чуть больше порядка.
Общие настройки — в settings/base.py, а в деве-стейджинге-продакшне делаю немного некошерно, но для настроек — самое оно:
Общие настройки — в settings/base.py, а в деве-стейджинге-продакшне делаю немного некошерно, но для настроек — самое оно:
from .base import *
# отличающиеся настройки
То есть у вас в settings.py хранятся только отличающиеся настройки? Как тогда решается проблема с системой контроля версий? (На продакшне одни settings.py, на деве — другие)
Мы делаем похожее, поэтому отвечу за 404.
В settings.py определены все настройки для боевого сервера.
Затем есть settings_local.py, который импортирует все с settings.py (from settings import *) и переопределяет необходимое, чтобы работало на local.
А сам сервер на локалке, например запускается с дополнительным параметром --settings=settings_local
Тоже самое с settings_dev.py (и другими версиями).
Таким образом на боевом все с одного файла без наследований, переопределений и импорта. На dev и local — наследование и переопределение. При этом все есть в нашем git, не нужно писать исключений и удалять настроечные файлы.
Для нас наиболее оптимальный вариант.
В settings.py определены все настройки для боевого сервера.
Затем есть settings_local.py, который импортирует все с settings.py (from settings import *) и переопределяет необходимое, чтобы работало на local.
А сам сервер на локалке, например запускается с дополнительным параметром --settings=settings_local
Тоже самое с settings_dev.py (и другими версиями).
Таким образом на боевом все с одного файла без наследований, переопределений и импорта. На dev и local — наследование и переопределение. При этом все есть в нашем git, не нужно писать исключений и удалять настроечные файлы.
Для нас наиболее оптимальный вариант.
У меня вообще нет settings.py (при наличии модуля settings и settings.py у питона просто сорвёт крышу.
При старте сервера (runserver, wsgi — не важно) просто указываются нужное значение в $DJANGO_SETTINGS_MODULE (my_project.settings.productiuon, например).
При старте сервера (runserver, wsgi — не важно) просто указываются нужное значение в $DJANGO_SETTINGS_MODULE (my_project.settings.productiuon, например).
А в чём профит?
Профит в том, что получается минимум копипасты.
Ну подождите. У вас же всё равно есть эти файлы my_project.settings.production и my_project.settings.development. Какая разница, включать из «запускатора» или из settings.py?
|-project
|--settings
|---__init__.py
|---base.py
|---ci.py
|---dev.py
|---production.py
|---staging.py
Во-первых, окружений может быть больше чем два, и тогда трюк с ImportError не прокатит, ну или надо будет делать многовложенные try-except.
Во-вторых, разработчиков может быть больше, чем один, и желательно иметь возможность синхронизировать их dev-окружения. Тут .gitignore нам всё поломает.
В-третьих, бОльшая часть настроек (INSTALLED_APPS, менеджеры контекста, мидлвари) — общие для всех окружений. Поэтому имеет смысл держать их в одном месте, коим и является base.py.
В two scoops of django читал про другой подход: версионируются абсолютно все настройки (settings/prod.py, settings/dev.py и т.д). А всякие SECRET_KEY, пароли от БД и т.д выносятся в переменные окружения.
Для «add_class»-функциональности (и прочих полезных штук для работы с формами) рекомендую django-widget-tweaks.
но при повторном использовании приложений в других проектах приходилось менять пути импорта
можно например использовать относительные импорты
Вы немного не поняли. Создайте django-admin.py startproject one, django-admin startproject two, и попытайтесь импортировать settings.py. Для первого проекта будет from one import settings, для второго from two import settings. Относительные пути не спасут.
P.s. Пример надуманный. Разумеется, по-хорошему from django.conf import settings.
P.s. Пример надуманный. Разумеется, по-хорошему from django.conf import settings.
Просто не нужно такие(переносимые) приложения «складывать» в ту же директорию где и settings.py. Кстати емнип «дефолтную» структуру проекта обновили в одной из крайних версий.
Тогда в проекте вместо такого импорта с именем проекта
будет возможен например такой импорт
вот еще как пример можно посмотреть github.com/django/djangoproject.com
p.s. по крайней мере у меня это нормально работает
p.p.s. хотя в статье у Вас указана нормальная структура(с приложениями в «корневой» директории, рядом с manage.py), тогда не понятно откуда проблема с импортами
Тогда в проекте вместо такого импорта с именем проекта
from project_one.news.models import Model
будет возможен например такой импорт
from news.models import Model
вот еще как пример можно посмотреть github.com/django/djangoproject.com
p.s. по крайней мере у меня это нормально работает
p.p.s. хотя в статье у Вас указана нормальная структура(с приложениями в «корневой» директории, рядом с manage.py), тогда не понятно откуда проблема с импортами
Я вас понял :) У меня эти мысли с унификацией названий проектов появились по нескольким причинам:
1. Я складываю все глобальные утилиты туда же, где и settings.py, в project/project. Например, project/project/templatetags/add_class.py. По мне, так это логично — всё, что применимо ко всему проекту — в основную папку проекта. Вы сейчас предложете вынести всё это в новое приложение utils — и будете тоже правы. Дело вкуса, имхо.
2. Когда на разных проектах одинаковые пути — это сильно облегчает жизнь, проверено. Лично я теперь не зависаю на cd, вспоминая имя проекта.
1. Я складываю все глобальные утилиты туда же, где и settings.py, в project/project. Например, project/project/templatetags/add_class.py. По мне, так это логично — всё, что применимо ко всему проекту — в основную папку проекта. Вы сейчас предложете вынести всё это в новое приложение utils — и будете тоже правы. Дело вкуса, имхо.
2. Когда на разных проектах одинаковые пути — это сильно облегчает жизнь, проверено. Лично я теперь не зависаю на cd, вспоминая имя проекта.
<irony>У вас слишком расистская статья, слишком много упоминаний рабства.</irony>
Называйте ваш проект project (django-admin.py startproject project) — ну или другим, но одинаковым именем для всех проектов. Раньше я называл проекты соответственно домену, но при повторном использовании приложений в других проектах приходилось менять пути импорта — то from supersite import utils, то from newsite import utils. Это путает и отвлекает.Это вообще странно. Та структура каталогов, что у вас ниже нарисована вообще не подразумевает, что в импорты попадёт «название проекта». Их туда вообще не нужно включать, т.к. в пути надо включать именно внутренность этой папки проекта (которая вообще неважно как называется), потому непонятно как и зачем оно в импорты попадёт. Названия «основных приложений» как раз, имхо, надо делать разными. Это удобно, например, если несколько таких «основных приложений» рядом надо где-то положить. Для этого к такому виду и было приведено, емнип, в версии 1.4. До этого внутренности были снаружи и там действительно бывали проблемы с повторным использованием и импортами.
Лично я внутренности того что вы называете «папки с проектом» вытаскиваю в корень внешней вашей «папки сайта». Потому что эта лишняя вложенность там не особо нужна.
Добавлю пару замечаний:
— Приложения достаточно удобно хранить в отдельной директории, например, apps.
— Шаблоны имеет смысл хранить все вместе, но отдельно от приложений (т.е. выделить под все шаблоны отдельную директорию). Такая структура подталкивает хранить шаблоны в структуре app_name/tmpl_name и коллизии сразу видны на глаз. Кроме того шаблоны обычно уникальны для каждого проекта (в отличие от приложений, которые полностью или частично реюзабельны), а если шаблон универсальный то вообще имеет смысл задуматься о создании пакета.
— Приложения достаточно удобно хранить в отдельной директории, например, apps.
— Шаблоны имеет смысл хранить все вместе, но отдельно от приложений (т.е. выделить под все шаблоны отдельную директорию). Такая структура подталкивает хранить шаблоны в структуре app_name/tmpl_name и коллизии сразу видны на глаз. Кроме того шаблоны обычно уникальны для каждого проекта (в отличие от приложений, которые полностью или частично реюзабельны), а если шаблон универсальный то вообще имеет смысл задуматься о создании пакета.
Есть такой замечательный продукт django-cms.
Расписывать все прелести не буду, вкратце — CMS на Django =)
Расписывать все прелести не буду, вкратце — CMS на Django =)
Простите, не удержался
Так, господа, я тут не для холивара или для рекламы ссылочку оставил. А для того, чтобы незнающие смогли узнать о наличии таковой CMS.
Недавно смотрел Django-CMS и видяшку на ютубе где аффтар утверждает «Friends don't let friends use Drupal». Но вот как раз в плане CMS-нутости, ИМХО Drupal даст Django-CMS огромную фору, т.к. механизм CCK+Views+Panels это реально мощный конструктор. В Django-CMS ничего такого не нашел. Как унифицированная простейшая CMS-ка пойдет, но не имеет ИМХО большого смысла. Заказчик чаще всего не хочет изучать все эти менюшки и настройки, он хочет зайти в админку и увидеть большую красную кнопку — «PROFIT». А для этого админку требуется сделать под заказчика и Django-CMS тут совсем не помогает +))
P.S: Сам долго юзал Drupal, но последний год использую Django, ибо в работе черезчур уникальные для Drupal-а вещи +))
P.S: Сам долго юзал Drupal, но последний год использую Django, ибо в работе черезчур уникальные для Drupal-а вещи +))
Drupal — PHP, Django (-cms) — Python, и вообще речь в топике не об этом)
Клиенту, естественно, хочется иметь такую кнопку, кто ж такую не хочет)) как только такая `работающая` появится — закажу себе парочку.
Клиенту, естественно, хочется иметь такую кнопку, кто ж такую не хочет)) как только такая `работающая` появится — закажу себе парочку.
{% include 'slave.html' %}
{% include 'slave.html' with var=var %}
И никакие они не медленные. При частом обращении ФС поместит файл в память и будет все нормально. Вдвойне неактуально во времена ssd vps. У меня основной шаблон так весь в инклудах, потому как редактировать простыни, где нужный код находится в 40-х отступах от левого края совсем неудобно. И в cvs красота — видно, что правили
footer.html
, а не ничего говорящее base.html
.pre_save
Есть еще Django Dirty Fields — неизменная специя к большинству моих моделей (автор идеи сам Armin!). Умеет так:
class TestModel(DirtyFieldsMixin, models.Model):
boolean = models.BooleanField(default=True)
>>> tm = TestModel(boolean=True,characters="testing")
>>> tm.save()
>>> tm.boolean = False
>>> tm.is_dirty()
True
>>> tm.get_dirty_fields()
{'boolean': True}
а для чего такое можно использовать?
Чаще всего я его использую в связке с mptt, т.к. предпочитаю хранить урлы категорий в базе:
Ключевое тут поле
class TreeModel(MPTTModel, DirtyFieldsMixin):
parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
title = models.CharField(max_length=100)
slug = models.SlugField(max_length=70, db_index=True, unique=True)
path = models.CharField(max_length=255, editable=False, unique=True, db_index=True)
Ключевое тут поле
path
— оно хранит адрес предков: /parent/parent/child/
, и при сохранении предка надо это поле обновить у всех детей вниз по иерархии. А чтобы не дергать базу просто так, при сохранении модели я проверяю, изменилось ли поле slug и если да, обновляю его у всех детей.def save(self, *args, **kwargs):
self.path = self.slug
if self.parent:
self.path = '{}/{}'.format(self.parent.path, self.slug)
# Надо сохранить модель прежде, чем браться за детей, чтобы записать path,
# но после вызова super.save память о старых полях потрется,
# поэтому надо запомнить состояние
is_dirty = 'path' in self.get_dirty_fields()
super(TreeModel, self).save(*args, **kwargs)
# Если изменение поля было, пускаем рекурсию — каждый child запустит свою проверку
if is_dirty:
for child in self.get_children():
child.save()
Спасибо.
Я называю инклюды медленными, потому что в своё время делал
Замена include сделала приложение быстрее.
А ещё коварный include не ругнётся, если вы забудете передать какую-либо переменную в его контекст, а inclusion tag ругнётся. Так что лично я не любитель инклюдов, хотя и пользуюсь ими иногда для разбивки полотна html на несколько мелких кусочков, не нуждающихся в контексте, например, {% include 'google_analytics.html' %}.
Я называю инклюды медленными, потому что в своё время делал
{% for item in items %}
{% include 'item_description.html' %}
{% endfor %}
Замена include сделала приложение быстрее.
А ещё коварный include не ругнётся, если вы забудете передать какую-либо переменную в его контекст, а inclusion tag ругнётся. Так что лично я не любитель инклюдов, хотя и пользуюсь ими иногда для разбивки полотна html на несколько мелких кусочков, не нуждающихся в контексте, например, {% include 'google_analytics.html' %}.
Я и сейчас так делаю. Это от проекта зависит: если кусочек не маленький и это противоречит DRY (в разумных рамках: большой шаблон, много условий и т.д.)
Вот как это легко решается:
Если item изменится, он тут же обновит кеш, а старый сам протухнет со временем.
Да прибудет с вами django-chunks!
Вот как это легко решается:
{% for item in items %}
{% cache 1800 list_item item.id item.modified %}
{% include 'item_description.html' %}
{% endcache %}
{% endfor %}
Если item изменится, он тут же обновит кеш, а старый сам протухнет со временем.
{% include 'google_analytics.html' %}
Да прибудет с вами django-chunks!
Но в данном случае переменная var передаётся в шаблон slave.html неявно — var передатся в master.html, а slave.html просто «цепляет» контекст master'а. Таким образом, мы видим, что шаблон внутри {% include %} зависит от контекста основного шаблона. Мы вынуждены следить за контекстом родительского шаблона, иначе в дочерний может попасть что-нибудь не то.
Решается параметром
only
:If you want to render the context only with the variables provided (or even no variables at all), use the only option. No other variables are available to the included template:
{% include "name_snippet.html" with greeting="Hi" only %}
Неплохой скелет проекта — django-skel.readthedocs.org/en/latest/, github.com/rdegges/django-skel
Еще можно описывать настройки для всех окружений в settings.py с помощью модуля django-configurations. Очень удобно если больше двух окружений.
Мне больше нравится этот вариант, он проще
Вместо virtualenv удобней использовать virtualenvwrapper.
Также в Python 3.4 есть встроенное виртуальное окружение.
Также в Python 3.4 есть встроенное виртуальное окружение.
Не раз встречал импорт local_settings в начале settings.py, как описано в вашей статье. Честно говоря, не понимаю почему в начале, а не в конце. Суть в том, что вам может понадобится что-либо переопределить. Ну предположим, что в settings.py DEBUG=False и вот как ни крути local_settings, если он подключен в начале, дебаг вы не включите. А вот если делаете импорт в конце, то можете переопределять в local_settings всё, что душе угодно не трогая никак settings.py.
А DEBUG в settings.py не нужен. Не забудете потом, что и где вы переопределили?
Ну про DEBUG, наверное, плохой пример, но, например, можно к INSTALLED_APPS добавлять debug_toolbar или ещё чего там может пригодиться для тестирования. Можно просто в local_settings сделать INSTALLED_APPS += ('debug_toolbar', ) и всё. Мне кажется это удобным.
А можно в settings.py сделать
:)
Можно и переопределять, конечно. Но тогда у вас одна опция одновременно хранится в разных файлах… А ведь явное лучше неявного.
if DEBUG:
INSTALLED_APPS += ...
:)
Можно и переопределять, конечно. Но тогда у вас одна опция одновременно хранится в разных файлах… А ведь явное лучше неявного.
Можно, да. Но костыль же. Тем более, если не определить в local_settings INSTALLED_APPS, будет фейл. Но, тут, конечно, можно ещё проверять существование свойства. :) Я на самом деле интересовался не спора ради, а просто, мало ли — есть какие-то причины на то. Но пока я останусь при своём мнении.
Старайтесь не писать {% url 'shop/product' id=product.id %}.
Почему?
Если вы решите потом изменить способ адресации к объекту, то придётся везде заменять теги {% url %}. Пример из моей практики: раньше адреса были вида /shop/product/<id товара>/, но потом пришли сеошники и заставили привести адреса к такому: /shop/product/<slug товара>/. Пришлось во всём проекте заменять {% url 'shop/product' id=product.id %} на {% url 'shop/product' slug=product.slug %}. Если бы я использовал везде get_absolute_url, то было бы достаточно изменить лишь этот метод.
Но ведь это работает только с урлами, однозначно сопоставленными с моделями. Что с остальными делать?
Ничего не делать с ними. Хардкодить {% url 'contacts' %}, по-другому никак.
Подробнее, зачем нужен get_absolute_url, хорошо написано на djangoproject.com.
Подробнее, зачем нужен get_absolute_url, хорошо написано на djangoproject.com.
1) Действительно ли inclusion tags работают быстрее {% include %}?
2) Beautiful soup адово течет, лучше использовать lxml
Дополню пост: есть замечательный апп django-devserver
2) Beautiful soup адово течет, лучше использовать lxml
Дополню пост: есть замечательный апп django-devserver
1) К сожалению, со 100% уверенностью сказать не могу. В моей практике рендериться с inclusion tag быстрее.
2) BS позволяет указать в качестве бэкенда lxml. По умолначию он использет дефолтный html.parser, который до версии питона 2.7.3 был корявым. Если вы имеете в виду, что течёт сам BS, то буду признателен за пруфлинк.
2) BS позволяет указать в качестве бэкенда lxml. По умолначию он использет дефолтный html.parser, который до версии питона 2.7.3 был корявым. Если вы имеете в виду, что течёт сам BS, то буду признателен за пруфлинк.
1. Обязательно включать кеширование шаблонов — оно доступно из коробки
2. Для разбития сеттингсов есть хорошая батарейка github.com/2general/django-split-settings
2. Для разбития сеттингсов есть хорошая батарейка github.com/2general/django-split-settings
Кэширование — зверь, которого надо уметь готовить. Лучше так: в разработке кэш отключать вообще, но обязательно соблюдать завершающую стадию «а теперь включим кэш», в тестах проверять-проверять-проверять!, на продакте — включать с уверенностью что все оттестировано.
Часто видел трудноуловимые и трудно понимаемые ошибки при наличии кэша, включенного а ля «нам надо ускорить рендеринг! а давай кэширование включим».
Часто видел трудноуловимые и трудно понимаемые ошибки при наличии кэша, включенного а ля «нам надо ускорить рендеринг! а давай кэширование включим».
Вопрос тем кто уже освоился с джангой, гуру или те кто чувствую себя с джангой вполне комфортно.
Я вот только начал, или даже только начинаю ее изучать.
Меня сбивает столку туториалы для разные версий джанги, одни на 1.5, чуть меньше на 1.6, two scoops которые зацепил тоже 1.6, а тут еще все ждут мега-эпичный релиз 1.7 который позиционируется такимже основательным как 1.0.
Я то понимаю что надо пережовывать все, пахать и пахать. Сталкивался с подобным и в других отрослях.
Но может всетки поделитесь какимито советами, подбдрите, успокоите — вдруг че умного надумали со времен когда сами были новисами :))))
Я вот только начал, или даже только начинаю ее изучать.
Меня сбивает столку туториалы для разные версий джанги, одни на 1.5, чуть меньше на 1.6, two scoops которые зацепил тоже 1.6, а тут еще все ждут мега-эпичный релиз 1.7 который позиционируется такимже основательным как 1.0.
Я то понимаю что надо пережовывать все, пахать и пахать. Сталкивался с подобным и в других отрослях.
Но может всетки поделитесь какимито советами, подбдрите, успокоите — вдруг че умного надумали со времен когда сами были новисами :))))
Я начинал с djangobook, которая уже в то время устарела :) Но именно она позволила понять, с чего вообще начать. Думаю, первые 7 глав позволят «въехать» в основные принципы и вполне себе сойдут за туториал, ну а дальше docs.djangoproject.com от начала и до конца.
У джанги есть и собственный туториал, но он в своё время мне не понравился.
У джанги есть и собственный туториал, но он в своё время мне не понравился.
даааа, от джангобука многие открещиваются как от нечистой — так что я как бы решил вабще не обращать на нее внимание. но конечно все же просмотрю :)
джанго туториал мне более или менее понравился, сам по себе он далек от полноценного, но через него думаю что я как минимум половину доков прочитал.
меня больше всего напрягает переход между фишками версий...1.5 1.6 1.7, что то добавлено, что то уже похоронено.
джанго туториал мне более или менее понравился, сам по себе он далек от полноценного, но через него думаю что я как минимум половину доков прочитал.
меня больше всего напрягает переход между фишками версий...1.5 1.6 1.7, что то добавлено, что то уже похоронено.
А в чём напряг? Все переходы подробно расписаны.
Просто начни писать что-нибудь простое. Там блог или чатик, или чонеть для сбора/обработки/отображения какой-неть простой статистики. Или что-то вроде To-Do списка, или сервис который считает сколько ты в день куришь. Главное — четко определи 1 единственную задачу для сервиса, и сделай его как получится. Когда после этого начнешь делать что-то второе, уже будешь ориентироваться в том что ты умеешь, что можно сделать лучше, что для этого надо изучить.
Тут как с английским языком — бессмысленно надеяться что ты походишь на курсы, поучишь словарь и внезапно заговоришь. Чтобы чему-то научиться, нужно это делать) Да, ты будешь косячить, будешь ошибаться, сделаешь кривую херню… а как тут иначе то?))
Тут как с английским языком — бессмысленно надеяться что ты походишь на курсы, поучишь словарь и внезапно заговоришь. Чтобы чему-то научиться, нужно это делать) Да, ты будешь косячить, будешь ошибаться, сделаешь кривую херню… а как тут иначе то?))
Sign up to leave a comment.
Django tips & tricks