Saturday, June 30, 2012

Re: advantages and disadvantages of Raw sql queries in django

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.

No comments:

Post a Comment