【问题标题】:Putting in extra restrictions when filtering on foreignkey in django-admin在 django-admin 中过滤外键时施加额外的限制
【发布时间】:2010-12-01 21:20:33
【问题描述】:

在获取基于 Unit 的成员时,我只想获取截至目前实际在该单元中的成员

我有一个看起来像这样的模型:

class Member(models.Model):
    name = models.CharField(max_length=256)
    unit = models.ManyToManyField(Unit, through='Membership')

class Membership(models.Model):
    member = models.ForeignKey(Member)
    unit = models.ForeignKey(Unit)
    start = models.DateField(default=date.today)
    stop = models.DateField(blank=True, null=True)

class Unit(models.Model):
    name = models.CharField(max_length=256)

如您所见,成员可以在单位中拥有“假”成员资格,这只是历史记录,不应在管理员的搜索和列表中考虑。它们应该显示在单个对象的更改页面中。

管理员是这样的:

class MembershipInline(admin.TabularInline):
    model = Membership
    extra = 1

class MemberAdmin(admin.ModelAdmin):
    list_filter = ('unit',)
    inlines = [MembershipInline,]

那么我怎么能(如果可能的话),在单元过滤时只得到那些membership__stop__isnull=True的单元?

我尝试了管理器,我可以让它们在管理本身的模型上工作,但不能在过滤/搜索上工作。还有一个 def queryset(self) 方法是可覆盖的,但我不知道如何使用它来解决我的问题。

编辑,如何使用:一个成员在一个单元中只有一个成员,但是,他们可能是以前的成员,但他们已经结束(停止)。所以我只想过滤(并在列表视图中显示)那些拥有开放式成员资格的成员(例如,他们现在是该单位的成员)。

有什么想法吗?

【问题讨论】:

    标签: python django filter django-admin many-to-many


    【解决方案1】:

    所以你想获取特定单位的成员,对吧?

    unit = Unit.objects.select_related().get(id=some_id)
    

    这将为您从数据库中提取该单元,以及属于它的成员资格和用户。您可以通过以下方式访问和过滤用户:

    for member in unit.membership__set.filter(stop__isnull=True):
        print member.name
    

    我希望这会有所帮助吗?我可能错了,我没有测试过。

    【讨论】:

    • 是的,Django 很棒,因为它非常简单。但是我想在管理员中使用它,有没有办法可以将该代码放入 list_filter 中?喜欢: def unit_without_old(self, unit_id): unit = member.unit.filter(unit=unit_id).filter(membership__stop__isnull=True) list_filter = ('unit_without_old',)
    【解决方案2】:

    实现这一点的一种方法是为 has_open_ended_membership.

    为此,只需向成员添加一个类似的 BooleaneField 并确保它是一致的

    从 django 文档看来,这似乎是无需在 ModelAdmin 对象中编写专门代码的唯一方法:

    设置 list_filter 以激活过滤器 更改列表的右侧边栏 管理员页面。这应该是一个 字段名称列表,以及每个 指定的字段应该是 布尔字段、字符字段、日期字段、 DateTimeField、IntegerField 或 外键。

    我对其他方法很好奇 - list_filter 肯定是有限的。

    【讨论】:

    • 啊,我想你误解了会员资格是什么。用于提供历史信息。所以每个人总是至少有一个不限成员名额的成员。但我只想过滤开放式会员,而不是封闭式会员(因为他们不再是那里的会员)。对不起,我应该在文中解释更多。我还查看了非规范化字段,我认为这可能是解决方案。将最新的单元作为普通外键并保持一致。
    • 好的,让我澄清一下。您基本上只想看到带有membership__stop__isnull=True 的成员# - 然后您需要一个经理并覆盖get_query_set。你试过了吗?
    • 是的,我写了一个经理,但我可能会以错误的方式完成它。无论如何,我在编辑页面时看到它们,但在过滤时却不想看到它们。我想这对 django-admin 的要求可能有点太多了。我正在考虑采用简单的方法并制作一个非规范化字段,该字段始终是活动单元的 ForeignKey。
    【解决方案3】:

    我通过在成员中放置一个非规范化字段来修复它,并为活动单元添加一个外键。然后,为了让它工作并在管理员中自动更新,我为会员制作了专门的保存功能。

    class Member(models.Model):
      name = models.CharField(max_length=256)
      unit = models.ManyToManyField(Unit, through='Membership')
      unit_denorm = models.ForeignKey(Unit)
    
    class Membership(models.Model):
      member = models.ForeignKey(Member)
      unit = models.ForeignKey(Unit)
      start = models.DateField(default=date.today)
      stop = models.DateField(blank=True, null=True)
    
      def save(self, *args, **kwargs):
        if not self.stop:
          self.member.unit_denorm = self.unit
          self.member.save()
        super(Membership, self).save(*args, **kwargs)
    
    class Unit(models.Model):
      name = models.CharField(max_length=256)
    

    在管理员中使用list_filter = ('unit_denorm',),它完全符合我的要求。

    太棒了!当然,stop__isnull=True 应该只有一个字段。我还没有想出如何做出这个限制。但是使用该系统的人知道他们无论如何都不应该这样做。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-28
      • 1970-01-01
      • 1970-01-01
      • 2011-01-23
      • 1970-01-01
      • 2011-03-14
      • 1970-01-01
      • 2016-08-01
      相关资源
      最近更新 更多