如何在 Django Admin 中访问 ManyToManyField 的两个方向?
Posted
技术标签:
【中文标题】如何在 Django Admin 中访问 ManyToManyField 的两个方向?【英文标题】:How to access both directions of ManyToManyField in Django Admin? 【发布时间】:2011-05-18 00:38:18 【问题描述】:Django 管理员filter_horizontal
设置为编辑多对多关系提供了一个不错的小部件。但这是一个需要字段列表的特殊设置,因此它仅在定义 ManyToManyField
的 (admin for the) 模型上可用;如何在 other 模型上获得相同的小部件,向后读取关系?
我的模型看起来像这样(请随意忽略User
/UserProfile
的复杂性;不过这是真正的用例):
class Site(models.Model):
pass
class UserProfile(models.Model):
user = models.OneToOneField(to=User,unique=True)
sites = models.ManyToManyField(Site,blank=True)
我可以在UserProfile
的管理表单上获得一个不错的小部件
filter_horizontal = ('sites',)
但看不到如何在Site
admin 上获得等价物。
我也可以通过在SiteAdmin
中添加一个内联来获得部分方法,定义为:
class SiteAccessInline(admin_module.TabularInline):
model = UserProfile.sites.through
虽然它很迂回且不方便;小部件对于简单地管理多对多关系根本不直观。
最后,有一个技巧 described here 涉及在 Site
上定义另一个 ManyToManyField
并确保它指向同一个数据库表(并跳过一些障碍,因为 Django 并不是真正设计为具有不同的字段描述相同数据的不同模型)。我希望有人能给我看一些更干净的东西。
【问题讨论】:
【参考方案1】:这是一个(或多或少)整洁的解决方案,感谢 http://blog.abiss.gr/mgogoulos/entry/many_to_many_relationships_and 并修复了来自 http://code.djangoproject.com/ticket/5247 的 Django 错误
from django.contrib import admin as admin_module
class SiteForm(ModelForm):
user_profiles = forms.ModelMultipleChoiceField(
label='Users granted access',
queryset=UserProfile.objects.all(),
required=False,
help_text='Admin users (who can access everything) not listed separately',
widget=admin_module.widgets.FilteredSelectMultiple('user profiles', False))
class SiteAdmin(admin_module.ModelAdmin):
fields = ('user_profiles',)
def save_model(self, request, obj, form, change):
# save without m2m field (can't save them until obj has id)
super(SiteAdmin, self).save_model(request, obj, form, change)
# if that worked, deal with m2m field
obj.user_profiles.clear()
for user_profile in form.cleaned_data['user_profiles']:
obj.user_profiles.add(user_profile)
def get_form(self, request, obj=None, **kwargs):
if obj:
self.form.base_fields['user_profiles'].initial = [ o.pk for o in obj.userprofile_set.all() ]
else:
self.form.base_fields['user_profiles'].initial = []
return super(SiteAdmin, self).get_form(request, obj, **kwargs)
这使用与filter_horizontal
设置相同的小部件,但硬编码到表单中。
【讨论】:
有人知道针对 django 1.4 更新的这个想法的更新版本吗?一方面,该错误(在过去两年中)已得到修复,就此而言,我不确定为什么 SiteAdmin 范围应该知道 user_profiles 的含义。事实上,我目前收到错误异常类型:配置不当的异常值:“HospitalAdmin.fields”指的是表单中缺少的字段“user_profiles”。当然,型号名称不同,但结构是一样的。医院=站点。以上是关于如何在 Django Admin 中访问 ManyToManyField 的两个方向?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Django Admin 中访问 ManyToManyField 的两个方向?
Django Admin Cookbook-18如何限制对Django Admin管理部分功能的使用
如何实现 has_many :through 关联两种方式?
Django admin - 如何获取模板标签中的所有注册模型?