Django权限检查基于当前用户的模板

时间:2015-01-16 22:01:10

标签: python django

鉴于一些模型:

class MailingList(models.Model):
    name = models.CharField(max_length=200, unique=True)

class Recipient(models.Model):
    email = models.CharField(max_length=200)
    mailingList = models.ForeignKey(MailingList)

class ListAdministrator(models.Model):
    username = models.CharField(max_length=200)
    mailingList = models.ForeignKey(MailingList)

我希望以干净的MVC方式完成以下操作,而不会产生不必要的代码重复:当前登录的用户如果被列为Recipient之一,则只能从MailingList删除ListAdministrator 1}} s或者是超级用户。

权限检查应该在两个地方进行:

  1. 在删除收件人之前,视图deleteRecipient(request, recipient_id)应检查所需的权限。这部分很简单,所有必需的信息都在request.userlistadministrator_set的{​​{1}}。

  2. 在列出包含所有相应收件人的所有邮件列表的模板中,只有当前用户可以删除的邮件列表旁边应显示“删除收件人”链接。这是我挣扎的地方:

    • 我不能给模型一个方法Recipient.objects.get(pk=recipient_id).mailingList并从传递当前用户的模板中调用该方法,因为Django不允许从模板传递参数。
    • 我无法在没有用户参数的情况下为模型提供方法userMayDelete(self, user),因为模型无法隐式访问当前用户。
    • 传递模板两组邮件列表,用户可以删除收件人的邮件列表和他不能删除的邮件列表,看起来很麻烦。并且它不允许按字母顺序排列显示所有列表。
  3. 什么是干净(最好是简单)的方法来实现这个目标?

1 个答案:

答案 0 :(得分:0)

您可以在将MailingList实例传递给模板之前为其设置其他属性:

def show_lists(request):

    username = request.user.username
    lists_under_control = [la.mailingList for la in
                           ListAdministrator.objects.filter(username=username)]

    mailing_lists = list(MailingList.objects.all())
    for mailing_list in mailing_lists:
        mailing_list.user_may_delete = (mailing_list in lists_under_control)

    return render(request, 'app/mailing_lists.html',
                           {'mailing_lists': mailing_lists})

然后在模板中使用此属性:

<ul>
{% for mailing_list in mailing_lists %}
    <li>{{ mailing_list }}
        <ul>
        {% for recipient in mailing_list.recipient_set.all %}
            <li>{{ recipient.email }}
                {% if mailing_list.user_may_delete %}
                    <a href="{% url 'delete_recipient' recipient.id %}">
                        Delete recipient
                    </a>
                {% endif %}
            </li>
        {% endfor %}
        </ul>
    </li>

{% endfor %}
</ul>

另一个(更糟糕的)选项是创建模板过滤器并使用它:

{% if user|may_delete:mailing_list %}