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

Reply via email to