Это мой первый вопрос о переполнении стека, поэтому, пожалуйста, дайте мне знать, если я что-то не так делаю.
Я хочу создать фильтр 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. Может ли кто-нибудь придумать более общий / элегантный способ сделать это?