2009-09-28 68 views
1

当根据Unit获得成员时,我只想从中获得那些实际上在中的成员。在django-admin过滤foreignkey时会有额外的限制

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

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

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

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

任何想法?

回答

0

我修正了它,把成员中的非规范化字段放在活动单元的外键中。然后,为了使其工作并在管理员中自动更新,我为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) 

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

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

0

所以你试图获得特定单位的成员,对吧?

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

这将拉动单元从数据库中的你,有属于它的成员和用户一起。您可以通过以下方式访问和过滤用户:

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

我希望这可以帮助吗?我可能是错的,我没有测试过。

+0

是的,Django很棒,因为这非常简单。但是我想在管理员中使用这种方法,有没有办法将该代码放入list_filter中?像: 高清unit_without_old(个体经营,UNIT_ID): 单位= member.unit.filter(单位= UNIT_ID).filter(membership__stop__isnull = TRUE) list_filter =( 'unit_without_old',) – 2009-09-28 11:56:05

0

确实可以实现此目的的一种方法是通过为 has_open_ended_membership添加非规格化字段。

要做到这一点,只需添加一个像这样的BooleaneField成员和确保它是一致的

从Django文档这似乎是没有了的ModelAdmin对象编写专门的代码的唯一途径:

设置list_filter激活过滤器在 管理员的变化列表 页面的右边栏。这应该是 字段名称列表,并且每个 指定的字段应该是 BooleanField,CharField,DateField, DateTimeField,IntegerField或 ForeignKey。

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

+0

啊,我想你误会了什么会员是。用于提供历史信息。所以每个人总是至少有一个开放式成员。但我只想过滤开放式会员资格,而不是封闭式会员(因为他们不再是会员)。 对不起,我应该在文中解释更多。 我也看过非规范化的领域,我认为这可能是解决方案。将最新的设备作为一个普通的外键并保持一致。 – 2009-09-29 10:28:59

+0

好的,让我澄清。你基本上只想用'membership__stop__isnull = True'来查看成员# - 然后你需要一个管理器并覆盖get_query_set。你尝试过吗? – phoku 2009-09-29 11:42:14

+0

是的,我写了一个经理,但我可以用错误的方式来完成。无论如何,我希望在我编辑页面时看到它们,而不是在我过滤时看到它们。我想这可能有点太多问django管理。我正在考虑采用简单的方法,并将非规范化的字段永远作为活动单元的ForeignKey。 – 2009-09-29 21:32:02