пятница, 5 декабря 2014 г.

PGQ очередь с одним consumer и producer

Установим pgq:
$ sudo pip install pgqueue

Установим pgq-расширение для PostgreSQL:
$ sudo apt-get install postgresql-9.2-pgq3

После этого нужно через консоль подсоединиться к БД и выполнить команду на создание расширения pgq:
my_db=# CREATE EXTENSION IF NOT EXISTS pgq;

Теперь нужно запустить процесс ticker. Если это не сделать, то события будут добавляться в очередь, но не будут отправляться консьюмерам, что приведет к быстрому росту очереди.

Запустим простую питоновскую реализацию ticker:
python -m pgqueue 'host=127.0.0.1 port=5432 user=postgres password=123 dbname=johny'

Создадим скрипт consumer.py:
# encoding: utf-8
import psycopg2
import pgqueue

conn = psycopg2.connect("dbname=johny user=postgres password=123 host=localhost")
conn.autocommit = True
cursor = conn.cursor()

consum_q = pgqueue.Consumer('first_queue', 'consumer_one')
consum_q.register(cursor)

# Получаем события из очереди
conn.autocommit = False
for event in consum_q.next_events(cursor, commit=True):
    print(event)


При запуске этого скрипта события буду забираться из очереди. Но там пока нет событий. Чтобы они там появились, создадим файл publisher.py:
# encoding: utf-8
import psycopg2
import pgqueue

conn = psycopg2.connect("dbname=johny user=postgres password=123 host=localhost")
conn.autocommit = True
cursor = conn.cursor()

# Инициируем очередь
first_q = pgqueue.Queue('first_queue')
first_q.create(cursor, ticker_max_lag='4 seconds')

# Добавляем события в очередь
first_q.insert_event(cursor, 'greeting', 'How are you?')
first_q.insert_event(cursor, 'question', 'What are you doing?')

Чтобы события появились в очереди, запустим скрипт publisher.py:
$ python publisher.py

Теперь попробуем прочитать эти события из очереди, запустив consumer.py:
$ python consumer.py  

Если ответ не пришел, нужно убедиться, что процесс ticker запущен.

вторник, 25 ноября 2014 г.

Дизассемблировать python-программу

Порой бывает интересно, что происходит "под капотом" вашей программы. В python есть замечательный модуль dis, который позволяет посмотреть, как интерпретатор выполняет ваш код.

Создадим файл app.py:
import dis

n = 0

def application(env, start_response):
    global n
    n = n + 1
    response = "%.6d" % n
    start_response('200 OK', [('Content-Type', 'text/plain')])
    return [response]

if '__main__' == __name__:
    print(dis.dis(application))
А теперь в терминале запустите этот файл:
$ python app.py

Программа выведет следующее:
           0 LOAD_GLOBAL              0 (n)
              3 LOAD_CONST               1 (1)
              6 BINARY_ADD         
              7 STORE_GLOBAL             0 (n)

           10 LOAD_CONST               2 ('%.6d')
             13 LOAD_GLOBAL              0 (n)
             16 BINARY_MODULO      
             17 STORE_FAST               2 (response)

 10          20 LOAD_FAST                1 (start_response)
             23 LOAD_CONST               3 ('200 OK')
             26 LOAD_CONST               6 (('Content-Type', 'text/plain'))
             29 BUILD_LIST               1
             32 CALL_FUNCTION            2
             35 POP_TOP            

 11          36 LOAD_FAST                2 (response)
             39 BUILD_LIST               1
             42 RETURN_VALUE       

Слева приведены строки нашей программы. Здесь видно, что операция инкремента переменной n (строка 7) занимает 4 операции.

четверг, 2 октября 2014 г.

Сделать на Django приложение бронирования времени приема

Как вы помните, фреймворк Django предназначен для быстрой разработки (Rapid Development). Следовательно, он поможет быстро решить следующую задачу.

Пролог
В компании ООО "Позитив", имеющей филиалы в нескольких городах России, возникла необходимость организовать 35 тысяч встреч со своими клиентами по вопросу оформления документов. Очевидно, что если все клиенты придут в первый день, то у специалистов компании "Позитив" будет в душе негатив. Кроме того, клиенты будут недовольны, ибо никто не любит терять время в километровых очередях.

Набросок технического задания
Нужно на Django создать сайт, где клиенты смогут указать свои данные и забронировать свободное время в удобный для них день.
Данные, требующиеся от клиента, которые должны быть отображены пользователю при бронировании времени:
  • ФИО
  • телефон
  • наименование организации
  • ИНН
  • Город, где удобно прийти на встречу
  • Адрес офиса, где будет проходить встреча
  • Дата встречи
  • Время встречи
При этом следует учесть ряд моментов:
  • организация не может забронировать более одной встречи
  • в списке дат и времени занятые значения должны отображаться серым цветом
Интерфейс придумайте самостоятельно. Защита "от дурака" (капча, невозможность создать более одной заявки с одного IP, валидация значений) не обязательна, ибо задание учебное.

Свои готовые решения можете публиковать ссылкой на проект github в комментариях к данной статье.

вторник, 3 июня 2014 г.

Запрограммируем сайт на Django

В сети нашел отличный сайт с видеоуроками по Bitrix. Там рассказывается, как на базе этой системы запрограммировать сайт. Сразу возникло желание сделать эту же работу на фреймворке Django.
Предлагаю Вам скачать шаблон сайта и запрограммировать его на Django. Гарантирую, вы многому научитесь.
Свою реализацию программирования сайта thesame я опубликовал на github.

понедельник, 26 мая 2014 г.

Пагинация страниц в Django

Часто требуется ограничить количество записей, выводимых на страницу. Для этого используется постраничное разделение материала - пагинация (pagination). В этом уроке мы рассмотрим реализацию пагинации стандартными средствами Django.

Добавить поля в модель User в Django

Данный урок написан на базе рекомендаций документации Django по добавлению новых полей к модели пользователя.

среда, 14 мая 2014 г.

prepopulated_fields в админке Django

Во многих CMS предусмотрена возможность создания поля slug на базе заголовка. К примеру, пользователь вводит название статьи: "Как я научился плавать", а система генерирует "kak-ya-nauchilsya-plavat". По этому id статьи можно к ней будет обращаться, например:
http://somesite.com/articles/kak-ya-nauchilsya-plavat

понедельник, 12 мая 2014 г.

Опрос (ч.7)

В предыдущей части урока по Django мы рассмотрели, как можно защитить наше приложение опросов от хакера. В этом уроке мы защитим наши опросы от повторного голосования.

Опрос (ч.6)

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

воскресенье, 11 мая 2014 г.

Размышления о Bitrix и Django

Нет ничего плохого в том, 
что вы установите 1С-Битрикс.
Только не называйте 
себя программистом.
(Кто-то из Интернета)

Фреймворк Django используется для разработки сайтов. CMS 1С-Битрикс тоже используется для этой цели. Если ваша работа связана с PHP, хорошо будет познакомиться с этой системой.

среда, 7 мая 2014 г.

Опрос (ч.5)

В части 4 мы создали роут, по которому стали доступен список последних двух опросов. В этой части мы сделаем детальное отображение опроса.

Аналог var_dump() в python

Как ни крути, а var_dump() в php очень удобен и интуитивно понятен.
К сожалению, такой простой конструкции в python нет, но ее можно примерно повторить, если сделать следующее:
from inspect import getmembers
from pprint import pprint
pprint(getmembers(yourObject))

пятница, 14 марта 2014 г.

Объединение css и js файлов в один - django-compressor


Для увеличения производительности веб-приложения нужно стремиться к уменьшению количества запросов к веб-серверу при загрузке каждой страницы.
Этого можно достичь объединением файлов стилей и скриптов в единые файлы. В итоге на страницу будет загружаться по одному .css и .js файлу.
 Чтобы объединять файлы стилей и скриптов в один файл, можно воспользоваться приложением django-compressor.

понедельник, 17 февраля 2014 г.

Простой web-сервер на python

Создать простой веб-сервер на python несложно. Для этого нам понадобится сокеты (sockets).
Но прежде нужно определить, что мы хотим получить в результате.
А хотим мы получить простую программу на python, которая будет прослушивать какой-то порт нашего локального компьютера и принимать запросы от браузера.
1. Создадим файл my_server.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import socket
import time

serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
serversocket.bind(('localhost', 8080))
serversocket.listen(5)
print 'Server is waiting for connections.'
while True:
    conn, addr = serversocket.accept()
    data = conn.recv(1024)
    
    print 'Connection:', addr
    print '------------------------------'
    print "Request Data from Browser"
    print '------------------------------'
    print data
    
    conn.send(data)
    conn.close()
    # Делаем задержку, чтобы цикл не сильно загружал процессор
    time.sleep(0.1)

2. А теперь запустим этот файл в консоли Windows cmd.exe. Для этого вам нужно открыть командную строку Windows, указать путь к файлу my_server.py и нажать Enter.
Так мы запустили сервер, который ожидает запросы на адрес http://127.0.0.1:8080.

3. Запустим браузер, к примеру Internet Explorer, и перейдем по адресу  http://127.0.0.1:8080/test. В результате в браузере и консоли мы увидим следующее:



 Таким образом, в переменной data нашего скрипта хранится информация о странице, которую пользователь запрашивает. Мы можем дописать код, и сервер будет возвращать в зависимости от запроса контент той или иной html-страницы, хранящейся на сервере.
Далее можно будет сделать так, чтобы содержимое html-страницы строилось на основе данных, хранящихся в базе данных, к примеру, mysql. Однако это тема отдельных постов.

пятница, 17 января 2014 г.

Bad request (400) при сохранении модели с изображением в Django

Иногда при попытке сохранения модели в админке Django может возникнуть ошибка Bad request (400). Рассмотрим пример такой модели:
class Category(models.Model):
    """ Категория товара. Например, Куртки, Пальто """
    title = models.CharField(max_length=100, verbose_name='Название')
    image = models.ImageField(upload_to='/images/category')
    slug = models.SlugField(verbose_name=u'Псевдоним для url')
    section = models.ManyToManyField(Section, verbose_name=u'Раздел сайта')
    description = models.TextField(verbose_name='Описание')

    def __unicode__(self):
        return self.title

    class Meta:
        verbose_name = 'Категория'
        verbose_name_plural = 'Категории'
Ошибка возникла из-за неверного указания пути для сохранения загружаемого файла.
В данном случае нужно было указать:
image = models.ImageField(upload_to='images/category')