Yeah, I'm kind of rethinking my approach here. Appreciate the thoughts.

On Saturday, March 23, 2019 at 1:55:34 PM UTC-5, Mike Bayer wrote:
>
> Just FTR i was thinking about this Q today and I usually would opt to 
> make a Service object stateless, and things like "request" and User 
> would be passed into individual methods explicitly.   I usually start 
> application with a pattern that might be more verbose to start with, 
> but once you write half a dozen cases front to back, the most 
> appropriate pattern usually makes itself apparent and you then 
> refactor. 
>
> e.g. don't overplan ahead, do it stupidly simple then expect to 
> refactor a few times.    but also don't create state where it isnt 
> needed, if that makes sense. 
>
>
> On Sat, Mar 23, 2019 at 11:24 AM Andrew Martin <agma...@gmail.com 
> <javascript:>> wrote: 
> > 
> > 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+...@googlegroups.com <javascript:>. 
> > To post to this group, send email to sqlal...@googlegroups.com 
> <javascript:>. 
> > Visit this group at https://groups.google.com/group/sqlalchemy. 
> > For more options, visit https://groups.google.com/d/optout. 
>

-- 
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