понедельник, 30 декабря 2013 г.

Альтернатива PIL (Python Image Library)

В последнее время у меня стали возникать проблемы с PIL при разработке под Windows. Как только в django я создаю модель с ImageField, возникает ошибка:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xed in position 20: ordinal not in range(128)

Вникать в суть проблемы не стал, вместо PIL установил пакет Pillow.
После установки Pillow под Windows 7 приведенная выше ошибка исчезла и я, наконец, смог создать модель, содержащую ImageField.

среда, 18 декабря 2013 г.

Минификация javascript файлов на python

Одним из методов увеличения скорости загрузки страницы является минификация javascript-файлов, при которой из файла удаляются комментарии, пробелы, переносы строк.
На python есть модуль jsmin, легко позволяющий сделать это. Скачайте этот модуль и достаньте из архива папку jsmin с кодом модуля.

воскресенье, 10 ноября 2013 г.

Изучаем Python на конкретном примере

Есть отличное видео, где на конкретном примере показывается, как Python может сыграть полезную роль. Как говорится, лучше один раз увидеть, чем сто раз услышать.


четверг, 7 ноября 2013 г.

Валидация форм в Django

Пусть у нас есть простая форма регистрации пользователя в системе на Django. Для того, чтобы пользователь мог зарегистрироваться, нужно предоставить ему возможность указать логин и пароль:

вторник, 29 октября 2013 г.

Веб-форма средствами Django

В статье Простейшая форма на Django мы научились создавать и обрабатывать форму сложным путем, прописывая все детали. Там мы выяснили, что при большом количестве полей такой способ чреват ошибками. Поэтому сейчас мы научимся создавать форму обратной связи средствами Django, используя Django forms.

четверг, 24 октября 2013 г.

Простейшая форма на Django

Принцип работы простейшей формы Django изображен на рисунке:
Данные при отправке формы помещаются в объект request.POST.

пятница, 27 сентября 2013 г.

Получить json из файла в кодировке utf-8

Если ваш json файл имеет корректный json и вы по-прежнему получаете ошибку "ValueError: No JSON object could be decoded", то, возможно, проблема в кодировке.

1. Создайте файл my_json.txt:
{
    "banks":
    [
        {
            "name": "Trust Bank",
            "atms": 
            [
                {
                    "longitude": "40.1222",
                    "latitude": "22.1222"
                }
                ,
                {
                    "longitude": "42.1222",
                    "latitude": "33.1222"
                }
            ]
        }
        ,
        {
            "name": "Invest Bank",
            "atms": [
                {
                    "longitude": "40.1222",
                    "latitude": "22.1222"
                }
            ]
        }
    ]
}


2. Переведите файл в кодировку utf-8. Если вы используете notepad++, то сделать это можно через меню "Кодировки" > "Преобразовать в UTF-8".
3. Наша задача - получить данные из этого файла, содержащего данные в формате json. В той же директории создадим файл import_json.py:
#-*- coding:utf-8 -*-

import json

json_file = open('my_json.txt')

# Вот эта строка решает проблему с кодировкой
content = json_file.read().decode("utf-8-sig")

data = json.loads(content)

for key in data:
    banks = data[key]
    for bank in banks:
        print bank['name']


4. Запустим файл import_json.py. Программа выведет:
Trust Bank
Invest Bank

В переменной data у нас будет словарь, содержащий данные из файла. Получение данных из json-файла в кодировке utf-8 прошло успешно, т.к. мы сказали python-у, что файл имеет эту кодировку.

пятница, 20 сентября 2013 г.

Вывести список чисел Фибоначчи и проверить unittest-ом

Задача. Напишите функцию, которая принимает на вход индекс числа в ряде Фибоначчи (0, 1, 1, 2, 3, 5, 8, 13, 21, ... - последующее число равно сумме двух предыдущих), а выводит список чисел этого ряда с 0 до указанного индекса включительно.
Пример:
get_fibonacci_list(0) вернет [0]
get_fibonacci_list(1) вернет [0, 1]
get_fibonacci_list(3) вернет [0, 1, 1, 2]

среда, 10 июля 2013 г.

Создание меню сайта в Django

Вот есть у нас простой Сайт о костюмах для танцев живота:

Рис. 1

Нам нужно, чтобы владелец сайта мог сам редактировать пункты меню через админку Django. Для этого мы используем стороннее приложение django-menu.

четверг, 4 июля 2013 г.

MEDIA_ROOT и MEDIA_URL в Django

Параметры MEDIA_ROOT и MEDIA_URL нужны для указания места хранения файлов, загруженных пользователями.
Вот, что написано в комментариях к данным параметрам в settings.py:
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/var/www/example.com/media/"
MEDIA_ROOT = 'media/'

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://example.com/media/", "http://media.example.com/"
MEDIA_URL = 'http://127.0.0.1:80/media/'

Но все хорошо, если сайт у нас запущен по адресу http://127.0.0.1:80/. Попробовал я запустить его по адресу http://192.168.0.5/, чтобы сделать доступным для компьютеров моей локальной сети, как все картинки перестали отображаться:




среда, 26 июня 2013 г.

Настройка роутов, путей в urls.py фреймворка Django

Пусть мы только что создали проект project. В нем сделали приложение articles, в котором намереваемся хранить статьи. При этом мы хотим, чтобы при обращении в браузере по адресу http://127.0.0.1:8000/ у нас загружались urls.py этого приложения articles.

Вот главные роуты проекта: project/urls.py:

# ... начальные настройки

urlpatterns = patterns('',
    # подключаем настройки роутов приложения article
    url(r'', include('article.urls')),

    url(r'^admin/doc/', include('django.contrib.admindocs.urls')),

    url(r'^admin/', include(admin.site.urls)),
)

четверг, 6 июня 2013 г.

'ManyRelatedManager' object is not iterable

Чтобы исправить эту ошибку, не нужно делать в шаблоне так:

{% for contest in winner.contest %}
    {{ contest.title }}
{% endfor %}

Нужно делать так:
{% for contest in winner.contest.all %}
    {{ contest.title }}
{% endfor %}

Это выражение winner.contest.all позволяет в шаблоне Django получить все элементы связанной модели (тип связи ManyToMany).
Вот так выглядит модель Winner:
class Winner(models.Model):
    # ... поля модели
    # значения этого поля мы хотели получить в шаблоне
    contest = models.ManyToManyField(Contest, verbose_name=u'Конкурс')


понедельник, 3 июня 2013 г.

Статический метод модели в Django: @staticmethod, @classmethod

Представим, что в нашем Django-проекте есть модель Конкурс (Contest). Конкурс ежегодный, поэтому характеризующая его модель будет иметь атрибут year.
Как же нам в классах представлений получить год последнего прошедшего конкурса?
Конечно! Написать для модели Contest метод, который будет возвращать этот год.
Метод должен быть статическим, т.е. для его вызова нам вовсе будет не нужно создавать экземпляр класса Contest.

Reverse for '*' with arguments '()' and keyword arguments '{u'pk': ''}' not found

Ошибка эта была получена, когда я попытался вывести на страницу список коллекций одежды для определенного года. Причина этой ошибки в том, что в шаблоне тэг {% url ... %} получал для pk пустое значение. В сообщении об ошибке был показан проблемный фрагмент шаблона:

{% for collection in collection_list %}
<li>
    <a>
        {{ collection.title }}
    </a> ( {{ collection.author.all|join:', ' }} )
</li>
{% endfor %}

среда, 29 мая 2013 г.

Отладка приложений в Django

Если в PHP, чтобы узнать значение переменной в том или ином месте кода, мы применяем echo, var_dump( ), print_r( ), то в фреймворке Django в коде моделей (models.py) или представлений (views.py) мы можем два метода: print и assert False, myvar

суббота, 25 мая 2013 г.

Показать название ManyToMany полей в админке Django

Есть у нас модель Collection. Коллекция может быть задействована в нескольких номинациях, поэтому связь здесь ManyToMany.

В админке эта модель будет отображаться так:


 Чтобы колонка появилась, нужно проделать пару шагов...

Как получить из списка первый элемент в шаблоне Django

Имеется модель Коллекция. У коллекции может быть несколько фотографий. Возникла необходимость в шаблоне, в котором уже получен список фотографий коллекции выводить только первую фотографию. Как это сделать?

1. В шаблоне Django можно проделать манипуляцию с тэгом with и фильтром first:

{% with attachments_list|first as attachment %}

    

{{ attachment.filename }}

{% endwith %}

2. Непосредственно обратиться к элементу списка по индексу. Это позволяет отобразить элемент с любым индексом:

{% with attachments_list.0 as attachment %}

    

{{ attachment.filename }}

{% endwith %}

пятница, 24 мая 2013 г.

inclusion_tag или Как отображать повторяющиеся блоки в шаблоне Django

Очень часто возникает необходимость отобразить в шаблоне Django повторяющиеся элементы. В нашем примере это будут призеры конкурса:


Как грамотно написать код для вывода повторяющихся элементов?

четверг, 23 мая 2013 г.

Как настроить MEDIA_ROOT и MEDIA_URL в Django

Параметры MEDIA_ROOT и MEDIA_URL показывают, куда будут складываться файлы, загружаемые пользователями вашего Django-сайта.
Но как их правильно настроить?

понедельник, 20 мая 2013 г.

Отображение ForeignKey в админке Django

Есть у нас модель Конкурс:
class Contest(models.Model):
    """
    Конкурс, проводимый ежегодно
    """
    title = models.CharField(max_length=200, verbose_name='Название конкурса')
    year = models.SlugField(unique=True, max_length=4, verbose_name='Год конкурса')
    description = models.TextField(verbose_name='Описание конкурса')

    def __unicode__(self):
        return unicode(self.year + " " + self.title)
        
    class Meta:
        verbose_name = 'Конкурс'
        verbose_name_plural = 'Конкурсы'
Допустим мы хотим использовать ее в модели Призер:
class Prizer(models.Model):

    contest = models.ForeignKey(Contest, verbose_name=u'Конкурс')
    # другие поля...
        
    class Meta:
        verbose_name = 'Призер'
        verbose_name_plural = 'Призеры'
Вот как в админке Django отобразится модель Prizer и поле contest:

Для того, чтобы эти записи в выпадающем списке были отсортированы по-порядку, в классе Contest добавим:
class Contest(models.Model):
    # все то же, что написано выше
        
    class Meta:
        # ...
        #вот эта магическая строчка для сортировки:
        ordering = ('year',)
После этого записи будут отсортированы в используемом поле ForeignKey по-порядку:

четверг, 16 мая 2013 г.

Декораторы в python

Взгляните на этот чудо-код с декоратором @amazed:
def amazed(func):
    def wrap():
        return func() + 'aaa!'

    return wrap

@amazed  
def hey():
    return 'hey'

print hey() # 'heyaaa!'
Эта запись позволяет заменить следующий код:
def amazed(func):
    # определяем функцию-обертку
    def wrap():
        # выполняем переданную функцию - func(). 
        # К результату подсоединяем строку 'aaa!'
        return func() + 'aaa!'
    # возвращаем объект функции wrap
    return wrap
    
def hey():
    return 'hey'
  
hey = amazed(hey)   

print hey()
Таким образом, декоратор @amazed позволил нам, не тронув кода функции hey(), изменить ее поведение и сделать так, чтобы к слову 'hey' добавлялась строка 'aaa!'

Зачем в python обрабатывать ошибки?

Все познается из практики. Будет ли показано 'hello':
def shout(word=u'yes'):
    return word.capitalize()+'!'
    
scream = shout

del shout
print shout()
print 'Hello'
Переменную shout мы удалили, поэтому будет ошибка. Выполнение скрипта остановится, слово 'hello' показано не будет.
Но в python есть блок try/catch/finally, который позволяет обработать ошибку и дать скрипту шанс выполняться дальше.
def shout(word=u'yes'):
    return word.capitalize()+'!'
    
scream = shout

del shout

# Мы заранее предвидим, что функцию
# shout() мог удалить какой-то касатик
try:
    print shout()
except NameError, e:
    print e
print 'Hello'
В этом случае будет выведено:
name 'shout' is not defined
Hello

воскресенье, 5 мая 2013 г.

Django и fixtures

Раньше я для разработки использовал базу данных sqlite3. И это было ошибкой, т.к.
1. в продакшене я применял другую базу данных - MySQL
2. возможности sqlite3 слишком ограничены, что не позволяло мне использовать south в своих разработках.

Теперь я по совету западных разработчиков использую в своих проектах PostgreSQL.
Кстати, я был привязан к sqlite потому, что это удобно сохранить данные разрабатываемого сайта в одном файлике mysite.sqlite3, потом скинуть папку с проектом на другой компьютер, запустить там manage.py runserver и... вуаля - сайт работает!
Но оказывается в django есть возможность сделать так, чтобы данные автоматически вставлялись в базу данных при syncdb проекта.
Для этого существуют fixtures - представления данных ваших приложений в форматах .json/.xml/.yaml

Дамп базы данных в файл фикстур

python manage.py dumpdata --format=json myapp > myapp/fixtures/initial_data.json

По умолчанию фикстуры нужно хранить в папке fixtures, которую нужно создать внутри каждого приложения.
Если фикстуры сохраняются в файл с названием initial_data, то при каждом syncdb фикстуры будут загружаться в базу данных вашего проекта.

Загрузка фикстуры из файла

python manage.py loaddata myapp/fixtures/myfix.json

Здесь мы вручную загружаем в базу данных приложения myapp данные, сохраненные в файле myfix.json

суббота, 4 мая 2013 г.

PostgreSQL против MySQL

В своих проектах я всегда использовал MySQL и не задумывался, что может быть что-то лучше. Недавно услышал, что есть другая база данных и что она якобы гораздо удобнее. Многие разработчики Django используют в своей работе именно PostgreSQL. Данное видео поможет вам понять - хотите вы использовать MySQL или нет.



После просмотра этого видео я решил перейти на использование в проекте своего сайта http://yesnik.ru базы данных PostgreSQL.

пятница, 5 апреля 2013 г.

Template context processor для создания меню в Django

Для создания меню в Django можно использовать контекстный процессор - template context processor.
Он позволяет передавать в шаблон определенную вами переменную.
Пусть у нас есть модель статей Article. Каждая статья имеет категорию Category. Мы хотим, чтобы на каждой странице выводился список из категорий, представляющий собой меню. При клике на категорию мы переходим на страницу со списком статей данной категории.

воскресенье, 31 марта 2013 г.

Передаем в шаблон переменные из class based view

Пусть у нас есть class based view для отображения списка статей. Данное представление размещено в файле views.py:

from django.views.generic import DetailView, ListView
from article.models import Article


class ArticleListView(ListView):

    model = Article

    def get_queryset(self):

        tag = self.kwargs['tag']
        return Article.objects.filter(tag__tag_url=tag)


    def get_context_data(self, *args, **kwargs):

        context = super(ArticleListView, self).get_context_data(**kwargs)
        context['my_var'] = 'Это моя переменная'
        return context

Благодаря функции get_context_data(), можно передать в шаблон дополнительные переменные.
В этом примере в шаблоне окажется доступна переменная my_var, которую в шаблоне можно получить так: {{ my_var }}

Получить параметр из url в Class Based View

Хотите, чтобы у вас происходило следующее?
url: /article/php - в class based view получаем параметр php
url: /article/python - в class based view получаем параметр python

Для этого вы должны определить паттерн в urls.py:
url(r'^aticle/(?P<category>[a-z]+)/$', ArticleListView.as_view()),
Согласно этому паттерну, получается, что если обратиться по адресу /article/php, то будет задействовано представление ArticleListView, основанное на классе (это class based view).
Данный класс размещен в views.py:

from django.views.generic import DetailView, ListView
from article.models import Article


class ArticleListView(ListView):

    model = Article

    def get_queryset(self):

        category_url = self.kwargs['category']

        return Article.objects.filter(category=category_url)

В этом классе мы из url получаем параметр category посредством self.kwargs['category']. Затем мы достаем все статьи и отбираем из них те, где категория соответствует параметру category, полученному из url.
Работая с class based views, следует помнить об этой замечательной функции def get_queryset(self): Она позволяет определить содержание параметров, передаваемых в шаблон.

воскресенье, 24 марта 2013 г.

Обход элементов словаря python

Напишите на python функцию, которая позволяет преобразовать словарь в строки, выводимые в консоль как показано в двух примерах:

dict1 = {'a':1, 'b':{'aa':11, 'bb':22}, 'c':3}

Результат: 
[a]=1
[b][aa]=11
[b][bb]=22
[c]=3

   
dict2 = {'a':1, 'b':{'aa':11, 'bb':22, 'cc':{'aaa':111, 'bbb':222, 'ccc':333}, 'dd':44}, 'c':3}

Результат:
[a]=1
[b][aa]=11
[b][bb]=22
[b][cc][aaa]=111
[b][cc][bbb]=222
[b][cc][ccc]=333
[b][dd]=44
[c]=3

    


среда, 20 февраля 2013 г.

Блог за 30 минут на Django

При изучении чего-либо важно учиться у профессионалов. Я уже сделал простой блог с тегами и с RSS-feed по материалам приведенного видео, попробуйте и вы.

Включаем подсветку кода на Blogspot

Вот так подсвечивается код python:
class BlogFeed(Feed):
    title = "Yesnik Site"
    description = "My site about Django"
    link = "/blog/feed/"
    
    def items(self):
        return Post.objects.all().order_by("-created")[:2]
    
    def item_title(self, item):
        return item.title
        
    def item_description(self, item):
        return item.body
        
    def item_link(self, item):
        return u"/blog/%d" % item.id 

Для этого:
1. В настройках блога в меню слева выберите пункт "Шаблон", затем нажмите "Изменить HTML".
2. В открывшемся окне найдите тег </head> . Ниже него добавьте следующий код:














3. Нажмите Сохранить шаблон.
4. Чтобы размещаемый код подсвечивался, перейдите при создании сообщения для блога из режима "Создать" в режим "HTML". Там заключите вставленный код в теги pre, к примеру:
<pre class="brush: python;">
class BlogFeed(Feed):
    title = "Yesnik Site"
    description = "My site about Django"
    link = "/blog/feed/"
</pre>

воскресенье, 20 января 2013 г.

Задача №1 по созданию сайта на Django


Создать сайт с функционалом:
  1. публичная часть
  2. административная часть, защищенная паролем
  3. сайт должен давать возможность создания любого числа страниц с содержимым, подобным статье (название статьи, содержимое, время создания).
  4. пока никаких товаров, никаких комментариев и изображений, никаких тегов, никакого поиска, никакого RSS.... об этом будем думать в других задачах.