ForeignKey Filter and the 1+N Problem

14 views
Skip to first unread message

Rares Vernica

unread,
Mar 25, 2020, 7:47:03 PM3/25/20
to django-filter
Hello,

I'm running into a performance issue when the drop down list for a ForeignKey filter is generated. Essentially, a DB query is executed for each record in the ForeignKey table. I'm using django-filter in combination with the Django Rest Framework. I would like to replace this drop down list with a text input field where the ID of the ForeignKey record can be typed.

Here is a brief example:

class Foo(Model):
  name = CharField(...)
  def __str__(self):
    return self.name

class Bar(Model):
  foo = ForeignKey(Foo)
  def __str__(self):
    return self.foo.__str__()

class Taz(Model):
  bar = ForeignKey(Bar)

class TazViewSet(ModelViewSet):
  filterset_fields = {
    'bar': ('exact', ),
    ... # other filters
  }
  ...

When the Django Rest Framework browsable API page for the Taz endpoint is generated, a Field Filter is generated for the bar field. This filter contains a list of all the records in the Bar table. For each such record, a query on the Foo table is issued to fetch the name field. This is also known as the 1 + N problem. The ideal solution for me would be to replace the drop down with an input field where the user would have to manually type the ID of a Bar record to filter with. This way, Django does not have to fetch a list of the Bar records and the corresponding Foo record for each. How can this be accomplished?

I'm ran into a similar problem with the HTML forms that the Django Rest Framework generates on the browsable API pages. I was able to work around it by using something like:

class TazSerializer(ModelSerializer):
  bar = PrimaryKeyRelatedField(
    queryset=Bar.objects,
    style={'base_template': 'index.html'))
  ...

or

class TazSerializer(ModelSerializer):
  bar = PrimaryKeyRelatedField(
    queryset=Bar.objects.select_related('foo'),
    html_cutoff=10)
  ...

Can something like this be worked into the FilterSet?

Thanks!
Rares


Reply all
Reply to author
Forward
0 new messages