kvesteri / wtforms-alchemy

Tools for creating wtforms from sqlalchemy models
Other
245 stars 59 forks source link

Model does not contain attribute named 'account_status'. #125

Open mark0978 opened 6 years ago

mark0978 commented 6 years ago

So, the full problem: I have a FK relationship to another model (from Account -> AccountStatus). I need that account_status model value (as a sqlalchemy object) to be available so that the QuerySelectField will "select" the current value when rendering the form. But since it is a RelationshipProperty instead of a Column property, I can't seem to get that to even allow me to declare the form, let alone instantiate it.

I must be missing something, because surely it is not this hard to do something this simple. The details around this problem are below.

The model looks like:

class BaseAccount(Base):
    ...
    account_status_id = Column('account_status_id', INTEGER(), ForeignKey('account_status.id'), nullable=False)
    ...

class Account(BaseAccount):
    """ base account contains all the Column properties, it is autogenerated by schema inspection"""
    ....
    account_status = relationship("AccountStatus")
    ...

Since account_status_id is in the model, I added I added a relationship (account_status) in an attempt to make that sqlalchemy attribute available on the model itself.

However when trying to use this in a QuerySelectField:

    def validate_attribute(self, attr_name):
        ...
        try:
            if not isinstance(attr.property, ColumnProperty):  <<<<<<< Problem Here (RelationshipProperty, NOT ColumnProperty)
                if self.meta.attr_errors:
                    raise InvalidAttributeException(attr_name)
                else:
                    return None, None
        except AttributeError:
            raise AttributeTypeException(attr_name)
        return attr_name, attr.property

wtforms_alchemy.exc.InvalidAttributeException: Model does not contain attribute named 'account_status'.

The form looks like:

class AccountUpdateForm(ModelForm):
    ...
    account_status = fields.QuerySelectField(label="Account Status",
                                             get_label="name",
                                             allow_blank=True,
                                             blank_text="[Select an account status]")
    ...
    class Meta:
        model = models.Account
        only = ["name", "disabled", "account_status", "account_manager",
                "notes", "type",]

    def __init__(self, db, formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs):
        super(AccountUpdateForm, self).__init__(formdata, obj, prefix, data, meta, **kwargs)
        self.account_status.query = db.query(models.AccountStatus)\
            .filter(models.AccountStatus.active == True)

How should I be doing this?

mark0978 commented 6 years ago

I have located this https://wtforms-alchemy.readthedocs.io/en/latest/relationships.html#one-to-many-relations However either there is too little functionality there, or the documentation is a bit too skinny since I see no way to use that to accomplish the list filtering that I am doing above.