Django and the domain layer
How to organize my domain layer using django?
I know I can write custom managers to hold my queries b开发者_StackOverflow中文版ut what if I want something more flexible like the specification pattern.
Is there any domain patterns that are unique to Django?
I am currently designing a large application that uses Django and I'd like to know how to do the domain layer right.
This question is a bit subjective, but here are my two cents:
- Business logic for changing multiple objects at the same time should in general go in a manager.
- Special logic for creating an object should be in the manager, think
MyModel.objects.create_complex(foo, bar)
- Business logic for calculating custom info, updating some complex field, etc, should be in methods (or properties) on your models, think
my_instance.get_accumulated_interest()
. These should not save the model, only update some fields and then return. - Business logic for validating information should either go in
clean
methods on the model or asclean
methods in special forms. If it is on the model it can be reused from different parts of the system more easily. - In general, if you cannot find a place to put the logic that makes sense, I put them in the views.
- Offline processing should go in custom management commands and you should be able to rerun the same command with the same arguments multiple times without any unwanted effects.
When I say "should go in X", I mean that these parts of the system should call into your own modules that may be separate from Django alltogether. This may make it easier to test these functions in isolation.
Edit:
For the "specification pattern" I would suggest writing a higher-level module that calls manager methods to filter objects. With Q objectsyou can create generic filters that you can use like this:
q = Q(field__isnull = False) | Q(otherfield__isnull = False)
objects = Model.objects.filter(q)
Edit II:
It just struck me: Python allows very generic programming. Classes and functions are first-class citizens. Consider the following example:
def HasFooBar(model_class):
return list(model_class.objects.filter(somefield__contains = 'foobar'))
def BarHasBaz(model_class, arg):
return list(model_class.objects.filter(somefield = arg))
objects = HasFooBar(MyModel) + BarHasBaz(OtherModel, baz)
You see what I just did there? :)
精彩评论