[英]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.