在django-admin中过滤外键时加入额外的限制

时间:2009-09-28 02:03:53

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

当获得基于单位的成员时,我只想让那些实际上在那个单位的人

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

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的单位?

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

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

有什么想法吗?

3 个答案:

答案 0 :(得分:0)

所以你想要获得特定单位的成员,对吗?

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

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

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

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

答案 1 :(得分:0)

确保实现这一目标的一种方法是为其添加非规范化字段 has_open_ended_membership

要做到这一点,只需向会员添加BooleaneField,并确保其一致

从django文档中,这似乎是在ModelAdmin对象中不编写专用代码的唯一方法:

  

设置list_filter以激活过滤器   更改列表的右侧边栏   管理员的页面。这应该是一个   字段名称列表,以及每个字段名称   指定字段应为a   BooleanField,CharField,DateField,   DateTimeField,IntegerField或   ForeignKey的。

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

答案 2 :(得分:0)

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

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字段。我还没弄明白如何制定这种限制。但是使用该系统的人知道他们不应该这样做。