Hey Malcolm, Thank you very much for your thoughts on those questions!
I will definitely be referring to your advice when I'm writing this thing. I had been thinking about those questions when I was on spring break (about a week or so) and couldn't seem to reach a conclusion, but, I think I'll be a bit better off now. Thank you again. -Sean On Apr 12, 11:16 pm, Malcolm Tredinnick <malc...@pointy-stick.com> wrote: > On Sun, 2009-04-12 at 20:41 -0700, Sean Neilan wrote: > > I'm building a large web application & I'm trying to figure out ways > > to organize my business logic (just the queries). I figure I should > > either put all my queries inside Model functions or ModelManager > > functions. I've searched all over the internet for documentation on > > where the business logic goes, but, didn't find what I was looking > > for. > > > I have a couple questions: > > Opinions vary a bit on these sorts of things. What follows are mine... > > > > > 1) Should Model methods not contain any queries? Only calculations > > based on the attributes of that model. Much like > >http://docs.djangoproject.com/en/dev/topics/db/models/#id4 > > When you have a model instance, it represents a single row in the > database. Methods on a Python class instance tend to act on that > instance, so it makes sense to have model methods act on the particular > data for that instance, not be more general. > > Now, it could well be that "acting on the instance" really means > "related to that instance" and does other queries to pull in > information. For example, my blog code currently has the world's lamest > tagging system (a very simple tag model with a name and a pointer to > itself for the parent) and I have methods on the model that are "get all > the descendents of this instance" and "get the ancestors of this > instance". They are methods that are specific to the instance at hand. > > > > > 2) Is it a good idea to encapsulate _all_ queries as methods inside of > > a manager class? Thus making it slightly easier to reuse queries. > > Abstracting everything to the n-th degree can often make code a lot > harder to read, so curb your enthusiasm a little bit here. > > Model managers tend to be a good place to put methods that act on the > collection of model instances. For example, using my lame tag example > again, a method to query all the tags matching a particular name prefix. > The documentation describes these as table-level methods, which tends to > be the way I've thought of them over the years. > > For genuinely reusable query fragments, I find myself writing normal > Python functions that accept a queryset as an argument. Then they aren't > tied to any particular model, although I have some implicit contract > with myself (as the user of those functions) that they querysets I pass > in will be for objects that, say, have a "title" attribute so I can > filter on the title. > > I will point out that some people like using classmethods for this sort > of stuff. For model class-level queries -- the table-level stuff -- I > find this looks very odd in code. It's one of those cases of not looking > like almost all other Django code. > > In general, I'm fairly negative about classmethods in Python, though, > since they're fairly unnecessary as Python already has ample namespacing > capabilities. Other languages have classmethod equivalents because > they're namespacing isn't as good. So you won't see me using classmethod > style operations and there's swearing involved when I have to use > somebody else's code that does (something that's happening in a > side-project at the moment -- the other app is making my code looking > fugly!) > > > > > 3) Is it a bad thing if a query inside of a Manager function uses > > filter() to join with or even return another object type/list? This > > obviously couples the query to the name of a model, but, also couples > > the manager to an object that it doesn't manage. (The object that it > > doesn't manage being joined in the query.) > > Trying to frame things as "bad" or "good" is probably not going to help > very much, since it leads to discussions about what is really bad or > good. I personally don't write things like that, since I like my > managers methods on model X to returns things about model X. > > However, I'm not a slave to "everything must be in a class" and normal > Python module-level functions are my good friends. So if I'm got > something that is related to model X and returns something that isn't a > queryset, I'll often just make it a function. The import statements > elsewhere in the code namespace it usefully and using the function is > pretty easy and not overly verbose. > > > 4) Also, Is it possible for a ModelManager object to gain access to > > request.user so that the objects returned depend on who's logged in? > > Not unless you pass it in. Models are completely independent of the > request/response cycle. They are only concerned with the persistent > storage of data (not even necessarily business rules -- they're not the > capital-M, MVC models). Request.user isn't a data storage thing. > > > Perhaps, if this is not a good design pattern (coupling the > > authentication mechanisms to the ModelManager), should I simply take a > > User object as a parameter on the ModelManager functions? > > I prefer that approach. Explicit over implicit. Some people shove > request.user into threadlocals and use that. I personally don't like it, > but I've used it from time to time as a last resort (or because the > existing code did). The problem there is that threadlocals are one of > the least "local" style of objects in all of Python, so it's not too > hard to end up with a real mess there. > > Hopefully that gives you some ideas to think about. Realise there isn't > (and shouldn't be) a unique solution to most of these questions. The > above are what has worked for me over a few years and probably a few > hundred thousand lines of Django application coding and reading, but I > might not be doing things the same way others do. > > Regards, > Malcolm --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to django-users@googlegroups.com To unsubscribe from this group, send email to django-users+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---