Unfortunately, using the `output_field` keyword argument leads to the same 
error:
>>> Conference.objects.annotate(year=ExtractYear('start_date', output_field=
CharField())).filter(website__contains=F('year'))
Traceback (most recent call last):
  File 
"/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/backends/utils.py"
, line 85, in _execute
    return self.cursor.execute(sql, params)
psycopg2.ProgrammingError: function replace(double precision, unknown, 
unknown) does not exist
LINE 1: ...nces"."website"::text LIKE '%' || REPLACE(REPLACE(REPLACE((E...
                                                             ^
HINT:  No function matches the given name and argument types. You might 
need to add explicit type casts.
I wonder if that is part of the same issue?

One way I got it working was using an explicit cast in another annotation:
Conference.objects.annotate(year=ExtractYear('start_date')).annotate(
year_string=Cast('year', CharField())).filter(website__contains=F(
'year_string')).values_list('website', flat=True)
I wonder why this works and the other method don't work? It seems I don't 
really understand the inner workings of casting and filtering between 
Django and Postgres.

Thanks again for your help

On Tuesday, October 9, 2018 at 9:48:22 AM UTC-7, Matthew Pava wrote:
>
> Oh, I see.
>
> Then just use Cast, or the output_field argument .
>
> Conference.objects.annotate(year=ExtractYear('start_date', 
> output_field=CharField())).filter(website__contains=F('year'))
>
>  
>
> *From:* [email protected] <javascript:> [mailto:
> [email protected] <javascript:>] *On Behalf Of *Jakob Karstens
> *Sent:* Tuesday, October 9, 2018 11:43 AM
> *To:* Django users
> *Subject:* Re: psycopg2 Substr SQL generator bug?
>
>  
>
> Thanks Matthew, I'll submit a ticket. 
>
>  
>
> Unfortunately, ExtractYear does not return a string, so it seems like I 
> would still need to explicitly cast the year annotation to a string:
>
> >>> Conference.objects.annotate(year=ExtractYear('start_date')).filter(
> website__contains=F('year'))
> Traceback (most recent call last):
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/backends/utils.py"
> , line 85, in _execute
>     return self.cursor.execute(sql, params)
> psycopg2.ProgrammingError: function replace(double precision, unknown, 
> unknown) does not exist
> LINE 1: ...nces"."website"::text LIKE '%' || REPLACE(REPLACE(REPLACE((E...
>                                                              ^
> HINT:  No function matches the given name and argument types. You might 
> need to add explicit type casts.
>
>  
>
>
> On Tuesday, October 9, 2018 at 6:45:32 AM UTC-7, Matthew Pava wrote:
>
> I would submit a ticket for that issue.
>
> Also, instead of using string functions to  solve your problem, I would 
> use the ExtractYear function.
>
>  
>
> Conference.objects.annotate(year=ExtractYear('start_date'
> )).filter(website__contains=F('year'))
>
>  
>
>  
>
> *From:* [email protected] [mailto:[email protected]] *On 
> Behalf Of *Jakob Karstens
> *Sent:* Tuesday, October 9, 2018 1:47 AM
> *To:* Django users
> *Subject:* psycopg2 Substr SQL generator bug?
>
>  
>
> I have a model named `*Conference`* which has two fields: a DateField `
> *start_date*` and a URLField `*website*`.
>
> I want to filter the rows to return all Conference's *c* such that: 
> *c**.website 
> *contains *c**.start_date__year. *I want to perform this query db-side, 
> not Python side (for memory reasons), and I don't want to use a raw query 
> (for portability reasons). I believe that Django does not support using 
> field lookups on the right side of the equals sign in a filter clause, so 
> my idea was to create an annotation to pull out the year (e.g. '2018') from 
> the `*start_date*` field and check if the `*website*` field contains this 
> annotation.
>
>  
>
> To verify that I could get the year strings correctly as an annotation, I 
> ran this statement:
>
>  
>
> Conference.objects.annotate(year_string=Substr(Cast('start_date', 
> CharField()), 1, length=4)).values_list('year_string', flat=True)
>
>
> It successfully returned:
>
> <PolymorphicQuerySet ['2018', '2018', '2018', '2018', '2018', '2018', 
> '2018', '2018', '2018', '2018', '2018', '2018', '2018', '2018', '2019', 
> '2018', '2018', '2018', '2018', '2018', '...(remaining elements 
> truncated)...']>
>
>
> However, when I tried to filter by website containing year (replacing the `
> *values_list*` call with the `*filter*` call):
>
> Conference.objects.annotate(year_string=Substr(Cast('start_date', 
> CharField()), 1, length=4)).filter(website__contains=F('year_string'))
>
>
> a strange exception occurred, complaining about %1% in the generated SQL 
> (I am using Postgres and the psycopg2 Python library for my Django project)
>
> >>> Conference.objects.annotate(year_string=Substr(Cast('start_date', 
> CharField()), 1, length=4)).filter(website__contains=F('year_string'))
> Traceback (most recent call last):
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/backends/utils.py"
> , line 85, in _execute
>     return self.cursor.execute(sql, params)
> psycopg2.DataError: invalid input syntax for integer: "%1%"
> LINE 1: ...E((SUBSTRING("conferences"."start_date"::varchar, '%1%', 4))...
>                                                              ^
>
>
>
>
> The above exception was the direct cause of the following exception:
>
>
> Traceback (most recent call last):
>   File "<console>", line 1, in <module>
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/polymorphic/query.py"
> , line 456, in __repr__
>     return super(PolymorphicQuerySet, self).__repr__(*args, **kwargs)
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/models/query.py"
> , line 248, in __repr__
>     data = list(self[:REPR_OUTPUT_SIZE + 1])
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/models/query.py"
> , line 272, in __iter__
>     self._fetch_all()
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/models/query.py"
> , line 1179, in _fetch_all
>     self._result_cache = list(self._iterable_class(self))
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/polymorphic/query.py"
> , line 56, in _polymorphic_iterator
>     o = next(base_iter)
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/models/query.py"
> , line 53, in __iter__
>     results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, 
> chunk_size=self.chunk_size)
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/models/sql/compiler.py"
> , line 1064, in execute_sql
>     cursor.execute(sql, params)
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/backends/utils.py"
> , line 100, in execute
>     return super().execute(sql, params)
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/backends/utils.py"
> , line 68, in execute
>     return self._execute_with_wrappers(sql, params, many=False, executor=
> self._execute)
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/backends/utils.py"
> , line 77, in _execute_with_wrappers
>     return executor(sql, params, many, context)
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/backends/utils.py"
> , line 85, in _execute
>     return self.cursor.execute(sql, params)
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/utils.py"
> , line 89, in __exit__
>     raise dj_exc_value.with_traceback(traceback) from exc_value
>   File 
> "/Users/jakobkarstens/confir/virt/lib/python3.6/site-packages/django/db/backends/utils.py"
> , line 85, in _execute
>     return self.cursor.execute(sql, params)
> django.db.utils.DataError: invalid input syntax for integer: "%1%"
> LINE 1: ...E((SUBSTRING("conferences"."start_date"::varchar, '%1%', 4))...
>
>  
>
> What is going on? Why is the generated SQL "%1%" and not "1"? Is this a 
> psycopg2 bug? Am I missing something?
>
> Thanks in advance
>
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at https://groups.google.com/group/django-users.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/django-users/083dae62-9ad7-484c-b10b-d6d1c3c7cb52%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/django-users/083dae62-9ad7-484c-b10b-d6d1c3c7cb52%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected] <javascript:>.
> To post to this group, send email to [email protected] 
> <javascript:>.
> Visit this group at https://groups.google.com/group/django-users.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/django-users/8326add2-3815-425a-bbaa-8bcdf80cd0a5%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/django-users/8326add2-3815-425a-bbaa-8bcdf80cd0a5%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/391faad9-696a-437d-af80-dcd453225dff%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to