Пользовательский ярлык, например, с django-фильтром

У меня есть модель Observer, которая расширяет пользовательскую модель через OneToOneRelation. Я сделал фильтрацию для контрольного списка модели, который имеет внешний ключ к Observer. Это код models.py:

class Observer(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    rating = models.IntegerField(default=0)
    bird_ratings = models.ManyToManyField('BirdName', through='BirdRatings')

class Checklist(gismodels.Model):
    date = models.DateField()
    time_start = models.TimeField(null=True)
    time_end = models.TimeField(null=True)
    site_name = models.CharField(max_length=200)
    municipality = models.CharField(max_length=200)
    observer = models.ForeignKey(Observer, null=True, default='')
    other_observers = models.CharField(max_length=150, default='')
    note = models.CharField(max_length=2000)
    location_note = models.CharField(max_length=2000, default='')
    position = gismodels.PointField(null=True, srid=4326)
    created = models.DateTimeField(db_index=True, null=True)
    rating = models.IntegerField(default=0)

Затем я сделал класс ChecklistFilter в filters.py:

class ChecklistFilter(django_filters.FilterSet):
    date = DateFromToRangeFilter(label='Datum pozorování', widget=RangeWidget(attrs={'display': 'inline'}))
    #groups = django_filters.ModelMultipleChoiceFilter(queryset=User.objects.filter(), widget=forms.CheckboxSelectMultiple)
    created = DateFilter(label='Datum vložení')
    observer = ModelChoiceFilter(queryset=Observer.objects.filter(), label='Pozorovatel')
    municipality = CharFilter(label='Obec')
    oblast = CharFilter(label='Oblast')
    rating = NumberFilter(label='Hodnocení')

    class Meta:
        model = Checklist
        fields = ['date', 'created', 'observer', 'municipality', 'site_name', 'rating']

Это часть моего кода из шаблона, где я использую поле наблюдателя:

<div class="col-sm-2">
    {{ filter.form.observer.label_tag }}
    {% render_field filter.form.observer class="form-control" %}
</div>

Но проблема в том, что мне не нужно получать объект наблюдателя, но мне нужно last_name из модели User, которая связана с моделью Observer. В формах я просто расширяю ModelChoiceField и переопределяю метод label_from_instance (). Но это не работает здесь. Django-фильтр использует эти классы, но здесь не работает overiding. Я попробовал это:

from .models import Checklist, Observer
from django.contrib.auth.models import User
import django_filters
from django_filters import DateFromToRangeFilter, DateFilter, CharFilter, NumberFilter, ModelChoiceFilter
from django_filters.widgets import RangeWidget
from django import forms


class ChecklistModelChoiceField(forms.ModelChoiceField):
    def label_from_instance(self, obj):
        return obj.user.last_name

class ChecklistFilter(django_filters.FilterSet):
    date = DateFromToRangeFilter(label='Datum pozorování', widget=RangeWidget(attrs={'display': 'inline'}))
    #groups = django_filters.ModelMultipleChoiceFilter(queryset=User.objects.filter(), widget=forms.CheckboxSelectMultiple)
    created = DateFilter(label='Datum vložení')
    observer = ChecklistModelChoiceField(queryset=Observer.objects.filter(), label='Pozorovatel')
    municipality = CharFilter(label='Obec')
    oblast = CharFilter(label='Oblast')
    rating = NumberFilter(label='Hodnocení')

    class Meta:
        model = Checklist
        fields = ['date', 'created', 'observer', 'municipality', 'site_name', 'rating']

Поле выбора тогда на сайте имеет объект-наблюдатель:

РЕДАКТИРОВАТЬ
Да, я попробовал их обоих. Тогда я попробовал:

class ChecklistModelChoiceField(django_filters.ModelChoiceFilter):
    def label_from_instance(self, obj):
        return obj.user.last_name

Нет ошибки, но label_from_instance() не используется Еще наблюдающий объект в избранном.

Я сделал ошибку. ModelChoiceFilter не расширяет ChoiceField. Код в фильтрах выглядит следующим образом. Это просто собственность:

class ModelChoiceFilter(QuerySetRequestMixin, Filter):
    field_class = forms.ModelChoiceField

Так что моя первая идея не сработает. Есть ли другой шанс, как сделать то, что мне нужно?

2 ответа

Решение

Я нашел решение. Я использую ChoiceFilter вместо ModelChoiceFilter, а затем для выбора вызываю метод, в котором я создаю кортеж кортежей с идентификатором наблюдателя и именем из пользовательской модели.

def get_last_names():
    last_names = ()
    observers = Observer.objects.all()
    for obs in observers:
        last_names += (obs.id, obs.user.last_name),
    return last_names

observer = ChoiceFilter(choices=get_last_names, label='Observer')

Я знаю, что этому вопросу больше года, но я столкнулся с той же проблемой и нашел решение, используя ModelChoiceFilter. Так что, если кто-то еще столкнулся с этим:

from .models import Checklist, Observer
from django.contrib.auth.models import User
import django_filters
from django_filters import DateFromToRangeFilter, DateFilter, CharFilter, NumberFilter, ModelChoiceFilter
from django_filters.widgets import RangeWidget
from django import forms

class ChecklistFilter(django_filters.FilterSet):
    date = DateFromToRangeFilter(label='Datum pozorování', widget=RangeWidget(attrs={'display': 'inline'}))
    #groups = django_filters.ModelMultipleChoiceFilter(queryset=User.objects.filter(), widget=forms.CheckboxSelectMultiple)
    created = DateFilter(label='Datum vložení')
    observer = ModelChoiceFilter(queryset=Observer.objects.filter(), label='Pozorovatel')
    municipality = CharFilter(label='Obec')
    oblast = CharFilter(label='Oblast')
    rating = NumberFilter(label='Hodnocení')

    class Meta:
        model = Checklist
        fields = ['date', 'created', 'observer', 'municipality', 'site_name', 'rating']

        def __init__(self, *args, **kwargs):
            super(ChecklistFilter, self).__init__(*args, **kwargs)
            # You need to override the method in the filter's form field
            self.filters['thon_group'].field.label_from_instance = lambda obj: obj.user.last_name
Другие вопросы по тегам