Django过滤和查询:在views.py,模板或过滤器中执行此操作?

时间:2015-01-14 06:17:13

标签: django django-models django-templates django-template-filters

所以我正在开发一个小型Django项目,目前还不需要优化。但为了为未来做好准备,我想更多地了解这三种方法。

例如,作为模型的一部分,我有UserUserProfileTransaction

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')
    ...

我经常需要执行类似"返回transactionsrequest.usergiverreceiver"或"返回用户的个人资料照片"。我有几个选择,例如获取待处理交易列表和双方的photo,我可以在views.py级别执行此操作:

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
    ...
  1. 或者我可以在template级别执行更多操作:

    # some template
    <!-- First receive transactions from views.py without photo data -->
    {% for t in transactions %}
    {{t.giver.profile.all.0.photo}}, ...
    {% endfor %}
    
  2. 或者我可以将部分甚至所有上述内容移至filters.py

    # some template
    {{ for t in request.user|pending_transactions }}
    {{ t.giver|photo  }} {{ t.receiver|photo }}
    {{ endfor }}
    
  3. 其中photopending_transactions与原始views.py中的代码大致相同,但已移至过滤器。

    所以我想知道如何选择哪种方法有最佳实践/指导方针?

    从Django文档中,较低级别更快,因此2. 3.应该慢于1;但如何比较2.和3.

    在获取用户照片时,应推荐两者中的哪一张,transactions.giver.profile.all()[0].photoprofile = UserProfile.objects.get(...) --> photo = profile.photo

1 个答案:

答案 0 :(得分:1)

将此逻辑移至模型和管理器中。视图和模板必须尽可能短。

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

所以模板将是:

{% for t in request.user.transactions %}
    {{ t.giver.photo  }} {{ t.receiver.photo }}
{% endfor %}

我的经验表明,模型中的业务逻辑比在视图/模板中更容易测试,支持和重用。