使用related_name将Django管理员中的ManyToMany呈现为水平过滤器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用related_name将Django管理员中的ManyToMany呈现为水平过滤器相关的知识,希望对你有一定的参考价值。

我有以下内容:

class User(models.Model)
    blablabla

class Product(models.Model)
    authorized_users = models.ManyToManyField(
        User,
        related_name='shared_products',
    )

我已经将Product的管理员配置为将authorized_users显示为水平过滤器,以便选择可以编辑产品的所有用户。

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

admin.site.register(Product, ProductAdmin)

问题是我想在User的管理员中做同样的事情,这意味着我想为shared_products设置一个水平过滤器,以便选择该用户能够编辑的产品。我尝试了以下哪些显然不起作用:

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

admin.site.register(User, UserAdmin)

我发现的其他答案建议使用In Lines但是我已经看到它们用于编辑另一端的模型实例,这不是我想要做的。

有人知道如何实现这一目标吗?

答案
class UserAdminForm(forms.ModelForm):
  products = forms.ModelMultipleChoiceField(
    queryset=Product.objects.all(), 
    required=False,
    widget=FilteredSelectMultiple(
      verbose_name=_('Products'),
      is_stacked=False
    )
  )

  class Meta:
    model = User

  def __init__(self, *args, **kwargs):
    super(UserAdminForm, self).__init__(*args, **kwargs)

    if self.instance and self.instance.pk:
      self.fields['products'].initial = self.instance.products.all()

  def save(self, commit=True):
    user = super(UserAdminForm, self).save(commit=False)

    if commit:
      user.save()

    if user.pk:
      user.products = self.cleaned_data['products']
      self.save_m2m()

    return user

class UserAdmin(admin.ModelAdmin):
  form = UserAdminForm

以上是关于使用related_name将Django管理员中的ManyToMany呈现为水平过滤器的主要内容,如果未能解决你的问题,请参考以下文章

升级到 Django1.7 后,related_names 抛出错误

Django GenericForeignKey 使用related_name

Django中related_name作用

django 在这种情况下如何使用Q和过滤related_name?

使用继承和ForeignKey时Django syncdb冲突related_name

django中related_name的作用和用法