I have a Flask SQLAlchemy project with 3 ORM tables, Category, Vendor, and CategoryVendorMap, and I am using Flask-Marshmallow to define schemas for the api.
Relationships:
Category has many Vendors by way of CategoryVendorMap. CategoryVendorMap also has an is_default
flag indicating the default Vendor for a Category. This is_default
field has also been denormalized onto the Category table.
Is there a way to set the is_default
value of the CategoryVendorMap
object by only accessing the Category
ORM Mapper? Basically I want to set the Category.default_vendor_id
field and have the setter for this field updated the appropriate CategoryVendorMap
associations.I know I could just update the CategoryVendorMap
objects directly, however ultimately my models are exposed via an api and I would like to avoid exposing this object, and creating custom controller logic to handle this use case.
class CategoryVendorMap(db.Model):
__tablename__ = "CategoryVendorMap"
__table_args__ = (
db.PrimaryKeyConstraint('category_id', 'vendor_id'),
)
category_id = db.Column(db.Integer, db.ForeignKey('Category.category_id'))
vendor_id = db.Column(db.Integer, db.ForeignKey('Vendor.vendor_id'))
is_default = db.Column(db.Boolean, default=False)
category = db.relationship('Category', backref=db.backref("category_vendors", cascade="all, delete-orphan"))
vendor = db.relationship('Vendor')
class Category(db.Model):
__tablename__ = 'Category'
@property
def default_vendor_id(self):
if self.category_vendors:
default_vendor_id = [cat_vendor_map for cat_vendor_map in self.category_vendors if cat_vendor_map.is_default]
return default_vendor_id[0].vendor_id if default_vendor_id else None
return
@default_vendor_id.setter
def default_vendor_id(self, vendor_id):
return int(vendor_id)
category_id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), unique=False, nullable=False)
vendors = association_proxy("category_vendors", "vendor",
creator=lambda vendor: CategoryVendorMap(vendor=vendor))
class Vendor(db.Model):
__tablename__ = 'Vendor'
vendor_id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True, nullable=False)