Використання SQLAlchemy в django

Для початку поставало питання як позбавиться від django ORM, але він відпав як тільки зіткнувся з сесіями. Тому було вирішено залишити в підключаються додатках тільки django.contrib.sessions.

settings.py 

# To create user sessions
INSTALLED_APPS = (
    'Django.contrib.sessions',
)

Був створений клас для створення сесій бази даних.

dbsession.py 
import sqlalchemy.orm
from django.conf import settings

class _Singleton (object):
    # By default we use db url from project's settings
    _database_url = None
    _session = None
    _refresh_session = False
    def set_dburl (self, database_url):
        self._database_url = database_url
        self._refresh_session = True
    def __call__ (self):
        if self._database_url:
            engine = sqlalchemy.create_engine (
                self._database_url, echo = settings.SQLALCHEMY_DEBUG)
        else:
            engine = sqlalchemy.create_engine (
                settings.SQLALCHEMY_ENGINE, echo = settings.SQLALCHEMY_DEBUG)
        Session = sqlalchemy.orm.sessionmaker ()
        connection = engine.connect ()
        if not self._session or self._refresh_session:
            self._session = Session (bind = connection)
            if self._refresh_session:
                self._refresh_session = False
        return self._session

_singleton = _Singleton ()
def Singleton (): return _singleton
session = Singleton ()

Для створення таблиць вирішили використовувати пакет sqlalchemy-migrate . Оскільки використовувати syncdb ми не будемо, через мігрейти створюємо таблицю django_session і таблицю users.

001_Initial_database_structure.py 
from sqlalchemy import *
from migrate import *

meta = MetaData ()

django_sessions_table = Table ('django_session', meta,
    Column ('session_key', String (40), primary_key = True),
    Column ('session_data', Text, nullable = False),
    Column ('expire_date', DateTime, nullable = False, index = True),
    mysql_engine = 'InnoDB',
    mysql_charset = 'utf8')
users_table = Table ('users', meta,
    Column ('id', Integer, primary_key = True),
    Column ('username', String (255), index = True, unique = True),
    Column ('password', String (255), index = True, nullable = False, default =''),
    Column ('is_active', Boolean, nullable = False, default = 1, index = True),
    Column ('is_superuser', Boolean, nullable = False, default = 0, index = True),
    Column ('last_login', DateTime, index = True),
    Column ('date_joined', DateTime, index = True),
    mysql_engine = 'InnoDB',
    mysql_charset = 'utf8'
    )

def upgrade (migrate_engine):
    meta.bind = migrate_engine
    django_sessions_table.create ()
    users_table.create ()
def downgrade (migrate_engine):
    meta.bind = migrate_engine
    django_sessions_table.drop ()
    users_table.drop ()

Загальна структура програми виглядає наступним чином.

src
  project
    users
      db.py 
      models.py 

Зауважимо що в models у нас немає ні слова про моделі django зате є наш клас User, в якому є все необхідне нам для авторизації.

models.py 
class User (object):
    "" "Represents an user in a database." ""
    def __init__ (self, username):
        self.username = username
    def get_password_hexdigest (self, password):
        "" "Returns hexdigest of password." ""
        h = hashlib.new ('sha1')
        h.update (smart_str (password))
        return h.hexdigest ()
    def set_password (self, password):
        "" "Set new hashed password to user." ""
        self.password = self.get_password_hexdigest (password)
    def check_password (self, password):
        "" "Checks password hash with values ??in database." ""
        return self.get_password_hexdigest (password) == self.password
    def is_anonymous (self):
        "" "
        Always returns False. This is a way of comparing User objects to
        anonymous users.
        "" "
        return False
    def is_authenticated (self):
        "" "
        Always return True. This is a way to tell if the user has been
        authenticated in templates.
        "" "
        return True
    def __repr__ (self):
        return u ''% (
            self.id ,
            self.username,
        )

Ми недовго сперечалися, де повинен розташовуватися метод створення користувача і прийшли до висновку, що він буде статик-методом в самому класі User.

@ staticmethod
    def create (username, password):
        user = User (username)
        user.date_registered = datetime.datetime.now ()
        db (). add (user)
        return user.save ()
    def save (self):
        db (). commit ()
        return self

Метод save зробимо комит в базу даних якщо відбулися зміни в нашому класі, чи змінився username або password. Джанго навіть не підозрює, як ми її надули цим самим і встановить поле last_login при авторизації користувача.

Чим подібний підхід хороший, мені здається він більш логічний.

- Визначення таблиць розташовується у файлі ;
- Наші класи містять строго певні нами методи і нічого зайвого, а з таблицею він зв'язується через mapper;

- Ні жахливих менеджерів, які на мій погляд абсолютно марні.

Опубліковано: 13/07/11 @ 04:35
Розділ php

Рекомендуємо:

Яндекс.Старт в Одесі
Післямова - про зарплати і сеньйора
Значення HTML 5 для пошукової оптимізації
Семінар «Як отримувати максимум цільового трафіку від Google»
Ви ще не закрили свої папки? Тоді хтось, можливо, прийде до вас ...