marselester – блог программиста


Темы: Django Dropbox Symfony2 Ассемблер Методы оптимизации Моделирование систем Портфолио Управление задачами

Выбор пространства имен при импорте в Django

02.02.2012
Сомневаешься в выборе пространства имен? Сбивает с толку «Writing your first Django app, part 1-4»?
Можно писать так:


# settings.py
ROOT_URLCONF = 'myproject.urls'

INSTALLED_APPS = (
    'myproject.polls',
)

# urls.py
urlpatterns = patterns('',
    url(r'^polls/', include('myproject.polls.urls')),
)

# polls/urls.py
urlpatterns = patterns('myproject.polls.views',
    url(r'^$', 'home', name='polls_home'),
)

# polls/views.py, polls/admin.py, polls/tests.py
from myproject.polls.models import Poll
или по-короче, без «myproject».

Оба варианта работают (что еще хуже, их можно перемешать), но хочется сделать «как правильно».
Мои поиски ответа привели к правилу: если создаешь приложение через ./manage.py startapp, используй вариант с «myproject.polls», в противном случае делай reusable приложение.

Dropbox аутентификация с использованием Python SDK 1.2

23.10.2011
Пару дней назад обновился Dropbox API и вышел Python SDK 1.2. Пришлось переписать скрипт обновления состояния кабинок для «Уфимских бань». Раньше можно было просто прописать e-mail и пароль к подключаемому Dropbox аккаунту. Сейчас же нужно получать access token. Этот процесс хорошо описан здесь, правда не приведен пример авторизации с имеющимся токеном. Вкратце постараюсь восполнить данный пробел. Копипастим пример с сайта Dropbox.


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Include the Dropbox SDK libraries
from dropbox import client, rest, session

# Get your app key and secret from the Dropbox developer website
APP_KEY = 'INSERT_APP_KEY_HERE'
APP_SECRET = 'INSERT_SECRET_HERE'

# ACCESS_TYPE should be 'dropbox' or 'app_folder' as configured for your app
ACCESS_TYPE = 'INSERT_ACCESS_TYPE_HERE'

sess = session.DropboxSession(APP_KEY, APP_SECRET, ACCESS_TYPE)

request_token = sess.obtain_request_token()

url = sess.build_authorize_url(request_token)

# Make the user log in and authorize this token
print "url:", url
print "Please visit this website and press the 'Allow' button, then hit 'Enter' here."
raw_input()

# This will fail if the user didn't visit the above URL and hit 'Allow'
print sess.obtain_access_token(request_token)
Запускаем скрипт, переходим по ссылке, жмем на 'Allow', потом в консоле на 'Enter'. Далее из появившейся строки копируем значения oauth_token_secret, oauth_token и подставляем в ACCESS_TOKEN_SECRET, ACCESS_TOKEN соответственно.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Include the Dropbox SDK libraries
from dropbox import client, rest, session

# Get your app key and secret from the Dropbox developer website
APP_KEY = 'INSERT_APP_KEY_HERE'
APP_SECRET = 'INSERT_SECRET_HERE'

# ACCESS_TYPE should be 'dropbox' or 'app_folder' as configured for your app
ACCESS_TYPE = 'INSERT_ACCESS_TYPE_HERE'

sess = session.DropboxSession(APP_KEY, APP_SECRET, ACCESS_TYPE)

ACCESS_TOKEN = 'blah'
ACCESS_TOKEN_SECRET = 'blah-blah'

sess.set_token(ACCESS_TOKEN, ACCESS_TOKEN_SECRET)
client = client.DropboxClient(sess)
resp = client.get_file("test.txt")

Написал свой блог на Django

17.10.2011
Написал свой блог на Django. До этого использовал WordPress. Будет не правдой сказать, что его не хватало. Здесь немного другое – меняю стек технологий, перехожу с PHP на Python. Ну а лучший способ научиться что-либо делать – практика. Кстати, исходник этого блога доступен на GitHub.

Разработан архив журнала «Агидель»

05.09.2011

Разработан электронный архив ежемесячного литературно-публицистического журнала «Агидель» на Django. Предполагается, что ресурс будет содержать архив журналов с 1923 года. Для удобной навигации сделал ajax поиск по авторам и публикациям, на подобии Яндекс search suggestions. Проблему отображения большого количества номеров журналов решил с помощью Paginator 3000, правда его пришлось немного допилить.

Разработан сайт флористического салона «Гламелия»

03.09.2011

Разработан сайт флористического салона «Гламелия» на самописной cms myscon.
Интересное в проекте

Разработан сайт компании «СССР»

05.08.2011

Разработан сайт компании «СССР» (поставщик дверей) на самописной cms myscon.
Интересное в проекте

Скрин сайта.

Разработан сайт архитектурных профильных систем

01.08.2011

Разработан сайт архитектурных профильных систем на самописной cms myscon с каталогом продукции.
Скрин сайта.

Установка Symfony2 под Ubuntu 10.10, 11.04

28.07.2011
Состоялся релиз Symfony2, для успешной работы которой под Ubuntu 10.11, 11.04 понадобилось проделать следующее:


sudo apt-get install php5-sqlite
sudo apt-get install php5-intl
sudo apt-get install libpcre3-dev
sudo pecl install apc
В php.ini подключить extension=apc.so и прописать date.timezone.
В конце не забываем перезагрузить apache.

sudo service apache2 restart

Разработан сайт компании «Уралнефтегаздиагностика»

07.07.2011

Разработан сайт научно-производственной фирмы «Уралнефтегаздиагностика» на самописной cms myscon.

Пример аутентификации в Django/MongoDB/mango

05.07.2011
Для того чтобы использовать MongoDB с Django мне не хватало двух важных вещей – аутентификации и сессий.
С этой задачей хорошо справляется mango. Ниже приведен пример использования этого бэкенда.

Скачиваем и устанавливаем mango. В файле settings.py добавляем следующие строки:


SESSION_ENGINE = 'mango.session'
AUTHENTICATION_BACKENDS = (
    'mango.auth.Backend',
)
MONGODB_HOST = 'localhost'
MONGODB_PORT = None
MONGODB_NAME = 'mydb'
Остальное оставляем по умолчанию. Для Django 1.3:

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',
)

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
)
Создаем приложение accounts и настраиваем urls: my_project/accounts/urls.py

urlpatterns = patterns('accounts.views',
    (r'^login/$', 'login'),
    (r'^logout/$', 'logout'),
    (r'^profile/$', 'profile'),
)
my_project/urls.py

urlpatterns = patterns('',
    (r'^accounts/', include('accounts.urls')),
)
Добавляем представление: my_project/accounts/views.py

# -*- coding: utf-8 -*-
import urlparse

from django.http import HttpResponse, HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.template.response import TemplateResponse

from django.contrib import auth

from my_project.accounts.forms import LoginForm

def login(request):
    redirect_to = request.REQUEST.get('next', '')
    
    if request.method == 'POST':
        form = LoginForm(request.POST)
        if form.is_valid():
            netloc = urlparse.urlparse(redirect_to)[1]
            
            if not redirect_to:
                redirect_to = reverse('accounts.views.profile')
            # Security check -- don't allow redirection to a different host
            elif netloc and netloc != request.get_host():
                redirect_to = reverse('accounts.views.profile')
            
            auth.login(request, form.get_user())
            
            return HttpResponseRedirect(redirect_to)
    else:
        form = LoginForm()
    
    return TemplateResponse(request, 'accounts/login.html', {
        'form': form,
        'next': redirect_to,
    })

def logout(request):
    auth.logout(request)
    return HttpResponseRedirect('/accounts/')

def profile(request):
    return HttpResponse('User profile.')
Добавляем класс формы: my_project/accounts/forms.py

# -*- coding: utf-8 -*-
from django import forms

from django.contrib import auth

class LoginForm(forms.Form):
    username = forms.CharField(label='Логин', max_length=30)
    password = forms.CharField(label='Пароль', widget=forms.PasswordInput)
    
    def clean(self):
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')
        
        if username and password:
            self.user_cache = auth.authenticate(username=username, password=password)
            if self.user_cache is None:
                raise forms.ValidationError("Неправильная пара логин-пароль! Попробуйте еще раз.")
            elif not self.user_cache.is_active:
                raise forms.ValidationError("Аккаунт заблокирован.")
        return self.cleaned_data
    
    def get_user(self):
        return self.user_cache
И наконец шаблон: my_project/templates/accounts/login.html

{{ form.non_field_errors }}

<form action="" method="post">
{% csrf_token %}
{{ form.username.label_tag }}:
{{ form.username }}
{{ form.username.errors }}

{{ form.password.label_tag }}:
{{ form.password }}
{{ form.password.errors }}

<input type="submit" value="Войти"/>
<input type="hidden" name="next" value="{{ next }}"/>
</form>
Пробуем залогиниться http://localhost:8000/accounts/login/ и смотрим результат в консоли MongoDB (коллекции sessions и users).