I just realized that almost everything about how I'm using mixins here is 
pretty much wrong. This is probably a garbage question and can be deleted, 
but I don't want to do it myself in case someone is writing a response to 
tell me that.

On Saturday, March 23, 2019 at 9:00:49 AM UTC-5, Andrew Martin wrote:
>
> I like to keep my models separate from actions on it, so I only use them 
> for defining tables, relationships, and indexes. To perform actions on a 
> model I use a service that inherits from the model and provides . . . well. 
> services. It's an interface pattern. I'm making these more generic, and 
> separating out repeated code into a mixin. It works fine, but I kind of 
> hate the implementation because it feels wrong and fragile to me. I was 
> wondering if anyone had some suggestions to improve how I'm doing this.
>
> Here are some examples.
>
>
> class User(Base):
>     __tablename__ = 'users'
>     __table_args__ = {'sqlite_autoincrement': True}
>
>     # postgres implementation for later
>     # user_id_seq = Sequence('user_id_seq', metadata=Base.metadata)
>     # id = Column(BigInteger, user_id_seq, 
> server_default=user_id_seq.next_value(), primary_key=True)
>     id = Column(Integer, primary_key=True)
>     resource_uid = Column(Text, nullable=False)
>     username = Column(Text, nullable=False, unique=True)
>     hashed_password = Column(Text, nullable=True)
>     is_enabled = Column(Integer, default=1, nullable=False)
>
>
> class CRUDMixIn:
>     def __init__(self):
>         # super().__init__()
>         print('initing crud mixin')
>         # This assumes that there are only two MixIns used in the service in 
> this order
>         # e.g.: class XService(FormMixIn, CRUDMixIn, User):
>         self.model = self.__class__.mro()[3]
>
>     def get_one_by_id(self, id):
>         one_row = 
> self.request.dbsession.query(self.model).filter(self.model.id == id).first()
>         return one
>
>     def get_all(self):
>         all_rows = self.request.dbsession.query(self.model).all()
>         return all_rows
>
>
> class UserService(FormMixIn, CRUDMixIn, User):
>     def __init__(self, request: Request):
>         super().__init__()
>         self.request = request
>
>     # other user related methods and business logic
>
>
>
> What is obviously really gross about this is getting the class for the 
> MixIn. Relying on the MRO means that anyone using it has to keep the same 
> order, and that feels wrong. But it doesn't feel as wrong repeating a bunch 
> of boilerplate CRUD code. I've looked at more than a few web/CRUD 
> frameworks, and I don't see people doing things like this. Most often what 
> I see is people putting generic CRUD functions in the Declarative Base, and 
> I really don't like that coupling there. I'd much prefer to have the model 
> layer separated from its actions. I had thought about setting the model in 
> the UserService like this:
>
> class UserService(FormMixIn, CRUDMixIn, User):
>     def __init__(self, request: Request):
>         super().__init__()
>         self.request = request
>         self.model = User
>
>
> But that returns a <class 
> 'sqlalchemy.ext.declarative.api.DeclarativeMeta'> instead of <class 
> models.User>, so I still have to get to the MRO there to get the user model 
> to query and it ends up being just as ugly. Although, I guess that's more 
> stable than what I'm doing now because the model MRO isn't going to change 
> often (or ever, maybe?).
>
> Anyway, I'm curious if anyone has thoughts about how I can make this 
> better or less fragile.
>
> thanks!
>
>
>

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to