class Organization(Party): """An organization represents any internal or external organization. Organizations can include businesses and groups of individuals""" using_options(tablename='organization') party_id = Field(Integer, ForeignKey('party.id'), primary_key=True) __mapper_args__ = {'polymorphic_identity': u'organization'} name = Field(Unicode(50), required=True, index=True) logo = Field(camelot.types.Image(upload_to='organization-logo'), deferred=True) tax_id = Field(Unicode(20)) directors = OneToMany('DirectedDirector', inverse='established_from', cascade='all, delete, delete-orphan') employees = OneToMany('EmployerEmployee', inverse='established_from', cascade='all, delete, delete-orphan') suppliers = OneToMany('SupplierCustomer', inverse='established_to', cascade='all, delete, delete-orphan') customers = OneToMany('SupplierCustomer', inverse='established_from', cascade='all, delete, delete-orphan') shareholders = OneToMany('SharedShareholder', inverse='established_from', cascade='all, delete, delete-orphan') def __unicode__(self): return self.name or '' @property def number_of_shares_issued(self): return sum((shareholder.shares for shareholder in self.shareholders), 0)
class User( self.Entity ): name = Field(String(50)) boston_addresses = OneToMany('Address', primaryjoin=lambda: and_(Address.user_id == User.id, Address.city == u'Boston'), viewonly=True ) addresses = OneToMany('Address')
class FazeActivitate(Entity): __tablename__ = 'faze_activitati' nume = Column(Unicode(30)) descriere = Column(Unicode(200)) data_inceput = Column(Date) data_sfarsit = Column(Date) task = OneToMany('Task') activitate = ManyToOne('Activitate') def __unicode__(self): return unicode(self.activitate) or 'Unknown' class Admin(EntityAdmin): verbose_name = 'Faza Activitate' verbose_name_plural = 'Faze Activitati' list_display = ['nume', 'descriere', 'data_inceput', 'data_sfarsit'] form_display = TabForm([('Importante', Form(['nume', 'descriere', 'data_inceput', 'data_sfarsit'])), ('Taskuri', Form(['task']))] ) class Admin2(EntityAdmin): verbose_name = 'Calendar' verbose_name_plural = 'Calendar' list_display = ['data_inceput','nume', 'descriere', 'data_sfarsit'] Admin2 = not_editable_admin(Admin2)
class TreeNode( self.Entity ): using_options(order_by='name') name = Field(String(50), required=True) parent = ManyToOne('TreeNode') children = OneToMany('TreeNode', inverse='parent') root = ManyToOne('TreeNode')
class ContactMechanism(Entity): using_options(tablename='contact_mechanism') mechanism = schema.Column(camelot.types.VirtualAddress(256), nullable=False) party_address = ManyToOne(PartyAddress, ondelete='set null', onupdate='cascade') party_contact_mechanisms = OneToMany('PartyContactMechanism') def __unicode__(self): if self.mechanism: return u'%s : %s' % (self.mechanism[0], self.mechanism[1]) class Admin(EntityAdmin): form_size = (700, 150) verbose_name = _('Contact mechanism') list_display = ['mechanism'] form_display = Form(['mechanism', 'party_address']) field_attributes = {'mechanism': {'minimal_column_width': 25}} def get_depending_objects(self, contact_mechanism): for party_contact_mechanism in contact_mechanism.party_contact_mechanisms: yield party_contact_mechanism party = party_contact_mechanism.party if party: yield party
class Activitate(Entity): __tablename__ = 'activitati' tip = Column(String(30)) __mapper_args__ = {'polymorphic_on': tip} nume = Field(Unicode(50), required=True, index=True) coordonator = ManyToOne('ResurseUmane', inverse='activitati_coordonate') membrii = ManyToMany('ResurseUmane') aprobata = Column(Boolean) res_fin = OneToMany('ResurseFinanciare', inverse="activitate") res_logistice = ManyToMany('ResursaLogistica') #todo adaugat faze activitate faze = OneToMany("FazeActivitate") def __unicode__(self): return self.nume or '' class Admin(EntityAdmin): verbose_name = 'Activitate' verbose_name_plural = 'Activitati' list_display = ['nume', 'aprobata'] form_display = TabForm([('Importante', Form(['nume', 'coordonator'])), ('Participanti', Form(['membrii'])), ('Resurse', Form(['res_fin', 'res_logistice'])), ('Faze', Form(['faze']))]) field_attributes = dict(ResurseUmane.Admin.field_attributes) form_actions = [RapoarteActivitati()] class Admin2(EntityAdmin): verbose_name = 'Calendar activitati' list_display = ['nume', 'coordonator', 'aprobata'] def get_query(self): session = Session return session.query(Activitate).join(ResurseUmane).filter( ResurseUmane.id == 1) # todo schimbat cu userul # curent class Admin3(EntityAdmin): verbose_name = 'Proiect Departament' verbose_name_plural = 'Proiecte Departament' list_display = ['nume', 'coordonator', 'aprobata', 'tip'] Admin3 = not_editable_admin(Admin3)
class DirectedDirector(PartyRelationship): """Relation from a directed organization to a director""" using_options(tablename='party_relationship_dir') established_from = ManyToOne(Organization, required=True, ondelete='cascade', onupdate='cascade') established_to = ManyToOne(Party, required=True, ondelete='cascade', onupdate='cascade') title = Field(Unicode(256)) represented_by = OneToMany('RepresentedRepresentor', inverse='established_to') partyrelationship_id = Field(Integer, ForeignKey('party_relationship.id'), primary_key=True) __mapper_args__ = {'polymorphic_identity': 'directeddirector'} class Admin(PartyRelationship.Admin): verbose_name = _('Direction structure') verbose_name_plural = _('Direction structures') list_display = [ 'established_from', 'established_to', 'title', 'represented_by' ] list_search = [ 'established_from.full_name', 'established_to.full_name' ] field_attributes = { 'established_from': { 'name': _('Organization') }, 'established_to': { 'name': _('Director') } } class DirectorAdmin(Admin): verbose_name = _('Director') list_display = ['established_to', 'title', 'from_date', 'thru_date'] form_display = [ 'established_to', 'title', 'from_date', 'thru_date', 'represented_by', 'comment' ] class DirectedAdmin(Admin): verbose_name = _('Directed organization') list_display = ['established_from', 'title', 'from_date', 'thru_date'] form_display = [ 'established_from', 'title', 'from_date', 'thru_date', 'represented_by', 'comment' ]
class ResurseUmane(Entity): __tablename__ = 'resurse_umane' username = Column(String(30)) nume = Column(String(50)) doctorat = Column(Boolean) functie = Column(String(30)) activitati = ManyToMany('Activitate') activitati_coordonate = OneToMany('Activitate') taskuri = OneToMany("Task", inverse="membrii") __mapper_args__ = { 'polymorphic_on': functie, } def __unicode__(self): return self.nume or 'Unknown' class Admin(EntityAdmin): verbose_name = 'Resurse Umane' verbose_name_plural = 'Resurse Umane' list_display = ['username', 'nume', 'doctorat', 'functie']
class Address(Entity): """The Address to be given to a Party (a Person or an Organization)""" using_options(tablename='address') street1 = Field(Unicode(128), required=True) street2 = Field(Unicode(128)) city = ManyToOne(City, required=True, ondelete='cascade', onupdate='cascade', lazy='subquery') party_addresses = OneToMany('PartyAddress') def name(self): return sql.select( [self.street1 + ', ' + GeographicBoundary.full_name], whereclause=( GeographicBoundary.id == self.city_geographicboundary_id)) name = ColumnProperty(name, deferred=True) @classmethod def get_or_create(cls, street1, street2, city): address = cls.query.filter_by(street1=street1, street2=street2, city=city).first() if not address: address = cls(street1=street1, street2=street2, city=city) orm.object_session(address).flush() return address def __unicode__(self): return u'%s, %s' % (self.street1 or '', self.city or '') class Admin(EntityAdmin): verbose_name = _('Address') verbose_name_plural = _('Addresses') list_display = ['street1', 'street2', 'city'] form_size = (700, 150) field_attributes = {'street1': {'minimal_column_width': 30}} def get_depending_objects(self, address): for party_address in address.party_addresses: yield party_address if party_address.party != None: yield party_address.party
class Person(Party): """Person represents natural persons """ using_options(tablename='person') party_id = Field(Integer, ForeignKey('party.id'), primary_key=True) __mapper_args__ = {'polymorphic_identity': u'person'} first_name = Field(Unicode(40), required=True) last_name = Field(Unicode(40), required=True) # end short person definition middle_name = Field(Unicode(40)) personal_title = Field(Unicode(10)) suffix = Field(Unicode(3)) sex = Field(Unicode(1), default=u'M') birthdate = Field(Date()) martial_status = Field(Unicode(1)) social_security_number = Field(Unicode(12)) passport_number = Field(Unicode(20)) passport_expiry_date = Field(Date()) is_staff = Field(Boolean, default=False, index=True) is_superuser = Field(Boolean, default=False, index=True) picture = Field(camelot.types.Image(upload_to='person-pictures'), deferred=True) comment = Field(camelot.types.RichText()) employers = OneToMany('EmployerEmployee', inverse='established_to', cascade='all, delete, delete-orphan') @property def note(self): for person in self.__class__.query.filter_by( first_name=self.first_name, last_name=self.last_name): if person != self: return _('A person with the same name already exists') @property def name(self): # we don't use full name in here, because for new objects, full name will be None, since # it needs to be fetched from the db first return u'%s %s' % (self.first_name, self.last_name) def __unicode__(self): return self.name or ''
class Profile(Entity): __tablename__ = 'profile' LastName = Column(Unicode(60), nullable=False) FirstName = Column(Unicode(60), nullable=False) DateOfBirth = Column(Date) Devices = OneToMany('OwnedDevice') def __unicode__(self): return self.Name class Admin(EntityAdmin): verbose_name = 'Profile' list_display = ['LastName', 'FirstName', 'DateOfBirth'] form_display = forms.TabForm([('Profile', forms.Form([ 'LastName', 'FirstName', 'DateOfBirth', 'Devices', ]))])
class A( self.Entity ): name = Field(String(60)) bs = OneToMany('B')
class Table1( self.Entity ): t1id = Field(Integer, primary_key=True) name = Field(String(30)) tbl2s = OneToMany('Table2') tbl3 = OneToOne('Table3')
class Movie(Entity): __tablename__ = 'movies' title = Column(sqlalchemy.types.Unicode(60), nullable=False) short_description = Column(sqlalchemy.types.Unicode(512)) releasedate = Column(sqlalchemy.types.Date) genre = Column(sqlalchemy.types.Unicode(15)) rating = Column(camelot.types.Rating()) # # All relation types are covered with their own editor # director = ManyToOne('Person') cast = OneToMany('Cast') visitor_reports = OneToMany('VisitorReport', cascade='delete') tags = ManyToMany('Tag', tablename='tags_movies__movies_tags', local_colname='tags_id', remote_colname='movies_id') # end short movie definition # # Camelot includes custom sqlalchemy types, like Image, which stores an # image on disk and keeps the reference to it in the database. # # begin image definition cover = Column(camelot.types.Image(upload_to='covers')) # end image definition # # Or File, which stores a file in the upload_to directory and stores a # reference to it in the database # script = Column(camelot.types.File(upload_to='script')) description = Column(camelot.types.RichText) # # Normal python properties can be used as well, but then the # delegate needs be specified in the Admin.field_attributes # @property def visitors_chart(self): # # Container classes are used to transport chunks of data between # the model the gui, in this case a chart # from camelot.container.chartcontainer import BarContainer return BarContainer(range(len(self.visitor_reports)), [vr.visitors for vr in self.visitor_reports]) # begin column_property @ColumnProperty def total_visitors(self): return sql.select([sql.func.sum(VisitorReport.visitors)], VisitorReport.movie_id == self.id) # end column_property # # Each Entity subclass can have a subclass of EntityAdmin as # its inner class. The EntityAdmin class defines how the Entity # class will be displayed in the GUI. Its behavior can be steered # by specifying some class attributes # # To fully customize the way the entity is visualized, the EntityAdmin # subclass should overrule some of the EntityAdmin's methods # class Admin(EntityAdmin): # the list_display attribute specifies which entity attributes should # be visible in the table view list_display = [ 'cover', 'title', 'releasedate', 'rating', ] lines_per_row = 5 # define filters to be available in the table view list_filter = ['genre', ComboBoxFilter('director.full_name')] # if the search function needs to look in related object attributes, # those should be specified within list_search list_search = ['director.full_name'] # begin list_actions # # the action buttons that should be available in the list view # list_actions = [ChangeRatingAction()] # end list_actions drop_action = DropAction() # the form_display attribute specifies which entity attributes should be # visible in the form view form_display = TabForm([ ('Movie', Form([ HBoxForm( [WidgetOnlyForm('cover'), ['title', 'rating', Stretch()]]), 'short_description', 'releasedate', 'director', 'script', 'genre', 'description', ], columns=2)), ('Cast', WidgetOnlyForm('cast')), ('Visitors', WidgetOnlyForm('visitors_chart')), ('Tags', WidgetOnlyForm('tags')) ]) # begin form_actions # # create a list of actions available for the user on the form view # form_actions = [BurnToDisk()] # end form_actions # # additional attributes for a field can be specified in the # field_attributes dictionary # field_attributes = dict( cast=dict(create_inline=True), genre=dict(choices=genre_choices, editable=lambda o: bool(o.title and len(o.title))), releasedate=dict(background_color=lambda o: ColorScheme.orange_1 if o.releasedate and o.releasedate < datetime. date(1920, 1, 1) else None), visitors_chart=dict(delegate=delegates.ChartDelegate), rating=dict(tooltip='''<table> <tr><td>1 star</td><td>Not that good</td></tr> <tr><td>2 stars</td><td>Almost good</td></tr> <tr><td>3 stars</td><td>Good</td></tr> <tr><td>4 stars</td><td>Very good</td></tr> <tr><td>5 stars</td><td>Awesome !</td></tr> </table>'''), smiley=dict(delegate=delegates.SmileyDelegate), script=dict(remove_original=True)) def __unicode__(self): return self.title or ''
class Artist(self.Entity): name = Field(String(30)) records = OneToMany('Record', order_by=['year', '-title'])
class Party(Entity): """Base class for persons and organizations. Use this base class to refer to either persons or organisations in building authentication systems, contact management or CRM""" using_options(tablename='party') addresses = OneToMany('PartyAddress', lazy=True, cascade="all, delete, delete-orphan") contact_mechanisms = OneToMany('PartyContactMechanism', lazy='select', cascade='all, delete, delete-orphan') shares = OneToMany('SharedShareholder', inverse='established_to', cascade='all, delete, delete-orphan') directed_organizations = OneToMany('DirectedDirector', inverse='established_to', cascade='all, delete, delete-orphan') status = Status() categories = ManyToMany('PartyCategory', tablename='party_category_party', remote_colname='party_category_id', local_colname='party_id') row_type = schema.Column(Unicode(40), nullable=False) __mapper_args__ = {'polymorphic_on': row_type} @property def name(self): return '' def _get_contact_mechanism(self, described_by): """Get a specific type of contact mechanism """ for party_contact_mechanism in self.contact_mechanisms: contact_mechanism = party_contact_mechanism.contact_mechanism if contact_mechanism != None: mechanism = contact_mechanism.mechanism if mechanism != None: if mechanism[0] == described_by: return mechanism def _set_contact_mechanism(self, described_by, value): """Set a specific type of contact mechanism """ assert value[0] in camelot.types.VirtualAddress.virtual_address_types for party_contact_mechanism in self.contact_mechanisms: contact_mechanism = party_contact_mechanism.contact_mechanism if contact_mechanism != None: mechanism = contact_mechanism.mechanism if mechanism != None: if mechanism[0] == described_by: if value and value[1]: contact_mechanism.mechanism = value else: session = orm.object_session( party_contact_mechanism) self.contact_mechanisms.remove( party_contact_mechanism) if party_contact_mechanism.id: session.delete(party_contact_mechanism) return if value and value[1]: contact_mechanism = ContactMechanism(mechanism=value) party_contact_mechanism = PartyContactMechanism( contact_mechanism=contact_mechanism) self.contact_mechanisms.append(party_contact_mechanism) @hybrid.hybrid_property def email(self): return self._get_contact_mechanism(u'email') @email.setter def email_setter(self, value): return self._set_contact_mechanism(u'email', value) @email.expression def email_expression(self): return Email.mechanism @hybrid.hybrid_property def phone(self): return self._get_contact_mechanism(u'phone') @phone.setter def phone_setter(self, value): return self._set_contact_mechanism(u'phone', value) @phone.expression def phone_expression(self): return Phone.mechanism @hybrid.hybrid_property def fax(self): return self._get_contact_mechanism(u'fax') @fax.setter def fax_setter(self, value): return self._set_contact_mechanism(u'fax', value) @fax.expression def fax_expression(self): return Fax.mechanism def _get_address_field(self, name): for party_address in self.addresses: return getattr(party_address, name) def _set_address_field(self, name, value): if not self.addresses: address = PartyAddress() self.addresses.append(address) address = self.addresses[0] setattr(address, name, value) if address.street1 == None and address.street2 == None and address.city == None: session = orm.object_session(address) if address in session.new: session.expunge(address) self.addresses.remove(address) else: session.delete(address) @hybrid.hybrid_property def street1(self): return self._get_address_field(u'street1') @street1.setter def street1_setter(self, value): return self._set_address_field(u'street1', value) @hybrid.hybrid_property def street2(self): return self._get_address_field(u'street2') @street2.setter def street2_setter(self, value): return self._set_address_field(u'street2', value) @hybrid.hybrid_property def city(self): return self._get_address_field(u'city') @city.setter def city_setter(self, value): return self._set_address_field(u'city', value) def full_name(self): aliased_organisation = sql.alias(Organization.table) aliased_person = sql.alias(Person.table) return sql.functions.coalesce( sql.select( [ sql.functions.coalesce(aliased_person.c.first_name, '') + ' ' + sql.functions.coalesce(aliased_person.c.last_name, '') ], whereclause=and_(aliased_person.c.party_id == self.id), ).limit(1).as_scalar(), sql.select( [aliased_organisation.c.name], whereclause=and_(aliased_organisation.c.party_id == self.id), ).limit(1).as_scalar()) full_name = ColumnProperty(full_name, deferred=True)
class Category(self.Entity): name = Field(String(16)) users = OneToMany('User', lazy=False) score = ColumnProperty(lambda c: select([func.avg( User.score)], User.category_id == c.id).as_scalar())
class User(self.Entity): name = Field(String(16)) category = ManyToOne('Category') tags = OneToMany('Tag', lazy=False) score = ColumnProperty(lambda c: select([func.sum( Tag.score)], Tag.user_id == c.id).as_scalar())
class Person( self.Entity ): name = Field(String(30)) father = ManyToOne('Person', inverse='children') children = OneToMany('Person', inverse='father')
class A( self.Entity ): name = Field(String(60), unique=True) bs = OneToMany('B')
class User( self.Entity ): name = Field(String(50)) boston_addresses = OneToMany('Address', filter=lambda c: c.city == u'Boston') addresses = OneToMany('Address')