Reputation: 2193
So I am working on a small Django project, which for the moment doesn't require optimization. But to prepare for the future, I'd like to know a bit more about the three approaches.
For instances, as part of the models, I have User
and UserProfile
, Transaction
.
class User(models.Model):
name = ...
email = ...
class UserProfile(models.Model):
user = models.ForeignKey(User, related_name='profile')
photo = models.URLField(...)
...
class Transaction(models.Model):
giver = models.ForeignKey(User, related_name="transactions_as_giver")
receiver = models.ForeignKey(User, related_name='transactions_as_receiver')
...
I frequently need to do something like "return transactions
that the request.user
is giver
or receiver
", or "return the profile photo of a user". I have several choices, for instance to get a list of pending transactions and photo
s of both parties, I can do it at views.py
level:
1.
#views.py
transactions = Transaction.objects.filter(Q(giver=request.user)|Q(receiver=request.user))
for transaction in transactions:
giver_photo = transactions.giver.profile.all()[0].photo
# or first query UserProfile by
# giver_profile = UserProfile.objects.get(user=transaction.giver),
# then giver_photo = giver_profile.photo
#
# Then same thing for receiver_photo
transaction['giver_photo'] = giver_photo
...
Or I can do it more on template
level:
# some template
<!-- First receive transactions from views.py without photo data -->
{% for t in transactions %}
{{t.giver.profile.all.0.photo}}, ...
{% endfor %}
Or I can move some or even all of the above stuffs into filters.py
# some template
{{ for t in request.user|pending_transactions }}
{{ t.giver|photo }} {{ t.receiver|photo }}
{{ endfor }}
where photo
and pending_transactions
are roughly the same code in original views.py
but moved to a filter.
So I wonder is there a best practice/guide line on how to choose which approach?
From Django documentation, lower level is faster, and therefore 2. 3. should be slower than 1; but how about comparing the 2. and 3.?
In getting a user photo, which of the two should be recommended, transactions.giver.profile.all()[0].photo
OR profile = UserProfile.objects.get(...) --> photo = profile.photo
?
Upvotes: 2
Views: 1737
Reputation: 45575
Move this logic into models and managers. Views and templates must be as short as possible.
class User(models.Model):
...
def transactions(self):
return Transaction.objects.filter(Q(giver=self)|Q(receiver=self))
def photo(self):
return self.profile.all().first().photo
So the template will be:
{% for t in request.user.transactions %}
{{ t.giver.photo }} {{ t.receiver.photo }}
{% endfor %}
My experience says that business logic in model as much easier to test, support and reuse than in the views/templates.
Upvotes: 1