0

你们是如何在不污染模型的情况下在点击模板之前根据一些业务规则向模型添加额外字段的?

假设我有一个QuerySet包含类型的模型Member

检索这些模型后,我想online动态添加一个属性(不在数据库中)。

我希望能够根据从缓存服务器检索到的值设置此属性,例如:

members_online = get_online_members_ids()
for m in members.all():
    m.online = m.id in members_online

此代码段不起作用,因为 1).all()返回 的副本QuerySet,2)online我的模型中不存在该属性。

之后在我的模板中,我希望能够打印该online属性。

我在 Django 中的第一步,请说明我的问题,谢谢!

编辑:

我的问题有点复杂......我的成员列表实际上是另一个模型的关系:

categories = Category.objects.select_related('members').all()
for cat in categories:
    for m in cat.members.all()
        m.online = m.id in members_online

类别是发送到我的模板/活塞处理程序的内容。

4

2 回答 2

1

原因 2 无关紧要:与所有 Python 对象一样,Django 模型可以在任何时候将任何属性应用于它们。

要绕过原因 1,您只需转换为列表:

all_members = members.objects.all()
for m in all_members:
    m.online = m.id in members_online

现在传递all_members给模板。

另一种方法是members_online单独传递给模板,并在那里单独检查状态:

{% for m in members %}
    {% if m.id in members_online %}online{% endif %}
{% endfor %}

尽管如果您需要多次使用每个成员的在线状态,那么效率会降低(尽管即使那样,您也可以使用with将当前状态保存到临时变量中)。

于 2013-10-24T20:28:50.490 回答
1

我以前从未使用过这种方法,但现在想起来我想出了这样的东西:

class Member(models.Model):
    # your fields

    @property
    def online(self):
        # load the list if it wasn't loaded before and save it as a class attribute.
        # that way `get_online_members_ids()` will be called the first time this
        # property is accessed, and that one time only.
        if not hasattr(Member, 'members_online'):
            Member.members_online = get_online_members_ids()
        return self.pk in Member.members_online  # return online status for the particular member

然后,您将在模板中使用它,就像它是一个普通字段一样:

{% for member in members %}
    {{ member.online }}
{% endfor %}

更新:更多地考虑这个我认为你需要小心,因为一旦加载静态属性可能会比你预期的更长时间,并在后续请求中被重用。这个我自己没有测试过。

于 2013-10-24T20:49:51.943 回答