Ross
Ross

Reputation: 2417

Django filter data using field in another model connected via foreign key

I have two models; Sets and Cards. There are many cards in one set. I would like to get it so that I can filter the cards that are returned in my tables but the set code, which for the example below is khc.

I have manage to get it to work to an extent by adding filter(set__code__exact="khc") to the Card.objects but this does not allow the user to change that filtering on the web page.

I cannot seem to add a code filter to the CardFilter

models.py

class Set(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    code = models.CharField(max_length=64)
    ...

class Card(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    ...
    set = models.ForeignKey(Set, on_delete=models.CASCADE, related_name='Card')

views.py

def cards_page(request):
    card_list = Card.objects.filter(set__code__exact="khc").order_by('name')
    card_filter = CardFilter(request.GET, queryset=card_list)
    card_list = card_filter.qs

filters.py

class SetFilter(django_filters.FilterSet):
    code = CharFilter(field_name='code', lookup_expr='iexact', label='', widget=TextInput(attrs={'placeholder': 'Set Code', 'class': 'page-input', 'style': 'width: 150px;'}))
    name = CharFilter(field_name='name', lookup_expr='icontains', label='', widget=TextInput(attrs={'placeholder': 'Name', 'class': 'page-input', 'style': 'width: 150px;'}))
    type = CharFilter(field_name='type', lookup_expr='icontains', label='', widget=TextInput(attrs={'placeholder': 'Type', 'class': 'page-input', 'style': 'width: 150px;'}))

    class Meta:
        model = Set
        fields = ''


class CardFilter(django_filters.FilterSet):
    # doesnt work # code = CharFilter(field_name='set', lookup_expr='iexact', label='', widget=TextInput(attrs={'placeholder': 'Set Code', 'class': 'page-input', 'style': 'width: 150px;'}))
    name = CharFilter(field_name='name', lookup_expr='icontains', label='', widget=TextInput(attrs={'placeholder': 'Name', 'class': 'page-input', 'style': 'width: 150px;'}))
    type = CharFilter(field_name='type_line', lookup_expr='icontains', label='', widget=TextInput(attrs={'placeholder': 'Type', 'class': 'page-input', 'style': 'width: 150px;'}))

    class Meta:
        model = Card
        fields = ''

cards.html

<form method="get" class="" autocomplete="off">
    {{ card_filter.form.code }}
    {{ card_filter.form.name }}
    {{ card_filter.form.type }}
    <button class="page-btn-icon" type="submit">
    ...

screenshot of filters:

enter image description here

Upvotes: 0

Views: 1086

Answers (1)

Ross
Ross

Reputation: 2417

This was really simple when I manage to figure out how to do it.

I added set_id__code to the field_name variable in my filters.py file. set_id is the field that connects two tables together, followed by two underscores (__) and then the field name in the Set model I wanted to filter by.

code = CharFilter(field_name='set_id__code', lookup_expr='iexact', label='', widget=TextInput(attrs={'placeholder': 'Set Code', 'class': 'page-input', 'style': 'width: 150px;'}))

Upvotes: 2

Related Questions