Structuring Django-App to Attach Custom Business Rules to Object Instances
I'm torn how to structure my code to accommodate business rules specific to instances of a particular model.
For example. Lets say I have a Contact model with a type field and choices=(('I','Individual'),('C','Company))
. Based on the type of model that I have, I might want to have custom methods.
So thinking out loud, something like this would be nice:
class IndividualContact(Contact):
""" A custom class used for Contact instances with type='I' """
criteria = Q(type='I')
# The goal here is that Contact is now aware of IndividualContact and constructs
# objects accordingly.
Contact.register(IndividualContact)
Or even:
class SpecialContact(Contact):
""" A custom class used for the contact with pk=1 """
criteria = Q(pk=1)
At which point I have a nice home for my special instance specific code.
One of the alternatives I explored is using model inheritance and avoiding things like type fields that impart new behaviors. That way, new classes plug into the existing framework elegantly and you're nicely set up to add custom fields to your different types in case you need them.
In my case I have a resource crediting system on the site that allows me to say things like "You may only have 2 Listings and 20 Photos". Individual resource types are rationed, but there is a generic credit table that gives you credits for various content types. The logic that goes into counting up your Listings and Photos varies based on the type of object you're working with.
I.E.:
listing_credit = Credit.objects.create(content_type=ContentType.objects.get_for_model(Listing), user=user, credit_amt=2)
# Should subtract **active** listings from current sum total of Listing credits.
listing_credit.credits_remaining()
photo_credit = Credit.objects.create(content_开发者_C百科type=ContentType.objects.get_for_model(Photo), user=user, credit_amt=5)
# Photos have no concept of an active status, so we just subtract all photos from the current sum total of Listing credits.
# Also, the Photo might be associated to it's user through a 'created_by' field whereas
# Listing has a user field.
photo_credit.credits_remaining()
My current approach is separate classes but I'd like to reduce that boilerplate and he necessity of creating N separate tables with only a credit_ptr_id
.
Take a look at django proxy models. They allow you to do exactly what you want.
http://docs.djangoproject.com/en/dev/topics/db/models/#proxy-models
But since in you case the behavior is dependent on the field value, then you should add custom managers to the proxy models that retrieve items only of only that type on queries.
精彩评论