Search code examples
djangodjango-filter

ModelChoiceFilter on django-filter


I'm improving my English, please be patient.

I created a django-filter class to use on my dashboard, but the ModelChoiceField dropdown is showing all 'colocador' objects and not just those that is related to the current user

Colocador is a user profile that is related to another user profile on

class Colocador(models.Model):
    user = models.OneToOneField(
        MyUser, on_delete=models.CASCADE, primary_key=True)
    work_for = models.ForeignKey(Dono, models.CASCADE, blank=True, null=True)

I have a model like this

class Venda(models.Model):
    name = models.CharField(max_length=50, verbose_name='Nome')
    colocador = models.ForeignKey(
        Colocador, on_delete=models.CASCADE, verbose_name="Colocador")
    

And in my filters.py

class VendaFilter(django_filters.FilterSet):
    foo
    colocador = django_filters.ModelChoiceFilter(
        queryset=Colocador.objects.filter(work_for=3))

    class Meta:
        model = Venda
        fields = ['search', 'status', 'colocador']

I hardcoded the work_for to 3 but obviously I don't want a hardcoded value, I already passing the actual user and tried this but doesn't work

class VendaFilter(django_filters.FilterSet):
    search = django_filters.CharFilter(
        method='search_filter', label='Procurar')
    # colocador = django_filters.ModelChoiceFilter(
    #     queryset=Colocador.objects.filter(work_for=3))

    class Meta:
        model = Venda
        fields = ['search', 'status', 'colocador']

    def search_filter(self, queryset, name, value):
        return Venda.objects.filter(
            Q(name__icontains=value) | Q(phone_number__icontains=value) | Q(
                cpf__icontains=value) | Q(rg__icontains=value), colocador__in=self.colocadores)

    def __init__(self, user, *args, **kwargs):
        super(VendaFilter, self).__init__(*args, **kwargs)
        self.colocadores = Colocador.objects.filter(work_for=user)
        self.filters['colocador'] = django_filters.ModelChoiceFilter(
            queryset=Colocador.objects.filter(work_for=user))

The dropdown is showing just the objects that are related to user, but when I submit the filter raise this error

raise FieldError("Cannot resolve keyword '%s' into field. "
django.core.exceptions.FieldError: Cannot resolve keyword 'None' into field. Choices are: acertado, colocador, colocador_id, cpf, expiration_date, id, mercadoria, mercadoria_id, name, phone_number, rg, sale_date, status

So, how to create a ModelChoiceFilter that works correctly and show me just the objects that is related to the current user.


Solution

  • If someone having the same problem here is the solution

    def __init__(self, user, *args, **kwargs):
        super(VendaFilter, self).__init__(*args, **kwargs)
        self.colocadores = Colocador.objects.filter(work_for=user)
        self.filters['colocador'].queryset = Colocador.objects.filter(
            work_for=user)
    

    Simple and beautiful.