Вышла новая версия Django 1.6.
В Django 1.6 появилось новое API для работы с транзакциями. Начиная с этой версии привычные для работы с транзакциями функции autocommit(), commit_on_success() и commit_manually() из модуля django.db.transaction теперь считаются устаревшими и останутся для совместимости до 1.8. На их замену приходит atomic().
Ранее ключевым моментом был механизм управления поведением при работе с коммитом транзакции - автокоммитом, когда каждый SQL-запрос начинает транзакцию и коммитит ее автоматом, или ручным коммитом (COMMIT; SQL-запрос отправляется самостоятельно). Этот механизм довольно хорошо работал в случае независимых транзакций, но вот в случае вложенного использования устаревших функций результат мог быть некорректен. Например, если у нас есть 2 блока commit_on_success(), вложенных один в другой, то может возникнуть ситуация, когда результат выполнения внутреннего блока будет закоммичен, поломав атомарность внешнего блока.
Теперь же во-первых Django 1.6 по умолчанию включает режим автокоммита. И единственным механизмом работы с транзакциями становится atomic(), который не боится вложенности. Также вместо TransactionMiddleware доступна конфигурационная константа ATOMIC_REQUESTS, при установке значения которой в True (дефолтное значение — False), джанго будет стараться обработать один HTTP-запрос в одной транзакции. То есть, если выполнился запрос без каких-либо проблем, то закоммитили, нет - откатили изменения.
Необходимо отметить, что atomic() может использоваться как декоратор, так и как менеджер контекста:
from django.db import transaction
# декоратор
@transaction.atomic
def viewfunc1(request):
# этот код будет выполнен внутри транзакции
do_stuff()
and as a context manager:
# менеджер контекста
def viewfunc2(request):
# этот код выполняется в режиме автокоммита
do_stuff()
with transaction.atomic():
# а здесь уже выполняется внутри транзакции
do_more_stuff()
В Django 1.6 были добавлены постоянные соединения с базой данных. Это, конечно, не пулл соединений, так как они изолированы потоками, в которых запущено приложение, но, это уже гораздо лучше, чем постоянное подключение к базе при каждом HTTP запросе. Время жизни соединений регулируется конфигурационной константой CONN_MAX_AGE.
В Django 1.6 появился новый механизм для запуска тестов: django.test.runner.DiscoverRunner, который использует логику поиска модулей с тестами из unittest2. Теперь тесты могут располагаться в любых модулях, если имя файла, содержащего их соответствует маске test*.py. Правда, при этом, тесты из models.py и tests/__init__.py найдены и запущены не будут. Самым простым решением является переименовывание их в что-либо вида test_models.py и tests/test.py. Помимо этого доктесты больше не будут подгружаться автоматом. Но их будет не сложно включить обратно, следуя указаниям из документации по unittest.
У management-команды ./manage.py test теперь появилась опция --pattern, указав которую, можно менять маску для поиска файлов с тестами.
Команда django-admin.py check теперь позволяет проверить совместимость проекта или приложения с текущей версией Django, выдавая оповещения в случае нахождения несовместимых мест. Предполагается, что эта команда будет помогать при переходе на новые версии фреймворка.
В Django 1.6 добавились улучшения ORM. Теперь QuerySet поддерживает синтаксический сахар в виде методов first() и last(), а также earliest() в дополнение к latest(). ORM теперь поддерживает hour, minute и second в дополнение к добавленным ранее year, month и day при поиске по полям с датой и/или временем.
Django 1.6 - это последний релиз Django, в котором еще поддерживается Python 2.6. Со следующего релиза Django будет требоваться как минимум Python 2.7.
пятница, 8 ноября 2013 г.
пятница, 12 апреля 2013 г.
Установка Apache, PHP, MySQL на Ubuntu
Все шаги выполнялись с привилегиями root, поэтому убедитесь, что вы вошли в систему как root.
Сначала мы установим MySQL 5 следующим образом:
Apache2 доступен в виде пакета для Ubuntu, поэтому мы можем установить его так:
Корневая директория Apache /var/www, файлы конфигурации /etc/apache2/apache2.conf. Дополнительные настройки хранятся в подкаталоге /etc/apache2, такие как: /etc/apache2/mods-enabled (для модулей Apache), /etc/apache2/sites-enabled (для виртуальных хостов) и /etc/apache2/conf.d.
Установка PHP5
Вы можете установить PHP5 и Apache PHP5 модуль следующим образом:
В корневом каталоге документов веб-сайта по умолчанию /var/www, мы создадим маленький PHP файл (info.php) и откроем его в браузере. Файл будет отображать много полезной информации об установленной версии PHP, например, версию установленного PHP и т.д.
Как видите, PHP5 работает с помощью Apache 2.0 Handler, об этом говорится в строке Server API. Прокрутив страницу вниз, вы увидите все модули, которые сейчас включены в PHP5, но в этом списке нету MySQL, а это означает, что у нас еще нету поддержки MySQL в PHP5.
Получение поддержки MySQL в PHP5
Ищем и устанавливаем нужные PHP5 модули, в том числе и модуль php5-mysql для поддержки MySQL в PHP:
Установка phpMyAdmin
phpMyAdmin — это веб-интерфейс, с помощью которого можно управлять базами данных MySQL.
Web server to reconfigure automatically: <— Выбрать Apache2
Configure database for phpmyadmin with dbconfig-common? <— No (Нет)
Далее, чтобы phpMyAdmin открывался по адресу http://localhost/phpmyadmin/, нужно сделать символьную ссылку на него:
sudo suУстановка MySQL 5
Сначала мы установим MySQL 5 следующим образом:
apt-get install mysql-server mysql-clientВам будет предложено ввести пароль для администратора MySQL — этот пароль действителен для пользователя root@localhost, а также root@server1.example.com, а это значит, что в дальнейшем нам не нужно указывать пароль для администратора вручную.
New password for the MySQL «root» user: <— Введите парольУстановка Apache2
Repeat password for the MySQL «root» user: <— Подтвердите пароль
Apache2 доступен в виде пакета для Ubuntu, поэтому мы можем установить его так:
apt-get install apache2Открываем браузер и переходим по адресу http://192.168.0.23. Вы должны увидеть страницу приветствия Apache2 (It works!):
Корневая директория Apache /var/www, файлы конфигурации /etc/apache2/apache2.conf. Дополнительные настройки хранятся в подкаталоге /etc/apache2, такие как: /etc/apache2/mods-enabled (для модулей Apache), /etc/apache2/sites-enabled (для виртуальных хостов) и /etc/apache2/conf.d.
Установка PHP5
Вы можете установить PHP5 и Apache PHP5 модуль следующим образом:
apt-get install php5 libapache2-mod-php5Потом мы должны перезапустить Apache:
/etc/init.d/apache2 restartПроверка PHP5 / Получение информации об установленном PHP5
В корневом каталоге документов веб-сайта по умолчанию /var/www, мы создадим маленький PHP файл (info.php) и откроем его в браузере. Файл будет отображать много полезной информации об установленной версии PHP, например, версию установленного PHP и т.д.
vi /var/www/info.phpВ нем пишем:
<?phpОткрываем этот файл в браузере (например, http://192.168.0.23/info.php)
phpinfo();
?>
Как видите, PHP5 работает с помощью Apache 2.0 Handler, об этом говорится в строке Server API. Прокрутив страницу вниз, вы увидите все модули, которые сейчас включены в PHP5, но в этом списке нету MySQL, а это означает, что у нас еще нету поддержки MySQL в PHP5.
Получение поддержки MySQL в PHP5
Ищем и устанавливаем нужные PHP5 модули, в том числе и модуль php5-mysql для поддержки MySQL в PHP:
apt-cache search php5Выберите те из них, которые вам нужны, и установите:
apt-get install php5-mysql php5-curl php5-gd php5-idn php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xslПерезагрузите Apache2:
/etc/init.d/apache2 restartОбновите страницу в браузере и прокрутите ее вниз, снова в раздел модулей. Теперь здесь должно появиться много новых модулей, включая модуль MySQL:
Установка phpMyAdmin
phpMyAdmin — это веб-интерфейс, с помощью которого можно управлять базами данных MySQL.
apt-get install phpmyadminВы увидите следующие вопросы:
Web server to reconfigure automatically: <— Выбрать Apache2
Configure database for phpmyadmin with dbconfig-common? <— No (Нет)
Далее, чтобы phpMyAdmin открывался по адресу http://localhost/phpmyadmin/, нужно сделать символьную ссылку на него:
ln -s /usr/share/phpmyadmin/ /var/www
Python Virtualenv. Строим виртуальное окружение с помощью virtualenv.
Python Virtualenv предназначен для создания виртуального окружения (далее просто "окружение") для вашего проекта. К примеру, вашему проекту нужен отличный от установленного python или какие-либо библиотеки отличных версий, вы можете создать общее окружение для нескольких проектов или по одному собственному для каждого проекта. Тем самым вы сможете устанавливать, изменять и удалять пакеты, и это не повлияет на другие ваши проекты или системное окружение.
В статье рассматривается версия 1.7.1.2
Установка
Для начала надо его установить в вашу систему, через PyPI:
$ sudo pip install virtualenv
$ sudo easy_install virtualenv
Или через Debian, Ubuntu:
$ sudo apt-get install python-virtualenv
Или через FreeBSD:
$ cd /usr/ports/evel/py-virtualenv
$ make install clean
Использование
Для начала рассмотрим самые полезные возможности, остальные вы можете посмотреть в man virtualenv:
--no-site-packages
Запретить использование системного site-packages (для полной изоляции вашего окружения от системы). Например у вас в системе установлена "Django 1.3", если вы будете использовать эту опцию, то в созданном окружении эта "Django" не будет доступна.
В текущих версиях virtualenv эта опция используется по умолчанию, можете её не указывать.
--system-site-packages
Эта опция противоположна предыдущей, то есть заставляет окружение использовать установленные в системе пакеты, если не нашлись онные в окружении.
-p PYTHON_EXE, --python=PYTHON_EXE
Вы можете указать нужную вам версию интерпретатора python, при этом он должен быть установлен в системе. Если вы опустили эту опцию, то будет использоваться умолчательный (Выполните which python чтобы узнать какой он у вас, но скорее всего это будет /usr/bin/python).
--distribute
Использовать Ditribute.
Опция используется по умолчанию.
--setuptools
Использовать Setuptools поверх Ditribute. Вы можете установить переменную окружения вашей системы VIRTUALENV_SETUPTOOLS, чтобы Setuptools стал умолчательным вместо Ditribute.
$ export VIRTUALENV_SETUPTOOLS=true
--extra-search-dir=SEARCH_DIRS
Указанные директории будут использовать для поиска в них пакетов при установке через setuptools/distribute/pip. Это подходит в случае когда вы не хотите их устаналивать из PyPI.
Подробное описание тут.
--never-download
Не использовать сеть для получения пакетов. Используется совместно с --extra-search-dir=SEARCH_DIRS.
Подробное описание тут.
--relocatable
Сделать существующее окружение относительным, то есть после этого вы сможете перемещать каталог с окружением и оно не будет зависеть от своего места дислокации, но опция в данный момент экспериментальная.
Подробное описание тут.
--prompt=PROMPT
Выводимое имя окружения (подсказка), например вы можете создать с названием (MY_VENV):
$ virtualenv --prompt="(MY_VENV)" <venv_name>
source venv/bin/activate
(MY_VENV)$
--clear
Используется для очистки существующего окружения от пакетов и прочих изменений.
Создаем общее окружение (для нескольких проектов) без использования системного site-packages:
$ mkdir ~/venv && cd ~/venv
$ virtualenv --no-site-packages <venv_name>
Часто я создаю окружение непосредственно в каталоге проекта:
$ cd ~/work/<project_name>
$ mkdir venv && echo "Virtualenv directory" > venv/README
$ git add venv && echo "/venv/" >> .gitignore && git add -f .gitignore
$ virtualenv --no-site-packages --prompt="(<project_name>)" <venv_name>
После того как вы установили новое окружение, у вас будет следующая структура:
~/venv/<venv_name>
├── bin
│ ├── activate
│ ├── easy_install
│ ├── pip
│ ├── python
│ └── ...
├── include
│ └── python2.7 -> /usr/include/python2.7
├── lib
│ └── python2.7
│ ├── distutils
│ │ └── ...
│ ├── site-packages
│ │ └── ...
│ └── ...
└── local
├── bin -> /home/username/venv/<venv_name>/bin
├── include -> /home/username/venv/<venv_name>/include
└── lib -> /home/username/venv/<venv_name>/lib
Таким образом вам сразу же доступны изолированные python, pip и easy_install.
Работа с окружением
Для начала работы вам следует активировать окружение так:
$ source ~/venv/<venv_name>/bin/activate
$ python manage.py
Для окончания работы с окружением (например для переключение на системный python) следует выполнить в командной строке:
$ deactivate
Вы также можете запустить python по абсолютному пути (это может пригодится например в cron):
$ ~/venv/<venv_name>/bin/python manage.py
Установка пакетов в окружение
Надо активировать окружение и запустить pip или easy_install:
$ source ~/venv/<venv_name>/bin/activate
$ pip install <something>
$ easy_install <something>
Также через pip вы можете установить не активируя окружение:
$ pip install -E ~/venv/<venv_name> <something>
В статье рассматривается версия 1.7.1.2
Установка
Для начала надо его установить в вашу систему, через PyPI:
$ sudo pip install virtualenv
$ sudo easy_install virtualenv
Или через Debian, Ubuntu:
$ sudo apt-get install python-virtualenv
Или через FreeBSD:
$ cd /usr/ports/evel/py-virtualenv
$ make install clean
Использование
Для начала рассмотрим самые полезные возможности, остальные вы можете посмотреть в man virtualenv:
--no-site-packages
Запретить использование системного site-packages (для полной изоляции вашего окружения от системы). Например у вас в системе установлена "Django 1.3", если вы будете использовать эту опцию, то в созданном окружении эта "Django" не будет доступна.
В текущих версиях virtualenv эта опция используется по умолчанию, можете её не указывать.
--system-site-packages
Эта опция противоположна предыдущей, то есть заставляет окружение использовать установленные в системе пакеты, если не нашлись онные в окружении.
-p PYTHON_EXE, --python=PYTHON_EXE
Вы можете указать нужную вам версию интерпретатора python, при этом он должен быть установлен в системе. Если вы опустили эту опцию, то будет использоваться умолчательный (Выполните which python чтобы узнать какой он у вас, но скорее всего это будет /usr/bin/python).
--distribute
Использовать Ditribute.
Опция используется по умолчанию.
--setuptools
Использовать Setuptools поверх Ditribute. Вы можете установить переменную окружения вашей системы VIRTUALENV_SETUPTOOLS, чтобы Setuptools стал умолчательным вместо Ditribute.
$ export VIRTUALENV_SETUPTOOLS=true
--extra-search-dir=SEARCH_DIRS
Указанные директории будут использовать для поиска в них пакетов при установке через setuptools/distribute/pip. Это подходит в случае когда вы не хотите их устаналивать из PyPI.
Подробное описание тут.
--never-download
Не использовать сеть для получения пакетов. Используется совместно с --extra-search-dir=SEARCH_DIRS.
Подробное описание тут.
--relocatable
Сделать существующее окружение относительным, то есть после этого вы сможете перемещать каталог с окружением и оно не будет зависеть от своего места дислокации, но опция в данный момент экспериментальная.
Подробное описание тут.
--prompt=PROMPT
Выводимое имя окружения (подсказка), например вы можете создать с названием (MY_VENV):
$ virtualenv --prompt="(MY_VENV)" <venv_name>
source venv/bin/activate
(MY_VENV)$
--clear
Используется для очистки существующего окружения от пакетов и прочих изменений.
Создаем общее окружение (для нескольких проектов) без использования системного site-packages:
$ mkdir ~/venv && cd ~/venv
$ virtualenv --no-site-packages <venv_name>
Часто я создаю окружение непосредственно в каталоге проекта:
$ cd ~/work/<project_name>
$ mkdir venv && echo "Virtualenv directory" > venv/README
$ git add venv && echo "/venv/" >> .gitignore && git add -f .gitignore
$ virtualenv --no-site-packages --prompt="(<project_name>)" <venv_name>
После того как вы установили новое окружение, у вас будет следующая структура:
~/venv/<venv_name>
├── bin
│ ├── activate
│ ├── easy_install
│ ├── pip
│ ├── python
│ └── ...
├── include
│ └── python2.7 -> /usr/include/python2.7
├── lib
│ └── python2.7
│ ├── distutils
│ │ └── ...
│ ├── site-packages
│ │ └── ...
│ └── ...
└── local
├── bin -> /home/username/venv/<venv_name>/bin
├── include -> /home/username/venv/<venv_name>/include
└── lib -> /home/username/venv/<venv_name>/lib
Таким образом вам сразу же доступны изолированные python, pip и easy_install.
Работа с окружением
Для начала работы вам следует активировать окружение так:
$ source ~/venv/<venv_name>/bin/activate
$ python manage.py
Для окончания работы с окружением (например для переключение на системный python) следует выполнить в командной строке:
$ deactivate
Вы также можете запустить python по абсолютному пути (это может пригодится например в cron):
$ ~/venv/<venv_name>/bin/python manage.py
Установка пакетов в окружение
Надо активировать окружение и запустить pip или easy_install:
$ source ~/venv/<venv_name>/bin/activate
$ pip install <something>
$ easy_install <something>
Также через pip вы можете установить не активируя окружение:
$ pip install -E ~/venv/<venv_name> <something>
среда, 27 марта 2013 г.
Django Paginator
views.py
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from blog.data.models import Entry
def index(request):
entries = Entry.objects.published_entries().order_by('-id')
paginator = Paginator(entries, 2)
page_num = request.GET.get('page', 1)
try:
page = paginator.page(page_num)
except EmptyPage:
page = paginator.page(paginator.num_pages)
except PageNotAnInteger:
page = paginator.page(1)
return render_to_response('homepage/index.html', {'page': page}, context_instance = RequestContext(request))
--------------------------------------------------------------------------------------------
index.html
{% extends "homepage/base.html" %}
{% block content %}
<h3>Entries</h3>
{% for entry in page.object_list %}
<div>{{ entry.title }} - {{ entry.created }}</div>
<div>{{ entry.text }}</div>
<br />
{% endfor %}
{% if page.has_previous %}
<a href="?page={{ page.previous_page_number }}">prev</a>
{% endif %}
| {{ page.number }} |
{% if page.has_next %}
<a href="?page={{ page.next_page_number }}">next</a>
{% endif %}
{% endblock %}
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from blog.data.models import Entry
def index(request):
entries = Entry.objects.published_entries().order_by('-id')
paginator = Paginator(entries, 2)
page_num = request.GET.get('page', 1)
try:
page = paginator.page(page_num)
except EmptyPage:
page = paginator.page(paginator.num_pages)
except PageNotAnInteger:
page = paginator.page(1)
return render_to_response('homepage/index.html', {'page': page}, context_instance = RequestContext(request))
--------------------------------------------------------------------------------------------
index.html
{% extends "homepage/base.html" %}
{% block content %}
<h3>Entries</h3>
{% for entry in page.object_list %}
<div>{{ entry.title }} - {{ entry.created }}</div>
<div>{{ entry.text }}</div>
<br />
{% endfor %}
{% if page.has_previous %}
<a href="?page={{ page.previous_page_number }}">prev</a>
{% endif %}
| {{ page.number }} |
{% if page.has_next %}
<a href="?page={{ page.next_page_number }}">next</a>
{% endif %}
{% endblock %}
вторник, 26 марта 2013 г.
Django MEDIA_URL in Templates
settings.py
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), 'static/'))
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/static/'
# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = ''
# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'
# URL prefix for admin static files -- CSS, JavaScript and images.
# Make sure to use a trailing slash.
# Examples: "http://foo.com/static/admin/", "/static/admin/".
ADMIN_MEDIA_PREFIX = '/static/admin/'
TEMPLATE_CONTEXT_PROCESSOR = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.media',
)
--------------------------------------------------------------------------------------------
views.py
from django.shortcuts import render_to_response
from blog.data.models import Entry
from django.template import RequestContext
def index(request):
entries = Entry.objects.published_entries().order_by('-id')
return render_to_response('homepage/index.html', {'entries': entries}, context_instance = RequestContext(request))
def about(request):
return render_to_response('homepage/about.html', context_instance = RequestContext(request))
def contact(request):
return render_to_response('homepage/contact.html', context_instance = RequestContext(request))
def archive(request):
return render_to_response('homepage/archive.html', context_instance = RequestContext(request))
--------------------------------------------------------------------------------------------
base.html
<html>
<head>
<title>{% block title %}{% endblock %}</title>
{% block js %}{% endblock %}
{% block css %}<link rel="stylesheet" href="{{ MEDIA_URL }}css/main.css" type="text/css" media="screen" />{% endblock %}
</head>
<body>
<div id="top">My Blog</div>
<div id="navi">{% block navi %}{% endblock %}</div>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">{% block footer %}{% endblock %}</div>
</body>
</html>
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), 'static/'))
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/static/'
# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = ''
# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'
# URL prefix for admin static files -- CSS, JavaScript and images.
# Make sure to use a trailing slash.
# Examples: "http://foo.com/static/admin/", "/static/admin/".
ADMIN_MEDIA_PREFIX = '/static/admin/'
TEMPLATE_CONTEXT_PROCESSOR = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.media',
)
--------------------------------------------------------------------------------------------
views.py
from django.shortcuts import render_to_response
from blog.data.models import Entry
from django.template import RequestContext
def index(request):
entries = Entry.objects.published_entries().order_by('-id')
return render_to_response('homepage/index.html', {'entries': entries}, context_instance = RequestContext(request))
def about(request):
return render_to_response('homepage/about.html', context_instance = RequestContext(request))
def contact(request):
return render_to_response('homepage/contact.html', context_instance = RequestContext(request))
def archive(request):
return render_to_response('homepage/archive.html', context_instance = RequestContext(request))
--------------------------------------------------------------------------------------------
base.html
<html>
<head>
<title>{% block title %}{% endblock %}</title>
{% block js %}{% endblock %}
{% block css %}<link rel="stylesheet" href="{{ MEDIA_URL }}css/main.css" type="text/css" media="screen" />{% endblock %}
</head>
<body>
<div id="top">My Blog</div>
<div id="navi">{% block navi %}{% endblock %}</div>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">{% block footer %}{% endblock %}</div>
</body>
</html>
Django Static files on Developer Server
base.html
<html>
<head>
<title>{% block title %}{% endblock %}</title>
{% block js %}{% endblock %}
{% block css %}<link rel="stylesheet" href="/static/css/main.css" type="text/css" media="screen" />{% endblock %}
</head>
<body>
<div id="top">My Blog</div>
<div id="navi">{% block navi %}{% endblock %}</div>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">{% block footer %}{% endblock %}</div>
</body>
</html>
--------------------------------------------------------------------------------------------
settings.py
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), 'static/'))
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/static/'
# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = ''
# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'
# URL prefix for admin static files -- CSS, JavaScript and images.
# Make sure to use a trailing slash.
# Examples: "http://foo.com/static/admin/", "/static/admin/".
ADMIN_MEDIA_PREFIX = '/static/admin/'
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.admin',
'blog.data',
)
--------------------------------------------------------------------------------------------
urls.py
from django.conf.urls.defaults import patterns, include, url
from blog import settings
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', 'blog.homepage.views.index', name = 'homepage_index'),
url(r'^about/$', 'blog.homepage.views.about', name = 'homepage_about'),
url(r'^contact/$', 'blog.homepage.views.contact', name = 'homepage_contact'),
url(r'^archive/$', 'blog.homepage.views.archive', name = 'homepage_archive'),
url(r'^admin/', include(admin.site.urls)),
url(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
)
<html>
<head>
<title>{% block title %}{% endblock %}</title>
{% block js %}{% endblock %}
{% block css %}<link rel="stylesheet" href="/static/css/main.css" type="text/css" media="screen" />{% endblock %}
</head>
<body>
<div id="top">My Blog</div>
<div id="navi">{% block navi %}{% endblock %}</div>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">{% block footer %}{% endblock %}</div>
</body>
</html>
--------------------------------------------------------------------------------------------
settings.py
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = os.path.normpath(os.path.join(os.path.dirname(__file__), 'static/'))
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = '/static/'
# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = ''
# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'
# URL prefix for admin static files -- CSS, JavaScript and images.
# Make sure to use a trailing slash.
# Examples: "http://foo.com/static/admin/", "/static/admin/".
ADMIN_MEDIA_PREFIX = '/static/admin/'
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.admin',
'blog.data',
)
--------------------------------------------------------------------------------------------
urls.py
from django.conf.urls.defaults import patterns, include, url
from blog import settings
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', 'blog.homepage.views.index', name = 'homepage_index'),
url(r'^about/$', 'blog.homepage.views.about', name = 'homepage_about'),
url(r'^contact/$', 'blog.homepage.views.contact', name = 'homepage_contact'),
url(r'^archive/$', 'blog.homepage.views.archive', name = 'homepage_archive'),
url(r'^admin/', include(admin.site.urls)),
url(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
)
Django Urls from urls.py in Templates
urls.py
from django.conf.urls.defaults import patterns, include, url
from blog import settings
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', 'blog.homepage.views.index', name = 'homepage_index'),
url(r'^about/$', 'blog.homepage.views.about', name = 'homepage_about'),
url(r'^contact/$', 'blog.homepage.views.contact', name = 'homepage_contact'),
url(r'^archive/$', 'blog.homepage.views.archive', name = 'homepage_archive'),
url(r'^admin/', include(admin.site.urls)),
url(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
)
--------------------------------------------------------------------------------------------
index.html
{% extends "homepage/base.html" %}
{% block title %}My Blog Index{% endblock %}
{% block navi %}
<a href="{% url homepage_index %}">home</a> - <a href="{% url homepage_about %}">about</a> - <a href="{% url homepage_archive %}">archive</a> - <a href="{% url homepage_contact %}">contact</a>
{% endblock %}
{% block content %}
<h3>Entries</h3>
{% for entry in entries %}
<div>{{ entry.title }} - {{ entry.created }}</div>
<div>{{ entry.text }}</div>
<br />
{% endfor %}
{% endblock %}
{% block footer %}
2011 - MyBlog
{% endblock %}
from django.conf.urls.defaults import patterns, include, url
from blog import settings
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', 'blog.homepage.views.index', name = 'homepage_index'),
url(r'^about/$', 'blog.homepage.views.about', name = 'homepage_about'),
url(r'^contact/$', 'blog.homepage.views.contact', name = 'homepage_contact'),
url(r'^archive/$', 'blog.homepage.views.archive', name = 'homepage_archive'),
url(r'^admin/', include(admin.site.urls)),
url(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT}),
)
--------------------------------------------------------------------------------------------
index.html
{% extends "homepage/base.html" %}
{% block title %}My Blog Index{% endblock %}
{% block navi %}
<a href="{% url homepage_index %}">home</a> - <a href="{% url homepage_about %}">about</a> - <a href="{% url homepage_archive %}">archive</a> - <a href="{% url homepage_contact %}">contact</a>
{% endblock %}
{% block content %}
<h3>Entries</h3>
{% for entry in entries %}
<div>{{ entry.title }} - {{ entry.created }}</div>
<div>{{ entry.text }}</div>
<br />
{% endfor %}
{% endblock %}
{% block footer %}
2011 - MyBlog
{% endblock %}
Django Model Managers
data/managers.py
from django.db import models
class EntryManager(models.Manager):
def published_entries(self):
return self.model.objects.filter(published = True)
--------------------------------------------------------------------------------------------
data/models.py
#-*- coding: utf-8 -*-
from django.db import models
from blog.data.managers import EntryManager
class Entry(models.Model):
created = models.DateTimeField(auto_now_add = True)
updated = models.DateTimeField(auto_now = True)
title = models.CharField(max_length = 64)
text = models.TextField()
published = models.BooleanField(db_index = True, default = True)
objects = EntryManager()
def __unicode__(self):
return u'%s - %s' % (self.title, self.created)
--------------------------------------------------------------------------------------------
data/views.py
from django.shortcuts import render_to_response
from blog.data.models import Entry
def index(request):
entries = Entry.objects.published_entries().order_by('-id')
return render_to_response('homepage/index.html', {'entries': entries})
from django.db import models
class EntryManager(models.Manager):
def published_entries(self):
return self.model.objects.filter(published = True)
--------------------------------------------------------------------------------------------
data/models.py
#-*- coding: utf-8 -*-
from django.db import models
from blog.data.managers import EntryManager
class Entry(models.Model):
created = models.DateTimeField(auto_now_add = True)
updated = models.DateTimeField(auto_now = True)
title = models.CharField(max_length = 64)
text = models.TextField()
published = models.BooleanField(db_index = True, default = True)
objects = EntryManager()
def __unicode__(self):
return u'%s - %s' % (self.title, self.created)
--------------------------------------------------------------------------------------------
data/views.py
from django.shortcuts import render_to_response
from blog.data.models import Entry
def index(request):
entries = Entry.objects.published_entries().order_by('-id')
return render_to_response('homepage/index.html', {'entries': entries})
Comparison of Common Windows and Linux Commands
Command's Purpose | MS-DOS | Linux | Basic Linux Example |
---|---|---|---|
Copies files | copy | cp | cp thisfile.txt /home/thisdirectory |
Moves files | move | mv | mv thisfile.txt /home/thisdirectory |
Lists files | dir | ls | ls |
Clears screen | cls | clear | clear |
Closes prompt window | exit | exit | exit |
Displays or sets date | date | date | date |
Deletes files | del | rm | rm thisfile.txt |
"Echoes" output on the screen | echo | echo | echo this message |
Edits files with simple text editor | edit | pico[a] | pico thisfile.txt |
Compares the contents of files | fc | diff | diff file1 file2 |
Finds a string of text in a file | find | grep | grep this word or phrase thisfile.txt |
Formats a diskette | format a: (if diskette is in A:) | mke2fs (or mformat[b]) | /sbin/mke2fs /dev/fd0 (/dev/fd0 is the Linux equivalent of A:) |
Displays command help | command /? | man[c] | man command |
Creates a directory | mkdir | mkdir | mkdir directory |
View a file | more | less[d] | less thisfile.txt |
Renames a file | ren | mv | mv thisfile.txt thatfile.txt[e] |
Displays your location in the file system | chdir | pwd | pwd |
Changes directories with a specified path (absolute path) | cd pathname | cd pathname | cd /directory/directory |
Changes directories with a relative path | cd .. | cd .. | cd .. |
Displays the time | time | date | date |
Shows amount of RAM and use | mem | free | free |
Notes: a. Pico is a simple text editor; other editors you can use in place of Pico include Emacs and vi. b. This formats a disk for the DOS filesystem. c. You can also use info for some commands. d. The more pager can also be used to page through a file a screen at a time. e. The mv command can both move a file and, if you want to rename a file in the same directory, you "move" that file to the same directory with a new name, as in this example. |
вторник, 19 марта 2013 г.
Python Проверка существования файла
Данный Python код проверяет существование файла и возможность работы с ним.
from os import path, access, R_OK # W_OK for write permission.
PATH='./file.txt'
if path.exists(PATH) and path.isfile(PATH) and access(PATH, R_OK):
print "File exists and is readable"
else:
print "Either file is missing or is not readable"
from os import path, access, R_OK # W_OK for write permission.
PATH='./file.txt'
if path.exists(PATH) and path.isfile(PATH) and access(PATH, R_OK):
print "File exists and is readable"
else:
print "Either file is missing or is not readable"
Django UnicodeEncodeError: 'ascii' codec can't encode character Решение проблемы
При работе с Django во время записи русского текста в кодировке UTF-8 в файл может возникнуть исключение вида
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa1'
in position 0: ordinal not in range(128)
Такое исключение в Django может возникнуть, например, при выполнении такого кода:
#-*- coding: utf-8 -*-
import os
from django.template import Template, Context, loader
from django.http import HttpResponse
def write_file(request):
pathToFile = os.path.join(os.path.dirname(__file__), 'files/newtext.txt')
file = open(pathToFile, 'w')
text_for_file = u'Привет! Я новый файл!'
file.write(text_for_file)
file.close()
file = open(pathToFile, 'r')
text_from_file = file.read()
file.close()
t = loader.get_template('filework.html')
c = Context({'text': text_from_file})
renderedTemplate = t.render(c)
return HttpResponse(renderedTemplate)
Для устранения данной проблемы можно воспользоваться функцией smart_str(), имеющейся в Django, внеся в наш пример следующие две добавки:
#-*- coding: utf-8 -*-
import os
from django.template import Template, Context, loader
from django.http import HttpResponse
from django.utils.encoding import smart_str, smart_unicode
def open_file(request):
pathToFile = os.path.join(os.path.dirname(__file__), 'files/mytext.txt')
file = open(pathToFile, 'r')
text_from_file = file.read()
file.close()
t = loader.get_template('filework.html')
c = Context({'text': text_from_file})
renderedTemplate = t.render(c)
return HttpResponse(renderedTemplate)
def write_file(request):
pathToFile = os.path.join(os.path.dirname(__file__), 'files/newtext.txt')
file = open(pathToFile, 'w')
text_for_file = u'Привет! Я новый файл!'
file.write(smart_str(text_for_file))
file.close()
file = open(pathToFile, 'r')
text_from_file = file.read()
file.close()
t = loader.get_template('filework.html')
c = Context({'text': text_from_file})
renderedTemplate = t.render(c)
return HttpResponse(renderedTemplate)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa1'
in position 0: ordinal not in range(128)
Такое исключение в Django может возникнуть, например, при выполнении такого кода:
#-*- coding: utf-8 -*-
import os
from django.template import Template, Context, loader
from django.http import HttpResponse
def write_file(request):
pathToFile = os.path.join(os.path.dirname(__file__), 'files/newtext.txt')
file = open(pathToFile, 'w')
text_for_file = u'Привет! Я новый файл!'
file.write(text_for_file)
file.close()
file = open(pathToFile, 'r')
text_from_file = file.read()
file.close()
t = loader.get_template('filework.html')
c = Context({'text': text_from_file})
renderedTemplate = t.render(c)
return HttpResponse(renderedTemplate)
Для устранения данной проблемы можно воспользоваться функцией smart_str(), имеющейся в Django, внеся в наш пример следующие две добавки:
#-*- coding: utf-8 -*-
import os
from django.template import Template, Context, loader
from django.http import HttpResponse
from django.utils.encoding import smart_str, smart_unicode
def open_file(request):
pathToFile = os.path.join(os.path.dirname(__file__), 'files/mytext.txt')
file = open(pathToFile, 'r')
text_from_file = file.read()
file.close()
t = loader.get_template('filework.html')
c = Context({'text': text_from_file})
renderedTemplate = t.render(c)
return HttpResponse(renderedTemplate)
def write_file(request):
pathToFile = os.path.join(os.path.dirname(__file__), 'files/newtext.txt')
file = open(pathToFile, 'w')
text_for_file = u'Привет! Я новый файл!'
file.write(smart_str(text_for_file))
file.close()
file = open(pathToFile, 'r')
text_from_file = file.read()
file.close()
t = loader.get_template('filework.html')
c = Context({'text': text_from_file})
renderedTemplate = t.render(c)
return HttpResponse(renderedTemplate)
вторник, 12 марта 2013 г.
LDAP
LDAP - это прежде всего протокол, который призван централизовать,
унифицировать хранение и администрирование учетных записей с их
свойствами, а самое главное - это централизовать процесс авторизации
пользователей в КИС (корпоративные информационные системы), которые
включают в себя множество разношерстных систем. Вот и получается, что
храните вы все учетные записи на LDAP-сервере, а авторизация
пользователей может производиться в разных системай, например почтовых
клиента, системах оперативного и финансового учета и т.д. и т.п..
четверг, 7 марта 2013 г.
Django Работа с Memcached
Добавление настроек в Django для Memcached в файл settings.py
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
}
Кэширование в Memcached отдельных данных.
>>> from django.core.cache import cache
>>> cache.set('my_var', 'hello world', 30)
>>> cache.get('my_var', 'or return My_var has expired')
'hello world'
>>> cache.set('a', 1, 60)
>>> cache.set('b', 2, 60)
>>> cache.set('c', 3, 60)
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}
>>> cache.delete('a')
>>> cache.get_many(['a', 'b', 'c'])
{'b': 2, 'c': 3}
Кэширование в Memcached целых страниц Django.
from django.conf.urls.defaults import patterns, include, url
from django.views.decorators.cache import cache_page
from mysite.myapp.views import my_view
urlpatterns = ('',
(r'^foo/(\d{1,2})/$', cache_page(my_view, 60 * 15)),
)
Кэширование внутри файла views.py
from django.views.decorators.cache import cache_page
@cache_page(60 * 15)
def my_view(request, param):
...
...
...
Кэширование в Memcached всех страниц.
Для этого просто добавьте в файл settings.py строку 'django.middleware.cache.CacheMiddleware' вот так:
MIDDLEWARE_CLASSES = (
'django.middleware.cache.CacheMiddleware',
'django.middleware.common.CommonMiddleware',
)
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
}
Кэширование в Memcached отдельных данных.
>>> from django.core.cache import cache
>>> cache.set('my_var', 'hello world', 30)
>>> cache.get('my_var', 'or return My_var has expired')
'hello world'
>>> cache.set('a', 1, 60)
>>> cache.set('b', 2, 60)
>>> cache.set('c', 3, 60)
>>> cache.get_many(['a', 'b', 'c'])
{'a': 1, 'b': 2, 'c': 3}
>>> cache.delete('a')
>>> cache.get_many(['a', 'b', 'c'])
{'b': 2, 'c': 3}
Кэширование в Memcached целых страниц Django.
from django.conf.urls.defaults import patterns, include, url
from django.views.decorators.cache import cache_page
from mysite.myapp.views import my_view
urlpatterns = ('',
(r'^foo/(\d{1,2})/$', cache_page(my_view, 60 * 15)),
)
Кэширование внутри файла views.py
from django.views.decorators.cache import cache_page
@cache_page(60 * 15)
def my_view(request, param):
...
...
...
Кэширование в Memcached всех страниц.
Для этого просто добавьте в файл settings.py строку 'django.middleware.cache.CacheMiddleware' вот так:
MIDDLEWARE_CLASSES = (
'django.middleware.cache.CacheMiddleware',
'django.middleware.common.CommonMiddleware',
)
среда, 6 марта 2013 г.
Django Request
request.method
request.GET['parameter']
request.POST['parameter']
request.COOKIES['cookie_name']
request.session['session_parameter']
request.GET['parameter']
request.POST['parameter']
request.COOKIES['cookie_name']
request.session['session_parameter']
Django Пример использования шаблонной системы отдельно от Django
import django
from django.template import Context, loader
django.conf.settings.configure(TEMPLATE_DIRS = ('/путь/до/папки/с/вашими/шаблонами',))
# Работа в вашим шаблоном.
template = loader.get_template('my_template.html')
context = Context({'problems': info_problems or 'нет',
'plans': info_plans or 'нет',
'done': info_done or 'нет'})
html = template.render(context)
from django.template import Context, loader
django.conf.settings.configure(TEMPLATE_DIRS = ('/путь/до/папки/с/вашими/шаблонами',))
# Работа в вашим шаблоном.
template = loader.get_template('my_template.html')
context = Context({'problems': info_problems or 'нет',
'plans': info_plans or 'нет',
'done': info_done or 'нет'})
html = template.render(context)
Django Создание собственных шаблонных тэгов
Пример собственного шаблонного тэга.
<p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>
Пример создания и регистрации шаблонного тэга.
/templatetags/tags.py
from django import template
def do_current_time(parser, token):
try:
tag_name, format_string = token.split_contents()
except ValueError:
msg = '%r tag requires a single argument' % token..split_contents()[0]
raise template.TemplateSyntaxError(msg)
return CurrenTimeNode(format_string[1:-1])
# token.contents - это current_time "%Y-%m-%d %I:%M %p"
# Метод token.split_contents() отделяет current_time от "%Y-%m-%d %I:%M %p", не трогая строку в кавычках. Избегайте использование стандартного метода разбиения строк по пробелу token.contents.split(), так как такой метод не учитывает кавычки, разбивая все по пробелам.
# Таким образом после token.split_contents(): tag_name = "current_time", format_string = "%Y-%m-%d %I:%M %p".
# token.split_contents()[0] - всегда получает имя вашего тэга. В данном случае это "current_time".
# format_string[1:-1] убирает кавычки из "%Y-%m-%d %I:%M %p". Получается просто %Y-%m-%d %I:%M %p.
# Функция CurrenTimeNode(%Y-%m-%d %I:%M %p) - это наша функция типа Node.
import datetime
class CurrentTimeNode(template.Node):
def __init__(self, format_string):
self.format_string = format_string
def render(self, context):
now = datetime.datetime.now()
return now.strftime(self.format_string)
# Функция __init__() производит компиляцию шаблонного тэга.
# Функция render() производит рендеринг шаблонного тэга.
# Регистрация нашего тэга.
from django import template
register = template.Library()
register.tag('current_time', do_current_time) # 1 - имя тэга, 2 - функция компиляции тэга.
# Альтернативный вариант регистрации шаблонного тэга.
@register.tag('current_time', do_current_time)
def do_current_time(parser, token):
try:
tag_name, format_string = token.split_contents()
except ValueError:
msg = '%r tag requires a single argument' % token.split_contents()[0]
raise template.TemplateSyntaxError(msg)
return CurrenTimeNode(format_string[1:-1])
@register.tag
def shout(parser, token):
pass
# Если вы не укажете аргумент name в @register.tag, то Django будет использовать имя функции в качестве имени тега.
# Полный пример шаблонной библиотеки тэгов.
/templatetags/filters.py
from django import template
register = template.Library()
@register.tag('current_time', do_current_time)
def do_current_time(parser, token):
try:
tag_name, format_string = token.split_contents()
except ValueError:
msg = '%r tag requires a single argument' % token.split_contents()[0]
raise template.TemplateSyntaxError(msg)
return CurrenTimeNode(format_string[1:-1])
@register.tag('shout', shout)
def shout(parser, token):
pass
# Пример двойного шаблонного тэга.
{% upper %}
This will appear in uppercase, {{ your_name }}.
{% endupper %}
from django import template
register = template.Library()
@register.tag
def do_upper(parser, token):
nodelist = parser.parse(('endupper',))
parser.delete_first_token()
return UpperNode(nodelist)
class UpperNode(template.Node):
def __init__(self, nodelist):
self.nodelist = nodelist
def render(self, context):
output = self.nodelist.render(context)
return output.upper()
<p>The time is {% current_time "%Y-%m-%d %I:%M %p" %}.</p>
Пример создания и регистрации шаблонного тэга.
/templatetags/tags.py
from django import template
def do_current_time(parser, token):
try:
tag_name, format_string = token.split_contents()
except ValueError:
msg = '%r tag requires a single argument' % token..split_contents()[0]
raise template.TemplateSyntaxError(msg)
return CurrenTimeNode(format_string[1:-1])
# token.contents - это current_time "%Y-%m-%d %I:%M %p"
# Метод token.split_contents() отделяет current_time от "%Y-%m-%d %I:%M %p", не трогая строку в кавычках. Избегайте использование стандартного метода разбиения строк по пробелу token.contents.split(), так как такой метод не учитывает кавычки, разбивая все по пробелам.
# Таким образом после token.split_contents(): tag_name = "current_time", format_string = "%Y-%m-%d %I:%M %p".
# token.split_contents()[0] - всегда получает имя вашего тэга. В данном случае это "current_time".
# format_string[1:-1] убирает кавычки из "%Y-%m-%d %I:%M %p". Получается просто %Y-%m-%d %I:%M %p.
# Функция CurrenTimeNode(%Y-%m-%d %I:%M %p) - это наша функция типа Node.
import datetime
class CurrentTimeNode(template.Node):
def __init__(self, format_string):
self.format_string = format_string
def render(self, context):
now = datetime.datetime.now()
return now.strftime(self.format_string)
# Функция __init__() производит компиляцию шаблонного тэга.
# Функция render() производит рендеринг шаблонного тэга.
# Регистрация нашего тэга.
from django import template
register = template.Library()
register.tag('current_time', do_current_time) # 1 - имя тэга, 2 - функция компиляции тэга.
# Альтернативный вариант регистрации шаблонного тэга.
@register.tag('current_time', do_current_time)
def do_current_time(parser, token):
try:
tag_name, format_string = token.split_contents()
except ValueError:
msg = '%r tag requires a single argument' % token.split_contents()[0]
raise template.TemplateSyntaxError(msg)
return CurrenTimeNode(format_string[1:-1])
@register.tag
def shout(parser, token):
pass
# Если вы не укажете аргумент name в @register.tag, то Django будет использовать имя функции в качестве имени тега.
# Полный пример шаблонной библиотеки тэгов.
/templatetags/filters.py
from django import template
register = template.Library()
@register.tag('current_time', do_current_time)
def do_current_time(parser, token):
try:
tag_name, format_string = token.split_contents()
except ValueError:
msg = '%r tag requires a single argument' % token.split_contents()[0]
raise template.TemplateSyntaxError(msg)
return CurrenTimeNode(format_string[1:-1])
@register.tag('shout', shout)
def shout(parser, token):
pass
# Пример двойного шаблонного тэга.
{% upper %}
This will appear in uppercase, {{ your_name }}.
{% endupper %}
from django import template
register = template.Library()
@register.tag
def do_upper(parser, token):
nodelist = parser.parse(('endupper',))
parser.delete_first_token()
return UpperNode(nodelist)
class UpperNode(template.Node):
def __init__(self, nodelist):
self.nodelist = nodelist
def render(self, context):
output = self.nodelist.render(context)
return output.upper()
Djnago Создание собственных шаблонных фильтров
/templatetags/filters.py
from django import template
register = template.Library()
# Или традиционно можно записать так:
from django.template import Library
register = Library()
# Регистрация фильтров.
register.filter('cut', cut) # 1 - имя фильтра, 2 - сама функция фильтра.
register.filter('lower', lower) # 1 - имя фильтра, 2 - сама функция фильтра.
# Функция фильтра.
def cut(value, arg): # 1 - значение переменной в шаблоне, 2 - параметр самого фильтра.
"Удаляет все значения аргумента arg из строки value."
return value.replace(arg, '')
# Пример использования нашего фильтра.
# {{ my_var|cut:'0' }}
# Функция фильтра.
def lower(value): # 1 - значение переменной в шаблоне, 2 - параметра самого фильтра нет.
"Преобразовывает регистр строки в строчный."
return value.lower()
# Пример использования нашего фильтра.
# {{ my_var|lower }}
# Альтернативный вариант регистрации фильтров.
@register.filter(name='cut')
def cut(value, arg):
return value.replace(arg, '')
@register.filter
def lower(value):
return value.lower()
# Если вы опустите аргумент name в @register.filter, как это сделано во втором примере, то Django будет использовать имя функции в качестве имени фильтра.
# Полный пример шаблонной библиотеки фильтров.
/templatetags/filters.py
from django import template
register = template.Library()
@register.filter(name='cut')
def cut(value, arg):
return value.replace(arg, '')
@register.filter(name='lower')
def lower(value):
return value.lower()
from django import template
register = template.Library()
# Или традиционно можно записать так:
from django.template import Library
register = Library()
# Регистрация фильтров.
register.filter('cut', cut) # 1 - имя фильтра, 2 - сама функция фильтра.
register.filter('lower', lower) # 1 - имя фильтра, 2 - сама функция фильтра.
# Функция фильтра.
def cut(value, arg): # 1 - значение переменной в шаблоне, 2 - параметр самого фильтра.
"Удаляет все значения аргумента arg из строки value."
return value.replace(arg, '')
# Пример использования нашего фильтра.
# {{ my_var|cut:'0' }}
# Функция фильтра.
def lower(value): # 1 - значение переменной в шаблоне, 2 - параметра самого фильтра нет.
"Преобразовывает регистр строки в строчный."
return value.lower()
# Пример использования нашего фильтра.
# {{ my_var|lower }}
# Альтернативный вариант регистрации фильтров.
@register.filter(name='cut')
def cut(value, arg):
return value.replace(arg, '')
@register.filter
def lower(value):
return value.lower()
# Если вы опустите аргумент name в @register.filter, как это сделано во втором примере, то Django будет использовать имя функции в качестве имени фильтра.
# Полный пример шаблонной библиотеки фильтров.
/templatetags/filters.py
from django import template
register = template.Library()
@register.filter(name='cut')
def cut(value, arg):
return value.replace(arg, '')
@register.filter(name='lower')
def lower(value):
return value.lower()
вторник, 5 марта 2013 г.
Python *args и **kwargs - переменное число аргументов в функциях
В языке Python функциям позволяется принимать разное количество произвольных аргументов, имена которых неизвестны до момента выполнения кода.
Если поместить одну звёздочку * перед параметром в определении функции, то любые неименованные аргументы будут развёрнуты в единый кортеж.
*args - это кортеж (1, 2, 3) со значениями переменных, подставленных в функцию.
Если поместить две звёздочки ** перед параметром в определении функции, то любые именованные аргументы будут развёрнуты в хэш-массив (словарь).
**kwargs - это хэш-массив {'a': 1, 'b': 2, 'c': 3} с ключами и значениями переменных, подставленных в функцию.
Пример.
>>> def foo(*args):
... print(args)
>>> foo(1, 2, 3)
1, 2, 3
>>> def foo(**kwargs):
... print(kwargs)
>>> foo(a = 1, b = 2, c = 3)
{'a': 1, 'b': 2, 'c': 3}
>>> def foo(*args, **kwargs):
... print ("Positional arguments are:")
... print (args)
... print ("Keyword arguments are:")
... print (kwargs)
>>> foo(1, 2, 3, a = 1, b = 2, c = 3)
Positional arguments are:"
1, 2, 3
Keyword arguments are:
{'a': 1, 'b': 2, 'c': 3}
Если поместить одну звёздочку * перед параметром в определении функции, то любые неименованные аргументы будут развёрнуты в единый кортеж.
*args - это кортеж (1, 2, 3) со значениями переменных, подставленных в функцию.
Если поместить две звёздочки ** перед параметром в определении функции, то любые именованные аргументы будут развёрнуты в хэш-массив (словарь).
**kwargs - это хэш-массив {'a': 1, 'b': 2, 'c': 3} с ключами и значениями переменных, подставленных в функцию.
Пример.
>>> def foo(*args):
... print(args)
>>> foo(1, 2, 3)
1, 2, 3
>>> def foo(**kwargs):
... print(kwargs)
>>> foo(a = 1, b = 2, c = 3)
{'a': 1, 'b': 2, 'c': 3}
>>> def foo(*args, **kwargs):
... print ("Positional arguments are:")
... print (args)
... print ("Keyword arguments are:")
... print (kwargs)
>>> foo(1, 2, 3, a = 1, b = 2, c = 3)
Positional arguments are:"
1, 2, 3
Keyword arguments are:
{'a': 1, 'b': 2, 'c': 3}
Django Собственная валидация полей формы
Для добавления собственной валидации полей ввода формы необходимо создать для каждого поля собственный метод проверки, начинающийся со слова clean_ и подставить после него название поля, которое мы хотим проверить.
В результате Django автоматически найдет метод с таким названием и использует его в процессе валидации этого поля формы.
Сначала Django выполнит стандартную валидацию вида: заполнено поле или пусто, а затем выполнит ваш метод clean_, в коде которого будет производится ваша проверка данного поля формы. Если проверка завершится неуспешно, то рядом с полем будет выведено прописанное вами сообщение об ошибке raise forms.ValidationError('Тут ваше сообщение об ошибке.')
Пример.
class ContactForm(forms.Form):
subject = forms.CharField(max_length = 100)
email = forms.EmailField(required = False)
message = forms.CharField(widget = forms.Textarea)
def clean_subject(self):
subject = self.cleaned_data['subject']
num_words = len(message.split())
if num_words < 4:
raise forms.ValidationError('Not enough words!')
return subject
В результате Django автоматически найдет метод с таким названием и использует его в процессе валидации этого поля формы.
Сначала Django выполнит стандартную валидацию вида: заполнено поле или пусто, а затем выполнит ваш метод clean_, в коде которого будет производится ваша проверка данного поля формы. Если проверка завершится неуспешно, то рядом с полем будет выведено прописанное вами сообщение об ошибке raise forms.ValidationError('Тут ваше сообщение об ошибке.')
Пример.
class ContactForm(forms.Form):
subject = forms.CharField(max_length = 100)
email = forms.EmailField(required = False)
message = forms.CharField(widget = forms.Textarea)
def clean_subject(self):
subject = self.cleaned_data['subject']
num_words = len(message.split())
if num_words < 4:
raise forms.ValidationError('Not enough words!')
return subject
понедельник, 4 марта 2013 г.
Django Admin Model
books/admin.py
from django.contrib import admin
class BookAdmin(admin.ModelAdmin):
search_fields = ('first_name', 'last_name',)
list_display = ('first_name', 'last_name', 'email',)
filter_display = ('publication_date',)
date_hierarchy = 'publication_date'
ordering = ('-publication_date',)
fields = ('title', 'authors', 'publisher', 'publication_date',)
filter_horizontal = ('authors',)
filter_vertical = ('authors',)
raw_id_fields = ('publisher',)
admin.site.register(Book, BookAdmin)
from django.contrib import admin
class BookAdmin(admin.ModelAdmin):
search_fields = ('first_name', 'last_name',)
list_display = ('first_name', 'last_name', 'email',)
filter_display = ('publication_date',)
date_hierarchy = 'publication_date'
ordering = ('-publication_date',)
fields = ('title', 'authors', 'publisher', 'publication_date',)
filter_horizontal = ('authors',)
filter_vertical = ('authors',)
raw_id_fields = ('publisher',)
admin.site.register(Book, BookAdmin)
Django Стандарнтый набор файлов в приложении App
/mysite
/books
__init__.py
models.py
views.py
urls.py
admin.py
forms.py
/books
__init__.py
models.py
views.py
urls.py
admin.py
forms.py
Django Русификация Админки
Если английский не является вашим основным языком, то вы можете легко настроить интерфейс администратора на отображение информации на нужном вам языке. Для это в конфигурационном файле добавьте:
'django.middleware.locale.LocaleMiddleware',
в MIDDLEWARE_CLASSES.
Убедитесь, что оно следует после
'django.contrib.sessions.middleware.SessionMiddleware',
После этого перегрузите главную страницу административного интерфейса.
Если присутствует перевод для вашего языка, различные части интерфейса отобразятся на вашем языке вместо английского.
'django.middleware.locale.LocaleMiddleware',
в MIDDLEWARE_CLASSES.
Убедитесь, что оно следует после
'django.contrib.sessions.middleware.SessionMiddleware',
После этого перегрузите главную страницу административного интерфейса.
Если присутствует перевод для вашего языка, различные части интерфейса отобразятся на вашем языке вместо английского.
Django Model Create, Get, Update, Delete
# IMPORT
from mysite.books import Publisher
--------------------------------------------------------------------------
# CREATE
p = Publisher(name='Boris', age = 30)
p.save()
OR
Publisher.objects.create(name='Boris', age=30)
--------------------------------------------------------------------------
# UPDATE
p = Publisher.objects.get(id=1)
p.name = 'Tom'
p.save()
--------------------------------------------------------------------------
# GET
Publisher.objects.all()
Publisher.objects.all()[0:2]
Publisher.objects.get(name='Boris')
Publisher.objects.filter(name__contains='Bor')
Pyblisher.objects.order_by('-name')
--------------------------------------------------------------------------
# DELETE
Publisher.objects.get(name='Boris').delete()
from mysite.books import Publisher
--------------------------------------------------------------------------
# CREATE
p = Publisher(name='Boris', age = 30)
p.save()
OR
Publisher.objects.create(name='Boris', age=30)
--------------------------------------------------------------------------
# UPDATE
p = Publisher.objects.get(id=1)
p.name = 'Tom'
p.save()
--------------------------------------------------------------------------
# GET
Publisher.objects.all()
Publisher.objects.all()[0:2]
Publisher.objects.get(name='Boris')
Publisher.objects.filter(name__contains='Bor')
Pyblisher.objects.order_by('-name')
--------------------------------------------------------------------------
# DELETE
Publisher.objects.get(name='Boris').delete()
пятница, 1 марта 2013 г.
Djnago Русские буквы в браузере
Если в результате выполнения вашего кода Django в браузере не выводятся русские буквы, а выводится абракадабра, то вам необходимо сделать следующее.
Добавьте в файл первой строкой следующий комментарий.
#-*- coding: utf-8 -*-
Сохраните ваш файл в кодировке UTF-8 без BOM.
После этого русские буквы в браузере должны будут появиться.
Пример.
Файл views.py
#-*- coding: utf-8 -*-
from django.http import HttpResponse
def hello(request):
return HttpResponse('Здраувствуй, мир!')
Добавьте в файл первой строкой следующий комментарий.
#-*- coding: utf-8 -*-
Сохраните ваш файл в кодировке UTF-8 без BOM.
После этого русские буквы в браузере должны будут появиться.
Пример.
Файл views.py
#-*- coding: utf-8 -*-
from django.http import HttpResponse
def hello(request):
return HttpResponse('Здраувствуй, мир!')
Djnago Принудительный вывод страницы с отладочной информацией
В контроллере внутри акшон-метода (функции) страницы, которую вы хотите протестировать, чтобы узнать какие параметры ей передаются из формы, вы можете первой строкой прописать assert False. Это приведет к выводу стандартной страницы Django с сообщением об ошибке и всем списком переданных ей параметров.
def function_that_raises_an_exception():
assert False
...
def function_that_raises_an_exception():
assert False
...
Django Debug
Если необходимо иметь информацию о том, что происходит при выполнении функции представления, самым быстрым способом будет поместить в представление оператор print. Сервер разработки выводит результат обработки оператора print напрямую на терминал. Это альтернатива со стороны сервера JavaScript-функции alert().
Django Методы класса Model
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)
class Meta:
pass
class Admin:
pass
def __unicode__():
pass
def __str__():
pass
def get_absolute_url():
pass
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=40)
class Meta:
pass
class Admin:
pass
def __unicode__():
pass
def __str__():
pass
def get_absolute_url():
pass
вторник, 26 февраля 2013 г.
Django Basic Auth Middleware
from django.http import HttpResponse
from django.conf import settings
class BasicAuthMiddleware(object):
def unauthed(self):
response = HttpResponse("""<html><title>Auth required</title><body>
<h1>Authorization Required</h1></body></html>""", mimetype="text/html")
response['WWW-Authenticate'] = 'Basic realm="Development"'
response.status_code = 401
return response
def process_request(self,request):
if not request.META.has_key('HTTP_AUTHORIZATION'):
return self.unauthed()
else:
authentication = request.META['HTTP_AUTHORIZATION']
(authmeth, auth) = authentication.split(' ',1)
if 'basic' != authmeth.lower():
return self.unauthed()
auth = auth.strip().decode('base64')
username, password = auth.split(':',1)
if username == settings.BASICAUTH_USERNAME and password == settings.BASICAUTH_PASSWORD:
return None
return self.unauthed()
Django Basic Auth middleware использует username и password, определенные в файле settings.py через константы BASICAUTH_USERNAME и BASICAUTH_PASSWORD. Данный способ идентификации пользователей не использует Django auth. Однако такой способ достаточно удобен для быстрого сокрытия части сайта на период разработки.
Настройки для примера.
settings.py:
BASICAUTH_USERNAME = 'user'
BASICAUTH_PASSWORD = 'pass'
MIDDLEWARE_CLASSES = (
'app.module.BasicAuthMiddleware',
#all other middleware
)
from django.conf import settings
class BasicAuthMiddleware(object):
def unauthed(self):
response = HttpResponse("""<html><title>Auth required</title><body>
<h1>Authorization Required</h1></body></html>""", mimetype="text/html")
response['WWW-Authenticate'] = 'Basic realm="Development"'
response.status_code = 401
return response
def process_request(self,request):
if not request.META.has_key('HTTP_AUTHORIZATION'):
return self.unauthed()
else:
authentication = request.META['HTTP_AUTHORIZATION']
(authmeth, auth) = authentication.split(' ',1)
if 'basic' != authmeth.lower():
return self.unauthed()
auth = auth.strip().decode('base64')
username, password = auth.split(':',1)
if username == settings.BASICAUTH_USERNAME and password == settings.BASICAUTH_PASSWORD:
return None
return self.unauthed()
Django Basic Auth middleware использует username и password, определенные в файле settings.py через константы BASICAUTH_USERNAME и BASICAUTH_PASSWORD. Данный способ идентификации пользователей не использует Django auth. Однако такой способ достаточно удобен для быстрого сокрытия части сайта на период разработки.
Настройки для примера.
settings.py:
BASICAUTH_USERNAME = 'user'
BASICAUTH_PASSWORD = 'pass'
MIDDLEWARE_CLASSES = (
'app.module.BasicAuthMiddleware',
#all other middleware
)
четверг, 21 февраля 2013 г.
Pixel Perfect возвращение кнопки Add overlay в FireFox
В последних версиях FireFox 13, 14 у Pixel Perfect пропала кнопка "Add overlay".
Для того, чтобы она опять появилась необходимо проделать следующие действия:
- запустить FireFox;
- вызвать Firebug;
- нажать на кнопку "Open Firebug on New Window";
- закрыть FireFox;
- открыть FireFox и вызвать Firebug.
К сожалению, если свернуть Firebug обратно в окно браузера, то кнопка пропадает и нужно проводить данную процедуру еще раз.
Для того, чтобы она опять появилась необходимо проделать следующие действия:
- запустить FireFox;
- вызвать Firebug;
- нажать на кнопку "Open Firebug on New Window";
- закрыть FireFox;
- открыть FireFox и вызвать Firebug.
К сожалению, если свернуть Firebug обратно в окно браузера, то кнопка пропадает и нужно проводить данную процедуру еще раз.
среда, 20 февраля 2013 г.
Django Session Работа с сессиями
# Установить сессионное значение:
request.session["fav_color"] = "blue"
# Получить сессионное значение:
fav_color = request.session["fav_color"]
# Удалить сессионное значение:
del request.session["fav_color"]
# Проверить существует ли сессионное значение с данным ключем:
if "fav_color" in request.session:
...
request.session["fav_color"] = "blue"
# Получить сессионное значение:
fav_color = request.session["fav_color"]
# Удалить сессионное значение:
del request.session["fav_color"]
# Проверить существует ли сессионное значение с данным ключем:
if "fav_color" in request.session:
...
Django Cookie Установка и Получение
views.py
# Get cookie
def favorite_color(request):
if 'favorite_color' in request.COOKIES:
favorite_color = request.COOKIES['favorite_color']
return HttpResponse('Your favorite color is %s' % favorite_color)
else:
return HttpResponse('You don\'t have a favorite color.')
# Set cookie
def set_color(request):
if 'favorite_color' in request.GET:
response = HttpResponse('Your favorite color is %s' % request.GET['favorite_color'])
response.set_cookie('favorite_color', request.GET['favorite_color'])
return response
else:
return HttpResponse('You don\'t have a favorite color.')
# Get cookie
def favorite_color(request):
if 'favorite_color' in request.COOKIES:
favorite_color = request.COOKIES['favorite_color']
return HttpResponse('Your favorite color is %s' % favorite_color)
else:
return HttpResponse('You don\'t have a favorite color.')
# Set cookie
def set_color(request):
if 'favorite_color' in request.GET:
response = HttpResponse('Your favorite color is %s' % request.GET['favorite_color'])
response.set_cookie('favorite_color', request.GET['favorite_color'])
return response
else:
return HttpResponse('You don\'t have a favorite color.')
Django Создание скачиваемого PDF файла
views.py
from reportlab.pdfgen import canvas # НЕОБХОДИМО УСТАНОВИТЬ ОТДЕЛЬНО!!!
from django.http import HttpResponse
def hello_pdf(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=hello.pdf'
# Create the PDF object, using the response object as its "file."
p = canvas.Canvas(response)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
return response
Усложнение файла.
views.py
from cStringIO import StringIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def hello_pdf(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=hello.pdf'
temp = StringIO()
# Create the PDF object, using the StringIO object as its "file."
p = canvas.Canvas(temp)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly.
p.showPage()
p.save()
# Get the value of the StringIO buffer and write it to the response.
response.write(temp.getvalue())
return response
from reportlab.pdfgen import canvas # НЕОБХОДИМО УСТАНОВИТЬ ОТДЕЛЬНО!!!
from django.http import HttpResponse
def hello_pdf(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=hello.pdf'
# Create the PDF object, using the response object as its "file."
p = canvas.Canvas(response)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
return response
Усложнение файла.
views.py
from cStringIO import StringIO
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def hello_pdf(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(mimetype='application/pdf')
response['Content-Disposition'] = 'attachment; filename=hello.pdf'
temp = StringIO()
# Create the PDF object, using the StringIO object as its "file."
p = canvas.Canvas(temp)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly.
p.showPage()
p.save()
# Get the value of the StringIO buffer and write it to the response.
response.write(temp.getvalue())
return response
Django Создание скачиваемого CSV файла
views.py
import csv
data = [146, 184, 235, 200, 226, 251, 299, 273, 281, 304, 203]
def get_csv(request):
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(mimetype = 'text/csv')
response['Content-Disposition'] = 'attachment; filename = data.csv'
# Create the CSV writer using the HttpResponse as the "file."
writer = csv.writer(response)
writer.writerow(['Year', 'Airline Passengers'])
for (year, num) in zip(range(1995, 2006), data):
writer.writerow([year, num])
return response
import csv
data = [146, 184, 235, 200, 226, 251, 299, 273, 281, 304, 203]
def get_csv(request):
# Create the HttpResponse object with the appropriate CSV header.
response = HttpResponse(mimetype = 'text/csv')
response['Content-Disposition'] = 'attachment; filename = data.csv'
# Create the CSV writer using the HttpResponse as the "file."
writer = csv.writer(response)
writer.writerow(['Year', 'Airline Passengers'])
for (year, num) in zip(range(1995, 2006), data):
writer.writerow([year, num])
return response
Django Скачивание файла Image с сайта
import os
from django.http import HttpResponse
def get_image(request):
image_path = os.path.join(os.path.dirname(__file__), 'images/picture.png')
image_file = open(image_path, 'rb')
image_data = image_file.read()
return HttpResponse(image_data, mimetype='image/png')
from django.http import HttpResponse
def get_image(request):
image_path = os.path.join(os.path.dirname(__file__), 'images/picture.png')
image_file = open(image_path, 'rb')
image_data = image_file.read()
return HttpResponse(image_data, mimetype='image/png')
Django Автоматически выбор Developer или Production версии по имени хоста компьютера
# settings.py
import socket
if socket.gethostname() == 'my-laptop':
DEBUG = TEMPLATE_DEBUG = True
else:
DEBUG = TEMPLATE_DEBUG = False
# ...
import socket
if socket.gethostname() == 'my-laptop':
DEBUG = TEMPLATE_DEBUG = True
else:
DEBUG = TEMPLATE_DEBUG = False
# ...
Python Позиционные и именные (ключевые) аргументы функций (*args и **kwargs))
def foo(*args, **kwargs):
print "Positional arguments are:"
print args
print "Keyword arguments are:"
print kwargs
>>> foo(1, 2, 3)
Positional arguments are:
(1, 2, 3)
Keyword arguments are:
{}
>>> foo(1, 2, name='Adrian', framework='Django')
Positional arguments are:
(1, 2)
Keyword arguments are:
{'framework': 'Django', 'name': 'Adrian'}
print "Positional arguments are:"
print args
print "Keyword arguments are:"
print kwargs
>>> foo(1, 2, 3)
Positional arguments are:
(1, 2, 3)
Keyword arguments are:
{}
>>> foo(1, 2, name='Adrian', framework='Django')
Positional arguments are:
(1, 2)
Keyword arguments are:
{'framework': 'Django', 'name': 'Adrian'}
Django Паттерны
Обработка ошибок а полях формы.
Сначала необходимо создать пустой массив, в котором будут храниться сообщения об ошибках.
Далее в цикле необходимо проверить все значения из полей формы.
Если значение в поле формы введено с ошибкой, то в массив ошибок необходимо добавить описание этой ошибки.
После этого в шаблоне необходимо вывести все сообщения об ошибках из массива ошибок, если они есть.
def contact(request):
errors = []
if not request.POST['subject']:
errors.append('Enter a subject.')
if not request.POST['message']:
errors.append('Enter a message.')
if not request.POST['email']:
errors.append('Enter a valid e-mail address.')
if not errors:
send_mail(
request.POST['subject'],
request.POST['message'],
request.POST.get('email', 'noreply@example.com'),
['siteowner@example.com'],
)
return HttpResponseRedirect('/contact/thanks/')
t = loader.get_template('contact_form.html')
c = RequestContext(request, {
'errors': errors,
'subject': request.POST.get('subject', ''),
'message': request.POST.get('message', ''),
'email': request.POST.get('email', ''),
})
renderedTemplate = t.render(c)
return HttpResponse(renderedTemplate)
{% if errors %}
{% for error in errors %}
<p style="color: red;">{{ error }}</p>
{% endfor %}
{% endif %}
Сначала необходимо создать пустой массив, в котором будут храниться сообщения об ошибках.
Далее в цикле необходимо проверить все значения из полей формы.
Если значение в поле формы введено с ошибкой, то в массив ошибок необходимо добавить описание этой ошибки.
После этого в шаблоне необходимо вывести все сообщения об ошибках из массива ошибок, если они есть.
def contact(request):
errors = []
if not request.POST['subject']:
errors.append('Enter a subject.')
if not request.POST['message']:
errors.append('Enter a message.')
if not request.POST['email']:
errors.append('Enter a valid e-mail address.')
if not errors:
send_mail(
request.POST['subject'],
request.POST['message'],
request.POST.get('email', 'noreply@example.com'),
['siteowner@example.com'],
)
return HttpResponseRedirect('/contact/thanks/')
t = loader.get_template('contact_form.html')
c = RequestContext(request, {
'errors': errors,
'subject': request.POST.get('subject', ''),
'message': request.POST.get('message', ''),
'email': request.POST.get('email', ''),
})
renderedTemplate = t.render(c)
return HttpResponse(renderedTemplate)
{% if errors %}
{% for error in errors %}
<p style="color: red;">{{ error }}</p>
{% endfor %}
{% endif %}
вторник, 19 февраля 2013 г.
Django Регистрация таблиц базы данных в админке
Файл models.py
from django.db import models
import datetime
# Таблица базы данных и функции для работы над ее данными.
class Poll(models.Model):
question = models.CharField(max_length = 200)
pub_date = models.DateTimeField('date published')
def __unicode__(self):
return self.question
def was_published_today(self):
return self.pub_date.date() == datetime.datetime.today()
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice = models.CharField(max_length = 200)
votes = models.IntegerField()
def __unicode__(self):
return self.choice
Файл admin.py
from models import Poll # Импортирует класс таблицы базы данных.
from django.contrib import admin
class PollAdmin(admin.ModelAdmin):
fields = ['pub_date', 'question'] # Задает порядок расположения полей в админке
admin.site.register(Poll, PollAdmin) # Регистрирует таблицу базы данных для появления в админке.
В результате регистрации класса таблицы Poll базы данных в админке появится пункт меню Polls, который позволит редактировать данные таблицы Polls.
from django.db import models
import datetime
# Таблица базы данных и функции для работы над ее данными.
class Poll(models.Model):
question = models.CharField(max_length = 200)
pub_date = models.DateTimeField('date published')
def __unicode__(self):
return self.question
def was_published_today(self):
return self.pub_date.date() == datetime.datetime.today()
class Choice(models.Model):
poll = models.ForeignKey(Poll)
choice = models.CharField(max_length = 200)
votes = models.IntegerField()
def __unicode__(self):
return self.choice
Файл admin.py
from models import Poll # Импортирует класс таблицы базы данных.
from django.contrib import admin
class PollAdmin(admin.ModelAdmin):
fields = ['pub_date', 'question'] # Задает порядок расположения полей в админке
admin.site.register(Poll, PollAdmin) # Регистрирует таблицу базы данных для появления в админке.
В результате регистрации класса таблицы Poll базы данных в админке появится пункт меню Polls, который позволит редактировать данные таблицы Polls.
Django Admin Static files UnicodeDecodeError Windows
Если вы работаете в Windows, используете Python 2.7, Django 1.3 и при загрузке админки по адресу http://127.0.0.1:8000/admin/ не подгружаются стили, а при переходе по адресу http://127.0.0.1:8000/static/admin/css/base.css вы видите внизу страницы сообщение об ошибке:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe0 in position 0: ordinal not in range(128)
То это означает, что в реестре Windows находятся кирилические символы. Обычно они попадают туда после установки QuickTime.
Баг, описанный в данной статье, касается только Python 2.7, в котором модуль mimetypes стал обращаться к реестру Windows для пополнения собственной базы mime-типов. В предыдущих версиях Python этого не было.
Для устранения данной проблемы вам необходимо нажать в Windows на кнопку Пуск (Start) и выбрать опцию Выполнить (Run).
Далее в появившемся окне введите regedit и нажмите на кнопку OK.
В результате откроется окно редактора реестра Windows.
В этом окне вам необходимо раскрыть последовательность папок
HKEY_CLASSES_ROOT\MIME\Database\Content Type
Внутри папки Content Type в само низу вы найдете папки, имеющие русские буквы в названии, такие как "аудио" и "видео".
Например.
аудио/AMR
аудио/x-gsm
видео/x-m4v
Вы должны удалить эти папки или исправить их названия, заменив русские символы на английские. Например, "audio" и "video".
После этого исправления стили для оформления админки Django станут подгружаться.
(Для тех у кого в registry Windows 7 нет русских символов, но проблема осталась, переименуйте сетевое имя компьютера с русского на английский язык. )
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe0 in position 0: ordinal not in range(128)
То это означает, что в реестре Windows находятся кирилические символы. Обычно они попадают туда после установки QuickTime.
Баг, описанный в данной статье, касается только Python 2.7, в котором модуль mimetypes стал обращаться к реестру Windows для пополнения собственной базы mime-типов. В предыдущих версиях Python этого не было.
Для устранения данной проблемы вам необходимо нажать в Windows на кнопку Пуск (Start) и выбрать опцию Выполнить (Run).
Далее в появившемся окне введите regedit и нажмите на кнопку OK.
В результате откроется окно редактора реестра Windows.
В этом окне вам необходимо раскрыть последовательность папок
HKEY_CLASSES_ROOT\MIME\Database\Content Type
Внутри папки Content Type в само низу вы найдете папки, имеющие русские буквы в названии, такие как "аудио" и "видео".
Например.
аудио/AMR
аудио/x-gsm
видео/x-m4v
Вы должны удалить эти папки или исправить их названия, заменив русские символы на английские. Например, "audio" и "video".
После этого исправления стили для оформления админки Django станут подгружаться.
(Для тех у кого в registry Windows 7 нет русских символов, но проблема осталась, переименуйте сетевое имя компьютера с русского на английский язык. )
Подписаться на:
Сообщения (Atom)