Django:在“用户更改”管理页面上显示filter_horizo​​ntal

时间:2013-02-12 08:13:39

标签: django many-to-many

我有以下型号:

class Hospital(models.Model):
    name = models.CharField(max_length=200)
    authorized_users = models.ManyToManyField(User)

在医院管理页面上显示filter_horizo​​ntal小部件以管理ManyToManyField非常简单:

class HospitalAdmin(admin.ModelAdmin):
    filter_horizontal = ('authorized_users', )

admin.site.register(models.Hospital, HospitalAdmin)

然而,我真正喜欢的是在“更改用户”管理页面上显示该小部件,并与用户的其他信息一致。按理说,ManyToManyFields应该可以从两个方向进行修改 - 为一家医院授权多个用户,上述事实上的情况很好。但是,要授权多个医院的一个用户,目前的情况需要访问每个医院的管理页面并选择一个有问题的用户 - 荒谬。

我将添加我使用UserProfile方法来存储有关用户的其他信息(他们是什么类型的用户等)。一个可能的解决方案是使医院的ManyToManyField引用UserProfile而不是User。然后我可以将ManyToManyField(Hospital, through=Hospital.authorized_users.through)添加到UserProfile,从而允许我将filter_horizo​​ntal小部件添加到两端。然而,这是不理想的,因为以后引用连接会很痛苦。想象一下,我希望获得授权给定医院的第一个用户。而不是hosp_name.authorized_users.all()[0],我必须做hosp_name.authorized_users.all()[0].user之类的事情。我甚至不确定如何获得相当于hosp_name.authorized_users.all()的内容来获取完整列表(因为这会返回UserProfiles的列表,而不是User

1 个答案:

答案 0 :(得分:6)

更加雄辩地说,我的目标是使多对多医院 - 用户关系的管理成为双向的。也就是说,在Hospitals的管理页面上,你会得到一个filter_horizo​​ntal用户,在用户管理页面上你会得到一个filter_horizo​​ntal for Hospitals。

我放弃了与User建立关系的想法,而是使用UserProfile。我最终使用了this 7 year old standing Django ticket底部提到的确切代码。

最后,我的代码是

#models.py
class ReverseManyToManyField(models.ManyToManyField):
    pass
try:
    import south
except ImportError:
    pass
else:
    from south.modelsinspector import add_ignored_fields
    add_ignored_fields([".*\.ReverseManyToManyField$",])

class Hospital(models.Model):
    name = models.CharField(max_length=200)
    authorized_users = models.ManyToManyField('UserProfile', blank=True)
    def __unicode__(self):
        return self.name

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    authorized_hospitals = ReverseManyToManyField(Hospital, through=Hospital.authorized_rads.through)

    def __unicode__(self):
        return self.user.username

#admin.py
##### Stuff to register UserProfile fields in the admin site
class UserProfileInline(admin.StackedInline):
    model=models.UserProfile
    can_delete = False
    verbose_name_plural = 'profiles'
    filter_horizontal = ('authorized_hospitals',)

class UserAdmin(UserAdmin):
    inlines = (UserProfileInline, )

class HospitalAdmin(admin.ModelAdmin):
    filter_horizontal = ('authorized_users', )

admin.site.unregister(User)
admin.site.register(User, UserAdmin)
##### END UserProfile Stuff

admin.site.register(models.Hospital, HospitalAdmin)