38

我有一个与另一个对象有 ManyToMany 关系的对象。
在 Django Admin 中,这会导致多选框中的列表很长。

我想过滤 ManyToMany 关系,所以我只获取客户选择的 City 中可用的类别。

这可能吗?我必须为它创建一个小部件吗?如果是这样,我如何将标准 ManyToMany 字段中的行为复制到它,因为我也想要这个filter_horizontal函数。

这些是我的简化模型:

class City(models.Model):
    name = models.CharField(max_length=200)


class Category(models.Model):
    name = models.CharField(max_length=200)
    available_in = models.ManyToManyField(City)
    

class Customer(models.Model):
    name = models.CharField(max_length=200)
    city = models.ForeignKey(City)
    categories = models.ManyToManyField(Category)
4

7 回答 7

38

好的,这是我使用上述类的解决方案。我添加了更多过滤器来正确过滤它,但我想让代码在这里可读。

这正是我一直在寻找的,我在这里找到了我的解决方案:http ://www.slideshare.net/lincolnloop/customizing-the-django-admin#stats-bottom (幻灯片 50)

将以下内容添加到我的 admin.py:

class CustomerForm(forms.ModelForm): 
    def __init__(self, *args, **kwargs):
        super(CustomerForm, self).__init__(*args, **kwargs)
        wtf = Category.objects.filter(pk=self.instance.cat_id);
        w = self.fields['categories'].widget
        choices = []
        for choice in wtf:
            choices.append((choice.id, choice.name))
        w.choices = choices


class CustomerAdmin(admin.ModelAdmin):
    list_per_page = 100
    ordering = ['submit_date',] # didnt have this one in the example, sorry
    search_fields = ['name', 'city',]
    filter_horizontal = ('categories',)
    form = CustomerForm

这会过滤“类别”列表而不删除任何功能!(即:我仍然可以拥有我心爱的 filter_horizo​​ntal :))

ModelForms 非常强大,我有点惊讶文档/书中没有更多地介绍它。

于 2009-08-09T06:05:49.417 回答
17

据我了解,您基本上是想根据某些标准(根据城市的类别)过滤显示的选择。

limit_choices_to你可以通过使用属性来做到这一点models.ManyToManyField。因此,将您的模型定义更改为...

class Customer(models.Model):
    name = models.CharField(max_length=200)
    city = models.ForeignKey(City)
    categories = models.ManyToManyField(Category, limit_choices_to = {'available_in': cityId})

这应该可以工作,因为limit_choices_to, 可用于此目的。

但需要注意的一点是,limit_choices_to在带有自定义中间表的 ManyToManyField 上使用时没有效果。希望这可以帮助。

于 2009-08-04T12:15:26.413 回答
9

另一种方法是formfield_for_manytomany在 Django Admin 中。

class MyModelAdmin(admin.ModelAdmin):
    def formfield_for_manytomany(self, db_field, request, **kwargs):
        if db_field.name == "cars":
            kwargs["queryset"] = Car.objects.filter(owner=request.user)
        return super(MyModelAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)

考虑到“汽车”是多对多领域。

检查此链接以获取更多信息。

于 2016-04-29T21:25:29.843 回答
2

我想这就是你要找的:

http://blog.philippmetzler.com/?p=52

我们使用 django-smart-selects:

http://github.com/digi604/django-smart-selects

菲利普

于 2010-12-10T16:28:35.000 回答
1

由于您以相同的形式选择客户的城市和类别,因此您需要一些 javascript 来动态地将类别选择器缩减为所选城市中可用的类别。

于 2009-08-04T11:36:34.347 回答
0

正如 Ryan 所说,必须有一些 javascript 来根据用户选择动态更改选项。如果保存了城市并重新加载了管理表单,那么发布的解决方案就可以工作,那就是过滤器工作的时候,但是想想用户想要编辑对象然后更改城市下拉列表但类别中的选项不会刷新的情况。

于 2009-12-15T14:59:09.587 回答
-2
Category.objects.filter(available_in=cityobject)

那应该这样做。视图应该具有用户选择的城市,无论是在请求中还是作为该视图函数的参数。

于 2009-08-04T11:01:21.453 回答