在 Django Admin 中过滤 ManyToMany 框

发布于 2024-07-30 06:29:29 字数 623 浏览 7 评论 0原文

我有一个对象与另一个对象具有多对多关系。
在 Django 管理中,这会导致多选框中出现一个非常长的列表。

我想过滤多对多关系,以便只获取客户选择的城市中可用的类别。

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

这些是我的简化模型:

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)

I have an object with a ManyToMany relation with another object.
In the Django Admin this results in a very long list in a multiple select box.

I'd like to filter the ManyToMany relation so I only fetch Categories that are available in the City that the Customer has selected.

Is this possible? Will I have to create a widget for it? And if so—how do I copy the behavior from the standard ManyToMany field to it, since I would like the filter_horizontal function as well.

These are my simplified models:

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

拧巴小姐 2024-08-06 06:29:29

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

这正是我一直在寻找的,我在这里找到了解决方案: 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 非常强大,我有点惊讶它没有在文档/书中进行更多介绍。

Ok, this is my solution using above classes.
I added a bunch more filters to filter it correctly, but I wanted to make the code readable here.

This is exactly what I was looking for, and I found my solution here: http://www.slideshare.net/lincolnloop/customizing-the-django-admin#stats-bottom (slide 50)

Add the following to my 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

This filters the "categories" list without removing any functionality! (ie: i can still have my beloved filter_horizontal :))

The ModelForms is very powerful, I'm a bit surprised it's not covered more in the documentation/book.

十秒萌定你 2024-08-06 06:29:29

另一种方法是在 Django Admin 中使用 formfield_for_manytomany

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)

考虑到“汽车”是ManyToMany 领域。

检查此链接更多信息。

Another way is with formfield_for_manytomany in 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)

Considering that "cars" are the ManyToMany field.

Check this link for more info.

地狱即天堂 2024-08-06 06:29:29

据我所知,您基本上想根据某些标准(根据城市的类别)过滤显示的选项。

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

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 上使用时没有任何效果。 希望这可以帮助。

As far as i can understand you, is that you basically want to filter the shown choices according to some criteria (category according to city).

You can do exactly that by using limit_choices_to attribute of models.ManyToManyField. So changing your model definition as...

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

This should work, as limit_choices_to, is available for this very purpose.

But one things to note, limit_choices_to has no effect when used on a ManyToManyField with a custom intermediate table. Hope this helps.

攒一口袋星星 2024-08-06 06:29:29
Category.objects.filter(available_in=cityobject)

应该可以做到这一点。 视图应该具有用户在请求中选择的城市或作为该视图函数的参数。

Category.objects.filter(available_in=cityobject)

That should do it. The view should have the city that the user selected, either in the request or as a parameter to that view function.

酒几许 2024-08-06 06:29:29

我认为这就是您正在寻找的:

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

我们使用django-smart-selects:

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

菲利普

I think this is what you're looking for:

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

we use django-smart-selects:

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

Philipp

枕花眠 2024-08-06 06:29:29

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

Since you're selecting the customer's city and categories in the same form, you would need some javascript to dynamically whittle down the categories selector to just the categories available in the city selected.

朮生 2024-08-06 06:29:29

就像 Ryan 所说,必须有一些 JavaScript 来根据用户的选择动态更改选项。 如果保存城市并重新加载管理表单,即过滤器起作用,则发布的解决方案有效,但请考虑用户想要编辑对象然后更改城市下拉列表但类别中的选项不会刷新的情况。

Like Ryan says, there has to be some javascript to dynamically change the options based on what the user selects. The posted solution works if city is saved and the admin form is reloaded, thats when the filter works, but think of a situation where a user wants to edit an object and then changes the city drop down but the options in category wont refresh.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文