【问题标题】:Filter M2M in template?在模板中过滤 M2M?
【发布时间】:2015-07-13 18:04:53
【问题描述】:

在我的模型中,我有以下 M2M 字段

class FamilyMember(AbstractUser):
    ...
    email_list = models.ManyToManyField('EmailList', verbose_name="Email Lists", blank=True, null=True)
    ...

EmailList 表如下所示:

class EmailList(models.Model):
    name = models.CharField(max_length=50, default='My List')
    description = models.TextField(blank=True)
    is_active = models.BooleanField(verbose_name="Active")
    is_managed_by_user = models.BooleanField(verbose_name="User Managed")

在应用程序中,用户应该只能看到 is_active=True 和 is_managed_by_user=True 的记录。

在管理员方面,管理员应该能够将用户添加到任何/所有这些组,而不管 is_active 和 is_managed_by_user 标志。

发生的情况是管理员将用户分配给所有电子邮件列表记录。然后,用户登录并只能看到列表的子集(is_active=True 和 is_managed_by_user=True)。这是预期的行为。然而,接下来的不是。

用户取消选择电子邮件列表项,然后保存记录。由于 M2M_Save 在调用 save() 之前首先清除了所有 m2m 记录,因此我丢失了管理员分配给该用户的所有记录。

我怎样才能保留这些?我尝试创建多个列表,然后在保存之前合并它们,我尝试将整个列表传递给模板,然后隐藏 is_managed_by_user = False 的列表,我就是无法工作。

这对我来说更加棘手的是,这一切都包含在一个表单集中。

您将如何编写此代码?正确的方法是什么?我是否过滤掉用户不应该在我的视图中看到的记录?如果是这样,我如何在保存用户所做的任何更改之前合并这些丢失的记录?

【问题讨论】:

    标签: django django-forms django-views


    【解决方案1】:

    您可能想尝试在 models.py 中设置模型管理器来处理过滤。然后,您可以像这样在 views.py 中调用过滤器:

    models.py:

    class EmailListQuerySet(models.query.QuerySet):
        def active(self):
            return self.filter(is_active=True)
        def managed_by_user(self):
            return self.filter(is_managed_by_user=True)
    
    class EmailListManager(models.Manager):
        def get_queryset(self):
            return EmailListQuerySet(self.model, using=self._db)
        def get_active(self):
            return self.get_queryset().active()
        def get_all(self):
            return self.get_queryset().active().managed_by_user()
    
    class EmailList(models.Model):
        name = models.CharField(max_length=50, default='My List')
        description = models.TextField(blank=True)
        is_active = models.BooleanField(verbose_name="Active")
        is_managed_by_user = models.BooleanField(verbose_name="User Managed")
    
        objects = EmailListManager()
    

    views.py:

    def view(request):
        email = EmailList.objects.get_all()
        return render(request, 'template.html', {'email': email})
    

    显然,我的示例中包含了出色的数据,非常欢迎您根据需要更改变量/过滤器。但是,我希望以上内容可以让您了解可以尝试的可能性。

    在你看来你可以做email = EmailList.objects.all().is_active().is_managed_by_user(),但是如果你的数据库中有很多对象,加载时间会更长。模型管理器是首选以节省内存。此外,它不依赖于用户所做的事情,因此管理员和用户界面都必须直接与模型对话(保持它们同步)。

    注意:上面的示例直接输入到此答案中,尚未在文本编辑器中验证。如果有一些语法或拼写错误,我深表歉意。

    【讨论】:

    • (根据您的回答编辑我的原始帖子是否合适?)
    • 我添加了一个与您的建议非常相似的经理,它按预期过滤了电子邮件列表。但是,当我进行更改时,它也会删除那些不适合过滤器的记录。它仍然消除了管理员对电子邮件列表选择所做的更改。如何正确发布我所做的和看到的?
    • 对不起,我不太明白。你是什​​么意思它消除了管理员所做的更改?至于删除不适合过滤器的记录,这意味着过滤器正在完成它的工作。您必须根据需要优化过滤器。您可以根据需要组合任意数量的过滤器,但如果可能,请尝试在管理器中而不是视图中进行。
    • 使用您的示例代码(谢谢!)我想要做的是使用 .is_managed_by_user() 查询来过滤用户的选择。这样可行。但是,在管理页面上,管理员将看到所有项目并可以从中进行选择。但是,管理员所做的任何更改都会在用户下次保存其记录时被清除。当用户保存更改时,我如何首先查询数据库以找到管理员所做的选择?以及如何将其从用户页面添加到cleaned_data 以便保存?
    猜你喜欢
    • 2022-01-22
    • 2022-01-20
    • 2011-03-05
    • 2013-01-24
    • 2014-03-31
    • 2018-05-07
    • 1970-01-01
    • 2011-12-20
    • 1970-01-01
    相关资源
    最近更新 更多