2014-12-03 2 views
1

У меня есть следующие три класса:SQLAlchemy: создание класса, который содержит набор элементов из другого класса

  1. A
  2. AItem
  3. ACollection.

Пользователь может добавить неограниченное количество объектов в качестве части class A. Каждому объекту, который наследуется от A, может быть добавлено неограниченное количество объектов в составе class AItem. Затем пользователь может создавать коллекции или комбинации этих предметов по своему усмотрению. эти коллекции доступны только для предметов, которые являются частью AItem, который является частью A. Обратите внимание, что не каждый объект в A должен иметь коллекцию, а элементы могут отображаться в нескольких коллекциях.

Пример:

colors = A 
red = AI(colors) 
green = AI(colors) 
blue = AI(colors) 
yellow = AI(colors) 
black = AI(colors) 
brown = AI(colors) 
white = AI(colors) 

Collection_1 = [red, green, blue] 
Collection_2 = [brown, black] 
Collection_3 = [red, brown, yellow] 

Мой код до сих пор:

class A(db.model): 
    __tablename__ = 'a' 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(64), unique=True) 

    a_items = db.relationship('AItem', backref='a') 

class AItem(db.model): 
    __tablename__ = 'a_items' 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(64), unique=True) 
    A_id = db.Column(db.Integer, db.ForeignKey('a.id')) 

class ACollection(db.model): 
    __tablename__ = 'a_collections' 
    id = db.Column(db.Integer, primary_key=True) 

Мой вопрос:

Как я могу построить ACollection класс? Также, пожалуйста, не стесняйтесь «перепроектировать» или изменить любой из моих кодов.

ответ

1

Вы хотите получить консультацию по архитектуре ваших данных или ваших классов? Как я не уверен, я дам вам обоих.

данные:

В данной точке зрения, я предлагаю вам создать таблицу a_items_collections между таблицами a_items и a_collections, потому что у вас есть N для N отношений (коллекция может иметь множество предметов и элемент может принадлежать многим коллекциям). Таким образом, каждая строка вашего a_items_collections будет устанавливать связь между элементом и коллекцией.

OOP:

В точке зрения ООП, у вас есть много возможностей, чтобы определить свои классы данных. Вы можете установить массив из AItem в ACollection, вы можете использовать другую коллекцию для таблицы a_items_collections, ... Вы обязательно должны использовать ORM, чтобы помочь вам в этом. Я не эксперт в Python, поэтому я не могу вам помочь. Кроме того, я настоятельно рекомендую вам отделить свои бизнес-классы от ваших классов данных с использованием шаблона SOA (сервис-ориентированная архитектура). Чтобы быть более ясным, ваше зеркало данных в вашей базе данных должно содержать только свойства, а интеллект для управления этими данными должен быть реализован в других классах (часто реализуется как singleton). Если вам нужно манипулировать своими коллекциями так же, как и ваши предметы, вы можете взглянуть на шаблон composite.

+1

Это не тот или другой. Если вы хотите выполнить алгоритм или/и программу, вы должны использовать ООП. Если вы хотите сохранить состояние объектов вашего объекта и коллекции в своей программе (чтобы получить их, например, при выключении компьютера или веб-сервера), вы должны использовать базу данных. Вы можете использовать ORM (Object Relationnal Mapper), чтобы помочь вам преобразовать ваши данные из вашей базы данных в объекты (исходя из того, что я назвал классами данных) в вашей программе. – Gnucki

+0

Спасибо за объяснение. Приложение, которое я делаю, - это веб-приложение, которое позволяет мне больше заниматься веб-разработкой, дизайном базы данных и построением ORM. Это проблема, которая столкнется со мной в другом реальном приложении, которое я планирую построить, поэтому понимание проблемы и решения имеет решающее значение для меня. У меня может возникнуть еще несколько вопросов к концу выходных, и если у вас есть что добавить к вашему ответу, пожалуйста, не стесняйтесь. Моя цель - построить его правильно и понять, почему так сделано – dassouki

+0

. Я дал вам несколько интересных ссылок. Это может быть трудно понять, но вы должны быстро взглянуть, чтобы узнать, что эти понятия существуют. Если вы можете сделать другой язык, чем Python, PHP лучше делать ООП. Я предлагаю вам использовать PHP с каркасом [Symfony2] (http://symfony.com/). Это помогает вам легко начать веб-разработку, по умолчанию имеет ORM, называемый Doctrine, и может использоваться на уровне экспертов, когда вы будете более комфортно с ним (помогая вам использовать все шаблоны, которые я вам рассказывал). – Gnucki

2

Я рекомендую вам начать с частичной документации SQLAlchemy Object Relational Tutorial, которая позволит вам лучше понять как реализованные концепции OO, так и представленные структуры данных. Он объясняет Единицу работы (сеансы), модель домена и различные типы отношений. Если вам нужно было прочитать только одну страницу (хотя и довольно крупную), это было бы так.

Но для того, чтобы вы начали, смотрите ниже автономный и запущенный код, в котором есть ваша модель, включая отношения «многие ко многим», вставку, обновление и удаление данных. На основе кода кода кода используется флажок и флажок-SQLAlchemy.

Кроме того, я бы действительно дали другие имена как ваши модели объектов и отношений:

A   -> Category 
AItem  -> [Category]Item 
ACollection -> [Item]Collection 
A.a_items -> items (with backref *category*) 

Ниже приведен код, комментарий [выход] линия с SQLALCHEMY_ECHO для того, чтобы скрыть/см казнены SQL заявления , Просто сохраните его в файле python и запустите его.

from flask import Flask 
from flask.ext.sqlalchemy import SQLAlchemy 

app = Flask(__name__) 
_db_uri = 'sqlite:///:memory:' 
app.config['SQLALCHEMY_DATABASE_URI'] = _db_uri 
app.config['SQLALCHEMY_ECHO'] = True # @TODO: uncomment to see SQL statements 
db = SQLAlchemy(app) 


# utility to make string representation of objects human-readable 
def _repr(self): 
    from sqlalchemy.orm import class_mapper 
    attrs = class_mapper(self.__class__).column_attrs # only columns 
    # attrs = class_mapper(self.__class__).attrs # show also relationships 
    return u"<{}({})>".format(
     self.__class__.__name__, 
     ', '.join(
      '%s=%r' % (k.key, getattr(self, k.key)) 
      for k in sorted(attrs) 
     ) 
    ) 
db.Model.__repr__ = _repr 


# DEFINE THE MODEL 
class A(db.Model): 
    __tablename__ = 'a' 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(64), unique=True) 

    a_items = db.relationship('AItem', backref='a') 

    def get_item_by_name(self, item_name): 
     """ In memory search for the item of this class of given name. """ 
     for item in self.a_items: 
      if item.name == item_name: 
       return item 


class AItem(db.Model): 
    __tablename__ = 'a_items' 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(64), unique=True) 
    A_id = db.Column(db.Integer, db.ForeignKey('a.id')) 


# this table contains many-to-many relationship 
t_collection_item = db.Table(
    'a_collection_item', db.Model.metadata, 
    db.Column('a_items_id', db.Integer, db.ForeignKey('a_items.id'), 
      primary_key=True), 
    db.Column('a_collections_id', db.Integer, db.ForeignKey('a_collections.id'), 
      primary_key=True) 
    ) 


class ACollection(db.Model): 
    __tablename__ = 'a_collections' 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(64)) 

    items = db.relationship(AItem, 
          secondary=t_collection_item, 
          backref='collections') 


def test_model(): 
    with app.app_context(): 
     db.create_all() 

     # CREATE SOME TEST DATA 
     # create instance of *A* 
     colors = A(name='colors') 
     smells = A(name='smells') 

     # add some items to them 
     colors.a_items = [ 
      AItem(name='red'), 
      AItem(name='green'), 
      AItem(name='blue'), 
      AItem(name='yellow'), 
      AItem(name='black'), 
     ] 
     smells.a_items = [ 
      AItem(name='superb'), 
      AItem(name='awful') 
     ] 

     # this will insert into DB instance of *A* and all their dependents 
     db.session.add(colors) 
     db.session.add(smells) 
     db.session.commit() 

     # create some collections, but first find colors 
     red = colors.get_item_by_name('red') 
     green = colors.get_item_by_name('green') 
     blue = colors.get_item_by_name('blue') 
     black = colors.get_item_by_name('black') 
     yellow = colors.get_item_by_name('yellow') 
     # create a new one 
     white = AItem(name='white') 
     colors.a_items.append(white) 

     coll1 = ACollection(name='my favorites', items=[red, green, blue]) 
     coll2 = ACollection(name='i hate these', items=[black, yellow]) 

     db.session.add_all([white, coll1, coll2]) 
     db.session.commit() 

     # SOME QUERIES 
     # get collections which has blue color 
     q = (db.session.query(ACollection) 
      .join(AItem, ACollection.items) 
      .filter(AItem.name == 'blue') 
      ) 
     for coll in q.all(): 
      print(coll) 
      for item in coll.items: 
       print(" {}".format(item)) 

     # Now I hate blue, so lets remove it from my collection and rename it 
     mycol = db.session.query(ACollection)\ 
      .filter(ACollection.name == 'my favorites').one() 
     mycol.name = 'my new favorites' 
     mycol.items.remove(blue) 
     db.session.commit() 
     assert 2 == len(mycol.items) 


if __name__ == '__main__': 
    test_model() 
Смежные вопросы