Устанавливаем django на denwer

1. Устанавливаем Python (желательно, версию 2.7).
2. Правой кнопкой по «Мой компьютер» => Свойства =>
=> Вкладка «Дополнительно» => Кнопка «Переменные среды» =>
=> В «Системные переменные» выбираем строку, где слева написано «Path» =>
=> Кнопка «Изменить» => в самый конец вставляем строку
«;C:\Python27\;C:\Python27\Scripts» без кавычек.
3. Везде жмем ОК.
4. Качаем и распаковываем архив с Django.
5. Открываем cmd и переходим в папку с Django.
6. Набираем «setup.py install».
7. Ждем установки.
8. Проверяем, набрав в консоли «python», затем «import django» и
«print django.get_version()». Если ошибок нет — значит, мы все сделали правильно.
9. Устанавливаем Denwer.
10. Файл «mod_wsgi.so» копируем в папку «Z:\usr\local\apache\modules».
11. В файле «Z:\usr\local\apache\conf\httpd.conf» после строк «LoadModule»
вставляем строку «LoadModule wsgi_module modules/mod_wsgi.so».
12. На этом установка закончена, для настройки самого проекта обратитесь к документации

Безопасный eval в python

Об этом уже достаточно много сказано, но может и мой вариант кому-то приглянется. Обычно запрещают список опасных функций для eval’а. Можно пойти чуть по другому пути и наоборот, разрешить, что-то. Я набросал пример, цель которого была — вычисление математических выражений. Чтобы было не так скучно, сделал это в django через аякс 🙂

Итак, views.py
[code lang=»python»]
import re, json
from django.shortcuts import render_to_response
from django.http import HttpResponse

#…

def calc(request):
return render_to_response(‘calc.html’, {})

def calc_json_expression(request):
p = re.compile(r'[-+*\/\(\)0-9(sin)(cos)(tan)]*’, re.IGNORECASE)
calcmath = request.POST["calc-math"]
res = ».join(p.findall(calcmath))
from math import sin, cos, tan
json_data = {}
try:
json_data[‘exp’] = res
json_data[‘res’] = eval(res)
except:
json_data[‘exp’] = »
json_data[‘res’] = ‘0’
return HttpResponse(json.dumps(json_data), mimetype="application/json")
[/code]

urls.py
[code lang=»python»]
urlpatterns = patterns(‘kernel.views’,
# …
url(r’^calc/$’, ‘calc’),
url(r’^calc-json-expression/$’, ‘calc_json_expression’),
)
[/code]

и файл шаблона calc.html
[code lang=»html»]
<!DOCTYPE html>
<html>
<head>
<title></title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</head>
<body>
<h1>Calc</h1>
<form method="post" id="calc-form">
<p><label for="calc-math">Print math expression</label><input type="text" name="calc-math" id="calc-math" value="" placeholder="Expression"></p>
<p>Expression: <span id="calc-math-expression"></span></p>
<p>Result: <span id="calc-math-answer">0</span></p>
</form>

<script type="text/javascript">
$(‘#calc-math’).keyup(function() {
$.post(‘calc-json-expression/’, $("#calc-form").serialize(),function(data){
$(‘#calc-math-answer’).text(data["res"]);
$(‘#calc-math-expression’).text(data["exp"]);
}, "json");
});
</script>
</body>
</html>
[/code]

Самое интересное во всем этом коде — выбор допустимых символов и слов регулярным выражением. Сюда можно добавить и другие выражения, но принцип должен быть понятен.

[code lang=»python»]
p = re.compile(r'[-+*\/\(\)0-9(sin)(cos)(tan)]*’, re.IGNORECASE)
[/code]

Собственно, это и есть мой способ, подобных при поиске «безопасный eval» не увидел. Проблема, с которой столкнулся — это ограничение на время исполнения скрипта. Такой штуки нет ни в джанго, ни в питоне. Поэтому 10 в миллиардной степени, например, этот скрипт не обработает, а сайт просто упадет. Есть решения, интернет ими кишит, но они, в основном, только для *nix, либо практически нерабочие. Если кто-то найдет кроссплатформенный рабочий код — отпишитесь, пожалуйста 🙂

Свои сообщения об ошибках при валидации формы в Django

Думаю, вы хотите, чтобы ваши сообщения об ошибках в заполняемых формах были на том же языке, что и сам сайт. Один из простых способов — это добавить следующий код в соответствующий forms.py. Затем формы надо будет наследовать не от forms.Form, а от MyForm (обратите внимание, ExampleForm, в примере ниже, наследуется от него).

[code lang=»python»]
class MyForm(forms.Form):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
for k, field in self.fields.items():
if ‘required’ in field.error_messages:
field.error_messages[‘required’] = u’Это поле обязательно!’

class ExampleForm(MyForm):
title = forms.CharField(max_length=100, required=True, label=u’Название’)
[/code]

Полный список error_messages для различных типов полей можно увидеть, если просмотреть этот раздел: https://docs.djangoproject.com/en/1.3/ref/forms/fields/#built-in-field-classes

Вот что есть на данный момент:

  • required — показывается, если данное поле обязательно;
  • max_length — если превышено максимальное количество символов в символьном поле / в случае с файлами — длина имени файла;
  • min_length — если символов меньше, чем должно быть, в символьном поле;
  • invalid_choice — если выбран невозможный choice;
  • invalid — при неправильном email’е и прочем неправильном вводе данных;
  • max_value — если превышено числовое значение;
  • min_value — если значение меньше минимального числового ограничения;
  • max_digits — если превышено количество цифр в числе;
  • max_decimal_places — если превышено количество цифр после запятой;
  • max_whole_digits — если превышено количество цифр до запятой;
  • missing — если файл не найден;
  • empty — если файл пустой;
  • invalid_image — если изображение повреждено;
  • invalid_list  — если неправильный список choice’ов;
  • invalid_link — для URLField — вызывается, если данного url не существует.

Основано на примере с http://stackoverflow.com/questions/1481771/django-override-default-form-error-messages

CSRF token missing or incorrect (django)

После переноса сайта с хостинга jino на webfaction, при попытке отправки любой формы возникала ошибка «CSRF token missing or incorrect». Т.е. даже залогиниться на сайт было невозможно (авторизация через админку работала нормально и на сайте после я этого был авторизован).

CSRF — это уязвимость, когда пользователи, переходя по обычной ссылке, запускают хакерский скрипт, который может от их имени передать какую-либо форму на абсолютно другой сайт (например, оставить от их имени комментарий на одном из форумов или еще что-нибудь). Сам хакер не сможет получить результат перехода по ссылке. Собственно, это и отличает CSRF от XSS (http://www.securitylab.ru/analytics/292473.php).

Все описания этой ошибки ссылаются на документацию — https://docs.djangoproject.com/en/dev/ref/contrib/csrf/, либо советом добавлять во всех формах {% csrf_token %} в темплейтах (у меня он везде добавлен) и проверить, есть ли в settings.py в MIDDLEWARE_CLASSES пункт ‘django.middleware.csrf.CsrfViewMiddleware’. Это все было. И не помогало.

Выход нашел, когда сравнил MIDDLEWARE_CLASSES от вебфакшна и джино.

webfaction:
[code lang=»python»]
MIDDLEWARE_CLASSES = (
‘django.middleware.common.CommonMiddleware’,
‘django.contrib.sessions.middleware.SessionMiddleware’,
‘django.middleware.csrf.CsrfViewMiddleware’,
‘django.contrib.auth.middleware.AuthenticationMiddleware’,
‘django.contrib.messages.middleware.MessageMiddleware’,
)
[/code]
jino:
[code lang=»python»]
MIDDLEWARE_CLASSES = (
‘django.middleware.common.CommonMiddleware’,
‘django.contrib.sessions.middleware.SessionMiddleware’,
‘django.contrib.auth.middleware.AuthenticationMiddleware’,
)
[/code]

Поменяв на джиновские миддлвары — все запустилось и заработало нормально. Т.е., получилось, что ‘django.middleware.csrf.CsrfViewMiddleware’, в моем случае, не должна была быть в списке. Хотя, возможно, что после ее удаления, джанго просто не показывает ошибку, а уязвимость осталась. По крайней мере, на данный момент, проблему это решило. При следующей встрече, постараюсь решить эту проблему правильней, на данный момент знаний по этой теме не хватает.

Подключение TinyMCE в админку django

Для того, чтобы в админке подключить WYSIWYG-редактор TinyMCE необходимо проделать следующие операции.

1. Скачиваем сам редактор TinyMCE: http://www.tinymce.com/download/download.php и заливаем на сервер (со стороннего url работать не будет).

2. Устанавливаем django-tinymce (обязательно должен быть версии 1.5.1a2 или выше, в стабильной на момент написания статьи версии 1.5 он имеет баг, из-за которого не хочет работать без напильника):

[code]
pip install django-tinymce
[/code]

3. В settings.py вашего проекта записываем записываем следующие переменные:
[code lang=»python»]
TINYMCE_JS_URL = ‘tiny_mce/tiny_mce.js’
TINYMCE_JS_ROOT = ‘tiny_mce’
TINYMCE_DEFAULT_CONFIG = {‘theme’: "advanced", ‘theme_advanced_toolbar_location’ : "top", ‘height’: ‘400’}
[/code]

TINYMCE_JS_URL — путь к tiny_mce.js — например, http://mysite.com/tinymce/tiny_mce.js (крайне желательно писать без домена, он здесь дан только для того, чтобы было понятно, относительно чего происходит запрос)

TINYMCE_JS_ROOT — путь к корневой папке, где лежит tiny_mce.js — например, http://mysite.com/tinymce/ (крайне желательно писать без домена)

TINYMCE_DEFAULT_CONFIG — конфигурация по умолчанию, подробности см. в официальной документации TinyMCE.

Также, в INSTALLED_APPS надо дописать ‘tinymce’:
[code lang=»python»]
INSTALLED_APPS = (

‘tinymce’,

)
[/code]

4. В модель, в которой хотим включить редактор TinyMCE импортируем tinymce:

[code lang=»python»]
from tinymce import models as tinymce_models
[/code]

Для самого класса модели пишем следующее

[code lang=»python»]
class MyModel(models.Model):
myField = tinymce_model.HTMLField()
[/code]

Т.е. мы заменяем models.TextField() на tinymce_model.HTMLField() в необходимых местах.

5. В urls.py проекта добавляем (r’^tinymce/’,include(‘tinymce.urls’)):

[code lang=»python»]
urlpatterns = patterns(‘myproject.views’,

(r’^tinymce/’, include(‘tinymce.urls’)),
(r’^admin/’, include(admin.site.urls)),
)
[/code]

Источники:
1. http://seobacks.ru/tinymce-django.html
2. http://django-tinymce.googlecode.com/svn/tags/release-1.5/docs/.build/html/index.html

«Читать далее» в django

Часто бывает нужно организовать новости, блог, какие-то статьи. Для этого обычно используют небольшой вступительный текст и ссылку «Читать далее».

Если вы используете HTML-тэги в своих статьях, то заметите, что Django не закрывает их при использовании фильтра truncatewords.

Пример реализации

Если вы хотите запретить HTML-тэги только в этом вступительном тексте, а также картинки, видео и прочее, то можно пойти следующим путем. В необходимом файле шаблона, в требуемой переменной примените фильтр striptags, затем truncatewords, затем safe (для правильной обработки HTML-символов):

[code]
{{ news.description|striptags|truncatewords:"30"|safe }}
[/code]

Получится, например, такой текст — «Как все мы помним, после The International все датские игроки из MYM покинули эту организацию и им на замену была взята команда Scythe.SG. Вчера стало известно, что состав снова претерпел серьезные …». Протестировано на Django 1.3.

Также, если у вас пробелы представлены в виде
[code lang=»html»]&nbsp;[/code]
то приведенный выше метод может не работать. Для решения проблемы используйте фильтр truncatewords-html. Таким образом, код будет вида:

[code]
{{ news.description|truncatewords_html:"30"|safe }}
[/code]

Как видите, мы еще убрали фильтр striptags.

Уникальные названия файлов при загрузке в Django

Django при сохранении файла через админку или форму сохраняет название файла. Например, при загрузке картинки «mypic.jpg» она сохранится с этим названием.
Также, если загружаемый файл на русском языке, то его имя будет сохранено — «моя_картинка.jpg». Вы можете изменить этот механизм.

ПРИМЕЧАНИЕ. Последующие загружаемые файлы с таким названием будут иметь префикс «_», т.е. «_mypic.jpg», «__mypic.jpg» и т.п.

Пример реализации

Этот код должен быть помещен в файл models.py нужного вам приложения.

[code lang=»python»]
import os, uuid

def get_file_path(instance, filename):
ext = filename.split(‘.’)[-1]
filename = "%s.%s" % (uuid.uuid4(), ext)
return os.path.join(instance.directory_string_var, filename)

class MyModelFiles(models.Model):
myimage = models.FileField(upload_to = get_file_path)
directory_string_var = ‘my-path-to-files-for-this-model’

class MyModelImages(models.Model):
myimage = models.ImageField(upload_to = get_file_path)
directory_string_var = ‘my-path-to-images-for-this-model’
[/code]

Таким образом, при следующей загрузке файла его имя будет выглядеть, например, так «384408e1-5465-46fd-bf47-61f913fa78e5.jpg».
Протестировано на версии Django 1.3.

Источник:
Ответ на вопрос на stackoverflow

Делаем правильные имена загружаемых картинок в django

Как известно, джанго при загрузке файла сохраняет его имя. Т.е. в имени файла вполне могут быть русские буквы — мы от этого не защищены. Я считаю, что лучше организовать изображения на сайте по хэшам или uuid. Это делается довольно просто, благодаря тому, что в джанго путь к картинке и имя файла можно генерировать функцией.

Давайте посмотрим, как это сделать.

[code lang=»python»]
import os, uuid

def get_file_path(instance, filename):
ext = filename.split(‘.’)[-1]
filename = "%s.%s" % (uuid.uuid4(), ext)
return os.path.join(instance.directory_string_var, filename)

class MyModel(models.Model):
myimage = models.FileField(upload_to = get_file_path)
directory_string_var = ‘my-path-to-images-for-this-model’
[/code]

Таким образом, при следующей загрузке файла его имя будет выглядеть, например, так «384408e1-5465-46fd-bf47-61f913fa78e5.jpg».

Встретился с данным решением на интересном англоязычном ресурсе stackoverflow.