Уведомления

Группа в Telegram: @pythonsu

#1 Март 25, 2011 18:35:27

m.meehalkoff
От:
Зарегистрирован: 2011-01-21
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

Sqlalchemy и внешние ключи

Доброго времени суток.

Есть три таблицы:
1. Информация о физических лицах:

class FContragent(Base):
__tablename__ = "f_contragent"

id = Column(Integer, primary_key = True)
contragent_type_id = Column(Integer, ForeignKey('contragent_type.id'), nullable = False)
surname = Column(Unicode, nullable = False)
name = Column(Unicode, nullable = False)
patronymic = Column(Unicode, nullable = False)
phone_number = Column(Unicode, nullable = False)
comment = Column(Unicode)

def __init__(self, contragent_type_id, surname, name, patronymic, phone_number, comment):
self.contragent_type_id = contragent_type_id
self.surname = surname
self.name = name
self.patronymic = patronymic
self.phone_number = phone_number
self.comment = comment
2. Информация о юридических лицах:
# класс таблицы юридических лиц
class UContragent(Base):
__tablename__ = "u_contragent"

id = Column(Integer, primary_key = True)
contragent_type_id = Column(Integer, ForeignKey('contragent_type.id'), nullable = False)
org_type_id = Column(Integer, ForeignKey('org_type.id'), nullable = False)
inn = Column(Unicode, nullable = False)
ogrn_kpp = Column(Unicode, nullable = False)
phone_number = Column(Unicode, nullable = False)
org_name = Column(Unicode, nullable = False)
account = Column(Unicode, nullable = False)
bik = Column(Unicode, nullable = False)
cor_account = Column(Unicode, nullable = False)
# физический адрес
f_zip = Column(Unicode, nullable = False)
f_country = Column(Unicode, nullable = False)
f_district = Column(Unicode, nullable = False)
f_city = Column(Unicode, nullable = False)
f_street = Column(Unicode, nullable = False)
f_street_type_id = Column(Integer, ForeignKey('street_type.id'), nullable = False)
f_building = Column(Unicode, nullable = False)
f_liter_type_id = Column(Integer, ForeignKey('liter_type.id'), nullable = False)
f_corpus_type_id = Column(Integer, ForeignKey('corpus_type.id'), nullable = False)
# юридический адрес
u_zip = Column(Unicode, nullable = False)
u_country = Column(Unicode, nullable = False)
u_district = Column(Unicode, nullable = False)
u_city = Column(Unicode, nullable = False)
u_street = Column(Unicode, nullable = False)
u_street_type_id = Column(Integer, ForeignKey('street_type.id'), nullable = False)
u_building = Column(Unicode, nullable = False)
u_liter_type_id = Column(Integer, ForeignKey('liter_type.id'), nullable = False)
u_corpus_type_id = Column(Integer, ForeignKey('corpus_type.id'), nullable = False)
comment = Column(Unicode)
sum_org_name = Column(Unicode, nullable = False)

def __init__(self, contragent_type_id, org_type_id, org_name, inn, ogrn_kpp, phone_number, account, bik, cor_account,
f_zip, f_country, f_district, f_city, f_street, f_street_type_id, f_building, f_liter_type_id, f_corpus_type_id,
u_zip, u_country, u_district, u_city, u_street, u_street_type_id, u_building, u_liter_type_id, u_corpus_type_id,
comment, sum_org_name):

self.contragent_type_id = contragent_type_id
self.org_type_id = org_type_id
self.inn = inn
self.ogrn_kpp = ogrn_kpp
self.phone_number = phone_number
self.org_name = org_name
self.account = account
self.bik = bik
self.cor_account = cor_account
self.f_zip = f_zip
self.f_country = f_country
self.f_district = f_district
self.f_city = f_city
self.f_street = f_street
self.f_street_type_id = f_street_type_id
self.f_building = f_building
self.f_liter_type_id = f_liter_type_id
self.f_corpus_type_id = f_corpus_type_id
self.u_zip = u_zip
self.u_country = u_country
self.u_district = u_district
self.u_city = u_city
self.u_street = u_street
self.u_street_type_id = u_street_type_id
self.u_building = u_building
self.u_liter_type_id = u_liter_type_id
self.u_corpus_type_id = u_corpus_type_id
self.comment = comment
self.sum_org_name = sum_org_name
3. Информация о заказе:
# класс таблицы заказа
class Order(Base):
__tablename__ = "order"

id = Column(Integer, primary_key = True)
date_reception = Column(Date, nullable = False)
contragent_type_id = Column(Integer, ForeignKey("contragent_type.id"), nullable = False)
contragent_id = Column(Integer, """ как организовать внешний ключ для значения из разных таблиц? """)
amount = Column(Integer, nullable = False)
status_id = Column(Integer, ForeignKey('status.id', nullable = False)
date_change_status = Column(Date, nullable = False)

def __init__(self, date_reception, contragent_type_id, contragent_id, amount, status_id, date_change_status):
self.date_reception = date_reception
self.contragent_type_id = contragent_type_id
self.contragent_id = contragent_id
self.amount = amount
self.status_id status_id
self.date_change_status = date_change_status
В таблицу с заказами необходимо вносить информацию о контрагенте.
Так как контрагентов два типа(юр. лица и физ. лица), то и значение id контрагента может браться из любой из
этих таблиц. Как в sqlalchemy организовать такой внешний ключ? Доки читал, но в английском не силен.
Заранее спасибо.



Офлайн

#2 Март 31, 2011 10:58:58

Sleepwalker
От:
Зарегистрирован: 2008-07-18
Сообщения: 68
Репутация: +  0  -
Профиль   Отправить e-mail  

Sqlalchemy и внешние ключи

Внешний ключ на две таблицы сделать не получится (или я просто чего-то не понимаю :) )

Вариант 1:

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

from sqlalchemy.orm import relation

class Order(Base):

ucontragent_id = Column(Integer, ForeignKey('u_contragent.id'), nullable=True)
fcontragent_id = Column(Integer, ForeignKey('f_contragent.id'), nullable=True)

ucontragent = relation(UContragent, uselist=False, backref='orders')
fcontragent = relation(FContragent, uselist=False, backref='orders')
Вариант 2:

Архитектурно переделать. Сделать наледованием таблиц (это описано в http://www.sqlalchemy.org/docs/orm/inheritance.html).
Тогда у вас будет клас Contractor от которого будут наследоваться физические и юридические лица. В базе же у вас будет таблица (напр. contractors) с которой (как one-to-one) будут связаны ucontractors и fcontractors.

В ссылке которую я вам дал это описано. Выглядеть это будет ПРИБЛИЗИТЕЛЬНО так:

class Contragent(Base):

__tablename__ = 'contragents'

id = Column(Integer, primary_key = True)

# общие поля для ucontragent и fcontragent

discriminator = Column('discriminator', String(30), nullable=False)

__mapper_args__ = {'polymorphic_on': 'Contragent.discriminator'}


class FContragent(Contractor):

__mapper_args__ = {'inherits': Contragent,
'polymorphic_identity': 'fcontragent'}

class UContragent(Contragent):

__mapper_args__ = {'inherits': Contragent,
'polymorphic_identity': 'ucontragent'}

class Order(Base):

contragent_id = Column(Integer, ForeignKey(Contragent.id))
Тогда вы сделая запросы session.query(Contragent).all() будете получать либо обьекты UContragent либо FContragent в зависимости от значения поля discriminator.



Отредактировано (Март 31, 2011 11:03:36)

Офлайн

#3 Апрель 1, 2011 20:08:30

m.meehalkoff
От:
Зарегистрирован: 2011-01-21
Сообщения: 25
Репутация: +  0  -
Профиль   Отправить e-mail  

Sqlalchemy и внешние ключи

Спасибо за информацию:)



Офлайн

Board footer

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

Powered by DjangoBB

Lo-Fi Version