简体   繁体   English

在django-admin中过滤外键时设置额外的限制

[英]Putting in extra restrictions when filtering on foreignkey in django-admin

When getting members based on Unit, I only want to get the ones who are actually in that unit as of now . 在根据Unit获得成员时,我只想获得截至目前实际在该Unit中的成员

I've got a model looking like this: 我有一个看起来像这样的模型:

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)

As you can see, members can have a "fake" membership in unit, that is only history and should not be considered in the searches and listings of the admin. 如您所见,成员可以在单位中具有“伪”成员身份,这只是历史记录,在管理员的搜索和列表中不应考虑这些成员。 They should be shown in the change-page for a single object though. 但是,它们应该在更改页面上显示为单个对象。

The admin looks like this: 管理员看起来像这样:

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

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

So how can I (if at all possible this way), when filtering on unit only get those units whose membership__stop__isnull=True ? 因此,在对单元进行过滤时,如何(如果可能的话)只能获得那些membership__stop__isnull=True单元?

I tried Managers, I can make them work on the model in the admin itself, but not on the filtering/searches. 我尝试了Managers,我可以让他们在admin本身的模型中工作,但不能在过滤/搜索中工作。 There is also a def queryset(self) method that is overrideable, but I can't wrap my head around how to use it to fix my problem. 还有一个def queryset(self)方法可以重写,但是我无法解决如何使用它来解决问题的问题。

Edit , how this is used: A member has only one membership in a unit, however, they could be members from before, but they are ended (with stop). 编辑 ,如何使用:成员在一个单元中只有一个成员,但是,它们可能是以前的成员,但是它们已结束(以stop结束)。 So I only want to filter (and show, in the list view) those members who have an open-ended membership (like, that they are members of that unit now). 因此,我只想过滤(并在列表视图中显示)那些具有开放式成员资格的成员(例如,他们现在是该单元的成员)。

Any ideas? 有任何想法吗?

So you're trying to get the members of a specific Unit, right? 因此,您正在尝试获取特定部门的成员,对吗?

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

This will pull the unit out of the database for you, along with the Memberships and Users that belong to it. 这将为您将单元以及属于该单元的成员资格和用户从数据库中拉出。 You can access and filter the users by: 您可以通过以下方式访问和过滤用户:

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

I hope this helps? 我希望这有帮助? I may be wrong, I haven't tested this. 我可能是错的,我还没有测试过。

One way to certainly achieve this is by adding a denormalized field for has_open_ended_membership . 实现此目标的一种方法是为has_open_ended_membership添加一个非规范化字段。

To do this just add a BooleaneField like that to the Member and make sure it's consistent . 为此,只需将类似的BooleaneField添加到Member并确保其一致

From the django documentation this seems to be the only way without writing specialized code in the ModelAdmin object: 从django文档中,这似乎是在ModelAdmin对象中不编写专门代码的唯一方法:

Set list_filter to activate filters in the right sidebar of the change list page of the admin. 设置list_filter以激活管理员更改列表页面右侧栏中的过滤器。 This should be a list of field names, and each specified field should be either a BooleanField, CharField, DateField, DateTimeField, IntegerField or ForeignKey. 这应该是字段名称的列表,每个指定的字段应该是BooleanField,CharField,DateField,DateTimeField,IntegerField或ForeignKey。

I'm curious about other approaches - list_filter certainly is limited. 我对其他方法很好奇-list_filter当然是有限的。

I fixed it with putting in a denormalized field in member, with a foreign-key to the active unit. 我通过在成员中放入非规范化字段并使用活动单元的外键来修复它。 Then, to make it work and be automatically updated in the admin, I made the specialized save-function for Membership. 然后,为了使其能够正常工作并在管理员中自动更新,我为会员资格设置了专门的保存功能。

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)

And with list_filter = ('unit_denorm',) in the admin, it does exactly what I want. 并在管理员中使用list_filter = ('unit_denorm',) ,它完全可以实现我想要的功能。

Great! 大! Of course, there should only be one field with stop__isnull=True . 当然,应该只有一个字段带有stop__isnull=True I haven't figured out how to make that restriction. 我还没有弄清楚如何进行限制。 but people using the system know they shouldn't do that anyway. 但是使用该系统的人知道他们无论如何都不应这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM