Camelot (Python framework): Specifying an Alternative EntityAdmin
Question: With the Camelot framework, models (subclassed from Entity) are defined with a
nested class (subclasses from EntityAdmin) that defines various gui properties
like layout and other widgets. The documentation indicates that multiple
EntityAdmins can be defined and then specified by the calling model:

> ### admin
>
> In case of relation fields, specifies the admin class that is to be used to
> visualize the other end of the relation. Defaults to the default admin class
> of the target class. This can be used to make the table view within a
> one2many widget look different from the default table view for the same
> object. [Camelot: Field Attributes man page](http://python-
> camelot.s3.amazonaws.com/gpl/release/pyqt/doc/doc/field_attributes.html#admin)

I can't seem to figure to figure out the required syntax. As a case study, can
anyone help me figure out how to do this with the "camelot-example" in the
package? (Camelot 13.04.13, Python 2.7.6)

Here is my example code:

    
    
    from sqlalchemy.schema import Column
    from sqlalchemy.types import Unicode, Integer
    
    from camelot.admin.entity_admin import EntityAdmin
    from camelot.core.orm import Entity, ManyToOne, OneToMany
    import camelot.types
    
    
    class Company(Entity):
        __tablename__ = 'company'
    
        name = Column(Unicode())
        city = Column(Unicode())
        employees = OneToMany('Employee')
    
        def __unicode__(self):
            return self.name or ''
    
        class Admin(EntityAdmin):
            verbose_name = 'Company'
            verbose_name_plural = 'Companies'
            list_display = ['name', 'city', 'employees']
            field_attributes = {'employees': {'create_inline': True},
                                              'admin': 'AlternativeAdmin'}
    
    
    class Employee(Entity):
        __tablename__ = "employee"
    
        name = Column(Unicode())
        age = Column(Integer())
        company = ManyToOne('Company')
    
        def __unicode__(self):
            return self.name or ''
    
        class Admin(EntityAdmin):
            verbose_name = 'Employee'
            list_display = ['name', 'age', 'company']
    
        class AlternativeAdmin(EntityAdmin):
            verbose_name = 'Employee'
            list_display = ['name']
    

Note:

  * "admin" under Company.Admin.field_attributes
  * The "AlternativeAdmin" class

**This code runs without errors, but it does not work as intended**. The
company form displays an employee subform that shows name, age, and company.
It should just show company. I've tried the following for the "admin" value:

    
    
    'AlternativeAdmin'
    AlternativeAdmin
    'Employee.AlternativeAdmin'
    Employee.AlternativeAdmin
    

The error I get when uncommenting is:

NameError: name 'AlternativeAdmin' is not defined

I'm a self-confessed Python novice and I suspect some better Python
understanding could help me solve this.

I managed to find this via the great magic eight-ball (Google): A forum-poster
said this (sic), "Stupid me, I insisted in the alternate admin class being an
inner class just like the original one. Once I unnested it, it worked." He was
referencing this code:

    
    
    class A(Entity):
         ...
         class Admin(EntityAdmin):
              ...
         class AdminEmbedded(EntityAdmin):
             ...
    
    class B(Entity):
         classA = OneToMany(...)
         ...
         class Admin(EntityAdmin):
              field_attributes = dict(classA=dict(admin=A.AdminEmbedded???))
    

Unfortunately, his grammar and/or spelling makes it hard to discern what he
meant. Also, I'm pretty sure there should be some quotes in there.


Answer: I figured it out. The answer induced a face-palm -- I left the
AlternativeAdmin class definition below where it was called after I un-nested
it. Once I moved it above, it worked fine.

Here is a full fixed version of the example in my question:

    
    
    from sqlalchemy.schema import Column
    from sqlalchemy.types import Unicode, Integer
    
    from camelot.admin.entity_admin import EntityAdmin
    from camelot.core.orm import Entity, ManyToOne, OneToMany
    import camelot.types
    
    
    class AlternativeAdmin(EntityAdmin):
        verbose_name = 'Employee'
        list_display = ['name']
    
    
    class Company(Entity):
        __tablename__ = 'company'
    
        name = Column(Unicode())
        city = Column(Unicode())
        employees = OneToMany('Employee')
    
        def __unicode__(self):
            return self.name or ''
    
        class Admin(EntityAdmin):
            verbose_name = 'Company'
            verbose_name_plural = 'Companies'
            list_display = ['name', 'city', 'employees']
            field_attributes = {'employees': {'create_inline': True,
                                              'admin': AlternativeAdmin}}
    
    
    class Employee(Entity):
        __tablename__ = "employee"
    
        name = Column(Unicode())
        age = Column(Integer())
        company = ManyToOne('Company')
    
        def __unicode__(self):
            return self.name or ''
    
        class Admin(EntityAdmin):
            verbose_name = 'Employee'
            list_display = ['name', 'age', 'company']
    

