Автор: Няшный Человек
Дата публикации: 2016-03-17T21:29:00.000+02:00
Архив метки: Django
Блог на Django. Часть 1 — установка
Итак начнем с установки Python-a. Так как у меня виндовс и к тому же 8.1 будет пробовать делать все под нее. Для того чтоб скачать свежую версию я воспользовался ссылкой https://www.python.org/downloads/ и на данный момент там есть версия 3.5.1, вот ее и возьму.
Во время установки я отметил галочкой пункт Add Python 3.5 to PATH, чтобы cmd его тоже распозновала.
Вот впринципе на этом данная статья может быть закончена, далее мы рассмотрим процесс настройки с БД. Хочу попробовать на postgreSQL, но а там как получится. А вообще выбор между MySQL & PostgreSQL.
Помогите с выбором БД, пишите в комментах какой отдать предпочтения.
Так же я в гит буду выкладывать все шаги разработки или же лучше выложить вконце один готовый вариант ?
Автор: Няшный Человек
Дата публикации: 2016-03-06T10:41:00.000+02:00
Почему я не люблю конфигурацию в django-style
Введение
Сегодня работал над добавлением в aiohttp.webсвойства scheme для request object.
Идея простая: отвечать что request.scheme "http" для HTTP запросов, иначе "https".
У меня есть правило: перед началом погляди как другие уже справились с этой задачей.
У создателей популярных библиотек есть большой опыт по преодолению неочевидных проблем, учиться у мастеров — полезно.
Так вышло что сегодня я смотрел код Django.
И было в том коде примерно такое:
@property
def scheme(self):
if settings.SECURE_PROXY_SSL_HEADER:
try:
header, value = settings.SECURE_PROXY_SSL_HEADER
except ValueError:
raise ImproperlyConfigured(
'The SECURE_PROXY_SSL_HEADER setting must be a tuple containing two values.'
)
if self.META.get(header, None) == value:
return 'https'
return 'http'
В целом очень хорошо: Django показала, как работать с HTTP и что делать если сервер расположен за HTTPS Reverse Proxy (Nginx, например).
В последнем случае я сконфигурирую Nginx чтобы он добавил несколько полезных HTTP HEADERS для HTTPS connection:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
По X-Forwarded-Proto я пойму что это был HTTPS.
В целом стандартная и всем (надеюсь) известная процедура.
У aiohttp свободы чуть больше: оно может понять что сокет, по которому подключились напрямую, сам уже SSL — но это пригодно только если мы готовы выставить наш aiohttp сервер прямо в веб.
Куда чаще его прячут за Nginx, HAProxy или похожим reverse proxyи там уже работают с сертификататами, проксируя обычный HTTP connection.
В общем всё прекрасно: Nginx выставит X-Forwarded-Proto HTTP HEADER который будет или "http" или "https".
Django глянет на settings.SECURE_PROXY_SSL_HEADER и если там ("X-Forwarded-Proto", "https") то scheme тоже будет "https".
Очень грамотно сделано, мне нравится.
Проблема
Так почему я этот пост написал?
А потому что settings.SECURE_PROXY_SSL_HEADER может быть чем угодно — строкой, числом или ещё какой непотребной константой.
Проверка выполняется на момент получения request.scheme.
Нам, питонщикам, плевать на производительность в данном случае — на самом деле try/except обходится дешево и никак не отразится на работе сайта.
Беда в другом — ошибка неправильной конфигурации выявится не на этапе старта приложения а тогда, когда его выкатят в production.
У тестов будет свой правильный settings.py, а на production serverадмин чуть-чуть ошибётся.
И это тоже не слишком большая проблема — при ручном тестировании команда QA, наверное, обнаружит ошибку очень быстро. Или на следующее утро — тут уж зависит от того как техроцесс построен.
А теперь представьте что вы ошиблись в другой настройке. Очень редко используемой, но при этом важной.
Решение
Проблему вроде бы можно выявить рано, перестроив процесс запуска программы.
Для начала нужно отказаться от использования общего конфига в API.
Строить код библиотеки так, чтобы она никогда не лезла в settings.py(это и Flask касается если что).
Пусть все нужные классы принимают конфигурационные параметры явно, прямо в конструкторах.
Тогда можно быстро понять, что формат параметра не тот или IP address недоступен.
Разделение на этапы:
- чтение конфига, анализ его и подготовка приложения к работе
- запуск и работа
помогает избежать досадных недоразумений.
Плюс, к тому же, на явном этапе подготовки к старту можно позволить себе довольно дорогостоящие проверки на корректное функционирование системы (послать PING чтобы убедится что Redis живой, например).
Автор: Andrew Svetlov
South. Документация. Конвертирование приложения
Конвертирование приложения
- Отредактируйте ваш settings.py и укажите south в INSTALLED_APPS (мы предполагаем, что Вы установили south туда, куда нужно)
- Запустите ./manage.py syncdb для того, чтобы загрузить таблицу South в БД. Обратите внимание, что теперь syncdb не такой как раньше — South его изменил
- Запустите ./manage.py convert_to_south myapp — South автоматически подготовит и выполнит первую миграцию
Конвертирование других установок и серверов
Автор: Ishayahu Lastov
Документация South — Перевод. Часть 4: Пользовательские поля
Наше поле
from django.db import models
class TagField(models.TextField):
description = "Stores tags in a single database column."
__metaclass__ = models.SubfieldBase
def __init__(self, delimiter="|", *args, **kwargs):
self.delimiter = delimiter
super(TagField, self).__init__(*args, **kwargs)
def to_python(self, value):
# If it's already a list, leave it
if isinstance(value, list):
return value
# Otherwise, split by delimiter
return value.split(self.delimiter)
def get_prep_value(self, value):
return self.delimiter.join(value)
Именованные аргументы
South знает все эти правила для стандартных полей Django, но Вам необходимо объяснить все это касательно своих полей. Хорошая новость состоит в том, что South может отследить цепочку наследования, так что о полях, определённых в родительских классах говорить заново в дочерних классах не надо (или надо сообщить только о тех дополнительных именованных аргументах, которых не было в родительском классе).
В нашем примере мы определяем только один дополнительный именованный аргумент — delimiter. Вот код, который мы добавляем для того, чтобы South мог обработать наше новое поле. Чуть позже мы его объясним:
from south.modelsinspector import add_introspection_rules
add_introspection_rules([
(
[TagField], # Класс(ы) к которым это применимо
[], # позиционные аргументы (не используется)
{ # именованные аргументы
"delimiter": ["delimiter", {"default": "|"}],
},
),
], ["^southtut.fields.TagField"])
Как Вы можете видеть, для того, чтобы рассказать South о вашем новом поле Вам нужно вызвать функцию south.modelsinspector.add_introspection_rules. Вы должны разместить этот код рядом с определением вашего поля. Так как последнее, что Вы хотели бы — это импортировать поле, но чтобы этот код не был выполнен.
add_introspection_rules принимает два аргумента: список правил и список регулярных выражений. Список регулярных выражений используется South для того чтобы понять, можно ли исследовать это поле. Просто иметь правило, которое подходит для поля недостаточно, так как наследование правил подразумевает, что любой пользовательский класс поля будет иметь хотя бы одно правило, под которое он подпадает (
опять — «(as they will inherit from «Field«, if not something more specificlike «CharField«), and some custom fields can get by with only those inherited rules (more on that shortly)«).
Первый аргумент — список правил. Каждое правило — это кортеж (или список) с тремя элементами:
- Список классов к которым применимы эти правила. Практически наверняка у Вас будет тут только одно поле, например, то, про которое мы сейчас говорим.
- Спецификация позиционных аргументов. Практически наверняка будет пустым списком — []
- Спецификация именованных аргументов: это словарь, где ключ — имя аргумента, а значение — список или кортеж (имя_аргумента, опции)
Простые наследования
class UpperCaseField(models.TextField):
"Убеждаемся, что содержимое всегда в верхнем регистре."
def to_python(self, value):
return value.upper()
def get_prep_value(self, value):
return value.upper()
from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^southtut.fields.UpperCaseField"])
Больше информации
Автор: Ishayahu Lastov
Django 1.5 и Python 3 (Перевод)
Автор: Ishayahu Lastov


