Уведомления

Группа в Telegram: @pythonsu

#1 Июль 31, 2007 13:59:13

niro
От:
Зарегистрирован: 2006-10-04
Сообщения: 178
Репутация: +  0  -
Профиль   Отправить e-mail  

Сложный select в sqlalchemy

Есть несколько таблиц. Таблица с юзерами и таблица с их сообщениями
Таблица юзеров:

        Table('users',self.metadata,
Column('user_id', Integer, primary_key=True),
Column('username', String(40)),
Column('password', String(32)),
Column('email', String(25)))
Таблица сообщений:
        Table('posts', self.metadata,
Column('id', Integer, primary_key=True),
Column('pub_date', DateTime),
Column('user_id',Integer, ForeignKey('users.user_id')),
Column('title', String(70)),
Column('text', String))
Я делаю достаточно простой select:
    post = select([posts.c.id,
posts.c.user_id,
posts.c.pub_date,
posts.c.title,
posts.c.text], posts.c.id == id).execute().fetchone()
Мне необходимо изменить этот select настолько, чтобы не менялась структура получаемых данных, но чтобы вместо user_id я получал username из таблицы users.



Офлайн

#2 Июль 31, 2007 16:47:44

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Сложный select в sqlalchemy


from sqlalchemy import *
import datetime

metadata = MetaData(“sqlite:///”)

users = Table('users', metadata,
Column('user_id', Integer, primary_key=True),
Column('username', String(40)),
Column('password', String(32)),
Column('email', String(25)))


posts = Table('posts', metadata,
Column('id', Integer, primary_key=True),
Column('pub_date', DateTime),
Column('user_id',Integer, ForeignKey('users.user_id')),
Column('title', String(70)),
Column('text', String))

metadata.create_all()

q = users.insert()
oid = q.execute(username='John', password='pass', email='j@c.com').lastrowid

post_id = posts.insert().execute(pub_date=datetime.datetime.now(), user_id=oid, title='title', text='text').lastrowid


post = select([posts.c.id,
users.c.username,
posts.c.pub_date,
posts.c.title,
posts.c.text], and_(posts.c.id == post_id, posts.c.user_id == users.c.user_id)).execute().fetchone()

print post



Офлайн

#3 Июль 31, 2007 17:04:59

niro
От:
Зарегистрирован: 2006-10-04
Сообщения: 178
Репутация: +  0  -
Профиль   Отправить e-mail  

Сложный select в sqlalchemy

Спасибо, вроде бы подходит.



Отредактировано (Июль 31, 2007 19:04:34)

Офлайн

#4 Авг. 3, 2007 20:20:27

niro
От:
Зарегистрирован: 2006-10-04
Сообщения: 178
Репутация: +  0  -
Профиль   Отправить e-mail  

Сложный select в sqlalchemy

Как пройтись какой либо функцией по определенной части результата ?
Например :

post = select([posts.c.id,
users.c.username,
posts.c.pub_date,
posts.c.title,
posts.c.text], and_(posts.c.id == post_id, posts.c.user_id == users.c.user_id)).execute().fetchone()
Мне необходимо пройтись по posts.c.text, не меня структуры выхода



Офлайн

#5 Авг. 4, 2007 01:17:19

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Сложный select в sqlalchemy

niro
post = select([posts.c.id,
users.c.username,
posts.c.pub_date,
posts.c.title,
posts.c.text], and_(and_(posts.c.id == post_id, posts.c.user_id == users.c.user_id), posts.c.text=='blablabla').execute().fetchone()
Это просто.

Странное использование sqlalchemy.
Конечно, Bayer говорит о том, что в пакете есть две системы - для функциональной замотки (то, что ты используешь) и для ORM.
Я выбирал ее именно для object relation mapping - и лучше нет на Питоне (пока, возможно).

В 4.0 появились one и any - чтобы выбирать нужное.

P.S.
Кажется, ты не знаешь, как стросить. Сформулируй вопрос как-нибудь иначе.



Отредактировано (Авг. 4, 2007 01:20:04)

Офлайн

#6 Авг. 4, 2007 11:22:59

niro
От:
Зарегистрирован: 2006-10-04
Сообщения: 178
Репутация: +  0  -
Профиль   Отправить e-mail  

Сложный select в sqlalchemy

Проще так - мне надо отформатировать, например расставить переносы, posts.c.text не изменяя post, т.е. чтобы я получал тот же post что и раньше но уже с отформатированным текстом.



Офлайн

#7 Авг. 5, 2007 23:58:02

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Сложный select в sqlalchemy

Есть два ответа: сложный и неправильный.
Неправильный - задать в схеме базы свой тип, который будет при отдавании результатов делать форматирование.
Читай в стандартной доке The Types System : Creating your Own Types (наследуются от TypeDecorator).

Сложный. (Он на самом деле простой, только требует перехода но объектно-реляционный уровень, для чего Алхимия и создавалась :))
Заводишь свои классы, мапишь их на таблицы и в классе Post создаешь метод getFormattedText, в котором текст и форматируется. Основы процесса описаны в разделе tutorial.

Можно написать и полный пример, если совсем непонятно. Но, по моему, даже tutorial весьма доходчив.



Отредактировано (Авг. 5, 2007 23:59:25)

Офлайн

#8 Авг. 6, 2007 11:51:24

niro
От:
Зарегистрирован: 2006-10-04
Сообщения: 178
Репутация: +  0  -
Профиль   Отправить e-mail  

Сложный select в sqlalchemy

от примера не откажусь :)



Офлайн

#9 Авг. 6, 2007 14:53:44

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

Сложный select в sqlalchemy


from sqlalchemy import *
from sqlalchemy.orm import *
import datetime

engine = create_engine(“sqlite:///:memory:”)
metadata = MetaData()

users = Table('users', metadata,
Column('user_id', Integer, primary_key=True),
Column('username', String(40), unique=True),
Column('password', String(32)),
Column('email', String(25)))


posts = Table('posts', metadata,
Column('id', Integer, primary_key=True),
Column('pub_date', DateTime),
Column('user_id',Integer, ForeignKey('users.user_id')),
Column('title', String(70)),
Column('text', String))

metadata.create_all(engine)

class User(object):
def __init__(self, name, passwd, email):
self.username = name
self.password = passwd
self.email = email

def __repr__(self):
return ‘User %s’%self.username

class Post(object):
def __init__(self, date, title, text):
self.pub_date = date
self.title = title
self.text = text

def __repr__(self):
return ‘Post %s:%s (%s)’%(self.user.username, self.pub_date, self.title)

def formattedText(self):
‘'’Do formatting here'''
ret = self.text.capitalize()
return ret

mapper(User, users, properties={
‘posts’ : relation(Post, backref='user', cascade=“all, delete, delete-orphan”),
})

mapper(Post, posts)

Session = sessionmaker(bind=engine, transactional=True)

session = Session()
u = User('John', ‘pass’, ‘john@company.com’)
session.save(u)
u.posts.append(Post(datetime.datetime.now(), ‘title’, ‘non formatted text’))
session.flush()


p = session.query(Post).filter(Post.id==1).one()

print p.id, p.user.username, p.pub_date, p.title, p.formattedText()


Внимание, используются некоторые специфические для 0.4.0 конструкции. Сейчас эта ветка - рабочая в trunk svn. Не пройдет и месяца, как станет официальным релизом.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version