#34015: "Related Field got invalid lookup: startswith" on CharField ForeignKey
-------------------------------------+-------------------------------------
Reporter: Thomas | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 4.1
(models, ORM) |
Severity: Normal | Resolution:
Keywords: ORM lookup | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by Thomas:
Old description:
> Hello,
>
> I have a model, let's call it `Parent`, with a field called `object_id`.
> I have another model, let's call it `Child`, which has a `ForeignKey`
> field called `parent_object[_id]` pointing to `Parent.object_id`. I need
> to do a lookup on `Child` where the FK starts with a certain character
> (it's a normalized value so, in the context of my app, it makes sense...
> also, I didn't design this schema and changing it is not a possibility
> ATM).
>
> The problem is that if I do:
> {{{#!python
> qs = Child.objects.filter(parent_object_id__startswith='c')
> }}}
>
> I get:
> {{{
> django.core.exceptions.FieldError: Related Field got invalid lookup:
> startswith
> }}}
>
> The only way I could make it work is:
> {{{#!python
> qs = Child.objects.filter(parent_object__object_id__startswith='c')
> }}}
>
> but it forces a join between the table and the view and that's a no-no in
> my case (way too costly).
>
> Here's the MCVE (tested on Python 3.9 + Django 4.0.7 and Python 3.10 +
> Django 4.1.1):
> {{{
> #!python
> import django
> django.setup()
> from django.db import models
>
> class Parent(models.Model):
> class Meta:
> app_label = 'test'
>
> object_id = models.CharField('Object ID', max_length=20, unique=True)
>
> class Child(models.Model):
> class Meta:
> app_label = 'test'
>
> parent_object = models.ForeignKey(
> Parent, to_field='object_id', related_name='%(class)s_set',
> on_delete=models.CASCADE
> )
>
> if __name__ == '__main__':
> qs = Child.objects.filter(parent_object_id__startswith='c') # fails
> with `FieldError: Related Field got invalid lookup: startswith`
> qs = Child.objects.filter(parent_object__object_id__startswith='c')
> # works but forces a costly join
> }}}
>
> And the error:
> {{{
> Traceback (most recent call last):
> File "/opt/src/_sandbox/django_bug.py", line 23, in <module>
> qs = Child.objects.filter(media_object_id__startswith='c')
> File "/opt/venv/lib/python3.9/site-
> packages/django/db/models/manager.py", line 85, in manager_method
> return getattr(self.get_queryset(), name)(*args, **kwargs)
> File "/opt/venv/lib/python3.9/site-packages/django/db/models/query.py",
> line 1071, in filter
> return self._filter_or_exclude(False, args, kwargs)
> File "/opt/venv/lib/python3.9/site-packages/django/db/models/query.py",
> line 1089, in _filter_or_exclude
> clone._filter_or_exclude_inplace(negate, args, kwargs)
> File "/opt/venv/lib/python3.9/site-packages/django/db/models/query.py",
> line 1096, in _filter_or_exclude_inplace
> self._query.add_q(Q(*args, **kwargs))
> File "/opt/venv/lib/python3.9/site-
> packages/django/db/models/sql/query.py", line 1502, in add_q
> clause, _ = self._add_q(q_object, self.used_aliases)
> File "/opt/venv/lib/python3.9/site-
> packages/django/db/models/sql/query.py", line 1532, in _add_q
> child_clause, needed_inner = self.build_filter(
> File "/opt/venv/lib/python3.9/site-
> packages/django/db/models/sql/query.py", line 1448, in build_filter
> condition = self.build_lookup(lookups, col, value)
> File "/opt/venv/lib/python3.9/site-
> packages/django/db/models/sql/query.py", line 1262, in build_lookup
> raise FieldError(
> django.core.exceptions.FieldError: Related Field got invalid lookup:
> startswith
> }}}
>
> Thanks for your help,
>
> Regards,
New description:
Hello,
I have a model, let's call it `Parent`, with a field called `object_id`. I
have another model, let's call it `Child`, which has a `ForeignKey` field
called `parent_object[_id]` pointing to `Parent.object_id`. I need to do a
lookup on `Child` where the FK starts with a certain character (it's a
normalized value so, in the context of my app, it makes sense... also, I
didn't design this schema and changing it is not a possibility ATM).
The problem is that if I do:
{{{#!python
qs = Child.objects.filter(parent_object_id__startswith='c')
}}}
I get:
{{{
django.core.exceptions.FieldError: Related Field got invalid lookup:
startswith
}}}
The only way I could make it work is:
{{{#!python
qs = Child.objects.filter(parent_object__object_id__startswith='c')
}}}
but it forces a join between the table and the view and that's a no-no in
my case (way too costly).
Here's the MCVE (tested on Python 3.9 + Django 4.0.7 and Python 3.10 +
Django 4.1.1):
{{{
#!python
import django
django.setup()
from django.db import models
class Parent(models.Model):
class Meta:
app_label = 'test'
object_id = models.CharField('Object ID', max_length=20, unique=True)
class Child(models.Model):
class Meta:
app_label = 'test'
parent_object = models.ForeignKey(
Parent, to_field='object_id', related_name='%(class)s_set',
on_delete=models.CASCADE
)
if __name__ == '__main__':
qs = Child.objects.filter(parent_object_id__startswith='c') # fails
with `FieldError: Related Field got invalid lookup: startswith`
qs = Child.objects.filter(parent_object__object_id__startswith='c') #
works but forces a costly join
}}}
And the error:
{{{
Traceback (most recent call last):
File "/opt/src/orm_test.py", line 26, in <module>
qs = Child.objects.filter(parent_object_id__startswith='c')
File "/opt/src/venv/lib/python3.10/site-
packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/opt/src/venv/lib/python3.10/site-
packages/django/db/models/query.py", line 1420, in filter
return self._filter_or_exclude(False, args, kwargs)
File "/opt/src/venv/lib/python3.10/site-
packages/django/db/models/query.py", line 1438, in _filter_or_exclude
clone._filter_or_exclude_inplace(negate, args, kwargs)
File "/opt/src/venv/lib/python3.10/site-
packages/django/db/models/query.py", line 1445, in
_filter_or_exclude_inplace
self._query.add_q(Q(*args, **kwargs))
File "/opt/src/venv/lib/python3.10/site-
packages/django/db/models/sql/query.py", line 1532, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/opt/src/venv/lib/python3.10/site-
packages/django/db/models/sql/query.py", line 1562, in _add_q
child_clause, needed_inner = self.build_filter(
File "/opt/src/venv/lib/python3.10/site-
packages/django/db/models/sql/query.py", line 1478, in build_filter
condition = self.build_lookup(lookups, col, value)
File "/opt/src/venv/lib/python3.10/site-
packages/django/db/models/sql/query.py", line 1292, in build_lookup
raise FieldError(
django.core.exceptions.FieldError: Related Field got invalid lookup:
startswith
}}}
Thanks for your help,
Regards,
--
--
Ticket URL: <https://code.djangoproject.com/ticket/34015#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/0107018344619052-03cda0fc-4604-46d3-b7c3-4152fa1c364f-000000%40eu-central-1.amazonses.com.