Фильтры Django - Использование AllValuesFilter (с LinkWidget) на ManyToManyField - PullRequest
1 голос
/ 23 января 2010

Это мой первый вопрос о переполнении стека, поэтому, пожалуйста, дайте мне знать, если я что-то не так делаю.

Я хочу создать фильтр AllValues ​​для поля ManyToMany с помощью замечательного приложения django-filters. По сути, я хочу создать фильтр, который выглядит так же, как в Admin, поэтому я также хочу использовать LinkWidget.

К сожалению, я получаю ошибку (Неверное имя поля: 'operator'), если я пытаюсь сделать это стандартным способом:

# Models
class Organisation(models.Model):
    name = models.CharField()  
    ...  

class Sign(models.Model):  
    name = models.CharField()  
    operator = models.ManyToManyField('Organisation', blank=True)  
    ...  

# Filter
class SignFilter(LinkOrderFilterSet):  
    operator = django_filters.AllValuesFilter(widget=django_filters.widgets.LinkWidget)  

    class Meta:
        model = Sign
        fields = ['operator']

Я справился с этим, создав собственный фильтр с жестко заданными отношениями «многие ко многим»:

# Models
class Organisation(models.Model):
    name = models.CharField()  
    ...  

class Sign(models.Model):  
    name = models.CharField()  
    operator = models.ManyToManyField('Organisation', blank=True)  
    ...  

# Filter
class MyFilter(django_filters.ChoiceFilter):  
    @property  
    def field(self):  
        cd = {}  
        for row in self.model.objects.all():  
            orgs = row.operator.select_related().values()  
        for org in orgs:  
            cd[org['id']] = org['name']    
        choices = zip(cd.keys(), cd.values())  
        list.sort(choices, key=lambda x:(x[1], x[0]))  
        self.extra['choices'] = choices  
        return super(AllValuesFilter, self).field  

class SignFilter(LinkOrderFilterSet):  
    operator = MyFilter(widget=django_filters.widgets.LinkWidget)  

Я новичок в Python и Django. Может ли кто-нибудь придумать более общий / элегантный способ сделать это?

Ответы [ 2 ]

1 голос
/ 02 октября 2014

Вы можете использовать это

class CircleFilter(django_filters.FilterSet):
    l = []
    for c in Organisation.objects.all():
        l.append((c.id, c.name))
    operator = django_filters.ChoiceFilter(
        choices=set(l))

class Meta:
    model = Sign
    fields = ['operator']
0 голосов
/ 13 марта 2010

Почему вы создали подкласс LinkOrderFilterSet?

Возможно, подключить способ использовать это:

import django_filters 

class SignFilter(django_filters.FilterSet):  
    operator = django_filters.AllValuesFilter(widget=django_filters.widgets.LinkWidget)  

    class Meta:
        model = Sign
        fields = ['operator']
...