.. _integrator_extend_data_model: Extend the data model ===================== The Data model can be extended in the file ``/models.py`` and the corresponding admin interface configuration in the file ``/forms.py``. For example to add some user details, including a link to a new class named "Title", add to ``/models.py``:: # Used to hide the original user in the admin interface User.__acl__ = [DENY_ALL] class UserDetail(User): __label__ = _('userdetail') __plural__ = _('userdetails') __tablename__ = 'userdetail' __table_args__ = {'schema': _schema} __acl__ = [ (Allow, Authenticated, ALL_PERMISSIONS), ] __mapper_args__ = {'polymorphic_identity': 'detailed'} id = Column(types.Integer, ForeignKey(_schema + '.user.id'), primary_key=True) phone = Column(types.Unicode, nullable=False, label=_(u'phone')) # title title_id = Column(Integer, ForeignKey(_schema + '.title.id'), nullable=False) title = relationship("Title", backref=backref('users')) def __init__(self, username=u'', password=u'', functionalities=[], phone=u'', email=u'', title=None, role=None): User.__init__(self, username, password, email, functionalities, role) self.phone = phone self.title = title class Title(Base): __label__ = _('title') __plural__ = _('titles') __tablename__ = 'title' __table_args__ = {'schema': _schema} __acl__ = [ (Allow, Authenticated, ALL_PERMISSIONS), ] id = Column(types.Integer, primary_key=True) name = Column(types.Unicode, nullable=False, label=_(u'Name')) description = Column(types.Unicode, label=_(u'Description')) def __init__(self, name=u'', description=u''): self.name = name self.description = description def __unicode__ (self): return self.name or u'' And in the file ``/forms.py``:: # Add a field set (form) for the title Title = FieldSet(models.Title) # Add a field set for the user details UserDetail = FieldSet(models.UserDetail) # Need to hide the password password = forms.DblPasswordField(UserDetail, UserDetail._password) UserDetail.append(password) # Fix the fields order fieldOrder = [UserDetail.username.validate(forms.unique_validator) .with_metadata(mandatory=''), password, UserDetail.role] if hasattr(UserDetail, 'parent_role'): fieldOrder.append(UserDetail.parent_role) fieldOrder.extend([UserDetail.title, UserDetail.functionalities. set(renderer=forms.FunctionalityCheckBoxTreeSet)]) UserDetail.configure(include=fieldOrder) # Add a grid for the title TitleGrid = Grid(models.Title) # Add a grid for the user details UserGrid = Grid(models.UserDetail) # Visible fields fieldOrder = [UserDetail.username, UserDetail.title, UserDetail.functionalities, UserDetail.role] if hasattr(UserGrid, 'parent_role'): fieldOrder.append(UserDetail.parent_role) UserGrid.configure(include=fieldOrder) We can change the renderer of a field, for example change the Role renderer:: Role.name.set(renderer=AnOtherRenderer, ...) And if we need an other resource (javascript or stylesheet):: from fa.jquery import fanstatic_resources from fanstatic import Resource, Group, Library from pyramid_formalchemy import events as fa_events fanstatic_lib = Library('_admin', 'static') new_js = Resource(fanstatic_lib, '', depends=[fanstatic_resources.]) new_css = Resource(fanstatic_lib, '') @fa_events.subscriber([models.Role, fa_events.IBeforeRenderEvent]) def before_render_role(context, event): Group([new_js, new_css]).need() And in the ``setup.py`` we need to add in the ``entry_points``:: 'fanstatic.libraries': [ '_admin = .forms:fanstatic_lib', ],