On Sat, Jun 30, 2012 at 5:26 PM, Nick Apostolakis <nickapos@oncrete.gr> wrote:
> Interesting idea, I haven't used that yet, could you give an example of
> that?
> Would you use a method calling the ORM that would include something like
> self.objects.select_related().bla bla?
for example: when modelling the requested/accepted/rejected of a
'friendship' relation between 'person' records, you have to design the
exact DB representation, but later on you might want to modify that
representation. Ideally, such changes shouldn't impact _all_ your
code.
specifically: my Person model has a ManyToManyField to 'self' called
'friends', where the intermediate table ('Friendship' model) has a
'state' field. These are implementation details, so i added some
methods to get the list of friends, list of unanswered requests sent,
received, and rejections sent and received:
def get_friends(self):
return self.friends.filter(as_B__state=Friendship.ACCEPTED)
def get_sent_requests_unanswered(self):
return self.friends.filter(as_B__state=Friendship.REQUESTED)
def get_rcvd_requests_unanswered(self):
return self.receivedRequests.filter(as_A__state=Friendship.REQUESTED)
def get_sent_requests_rejected(self):
return self.friends.filter(as_B__state=Friendship.REJECTED)
def get_rcvd_requests_rejected(self):
return self.receivedRequests.filter(as_A__state=Friendship.REJECTED)
as you can see, these queries are readable enough to be used anywhere;
but if later on i want to replace the single 'friends' link field with
several independent relationships, i don't have to search through all
my code, just the models.py
similarly, there are methods to send a request and to accept or reject
it. Again, the code is simple enough that it could be used directly;
but encapsulating it with the Person model makes it easy to maintain
consistency:
for example, the friendship request method:
def send_friend_request(self, target):
try:
f = Friendship.objects.get(personA=self, personB=target)
return f in (Friendship.REQUESTED, Friendship.ACCEPTED)
except Friendship.DoesNotExist:
Friendship.objects.create(
personA=self, personB=target,
state=Friendship.REQUESTED)
return True
doesn't allow a second request if one is already pending or rejected.
if later on this policy is changed (maybe a rejector could change
mind, or an old request could expire, etc), i know where to do the
changes.
also, this lets the views be _really_ thin. since the interface
presented by the models is really close to the conceptual data objects
presented to the users. After that, adding for example a REST layer
isn't hard; since it only has to use the same high-level methods as
the HTML views. again, consistency is guaranteed by the common
underlying implementation.
in short: an application model is _not_ an OOP view of the database;
it's the implementation of the conceptual data objects as handled by
the application.
--
Javier
--
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+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment