django-vote
django-vote copied to clipboard
Issue with template code that worked before updating Django 3->4 (possibly postgresql 13->14)
This is the entire traceback provided by Django:
Environment:
Request Method: GET
Request URL: http://192.168.2.155:8000/quotes/
Django Version: 4.0.8
Python Version: 3.10.8
Installed Applications:
['django.contrib.admin',
'django.contrib.admindocs',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.flatpages',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'django.contrib.sitemaps',
'django.contrib.humanize',
'django.contrib.postgres',
'django.forms',
'crispy_forms',
'bootstrapform',
'pinax.messages',
'pinax.notifications',
'notifications',
'haystack',
'ircdriven',
'django_filters',
'martor',
'formtools',
'debug_toolbar',
'django_gravatar',
'django_extensions',
'django_countries',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.github',
'allauth.socialaccount.providers.google',
'rest_framework',
'rest_framework.authtoken',
'drf_spectacular',
'friendship',
'captcha',
'mptt',
'widget_tweaks',
'machina',
'machina.apps.forum',
'machina.apps.forum_conversation',
'machina.apps.forum_conversation.forum_attachments',
'machina.apps.forum_conversation.forum_polls',
'machina.apps.forum_feeds',
'machina.apps.forum_moderation',
'machina.apps.forum_search',
'machina.apps.forum_tracking',
'machina.apps.forum_member',
'machina.apps.forum_permission',
'django_nyt.apps.DjangoNytConfig',
'sekizai',
'sorl.thumbnail',
'wiki.apps.WikiConfig',
'wiki.plugins.attachments.apps.AttachmentsConfig',
'wiki.plugins.editsection.apps.EditSectionConfig',
'wiki.plugins.globalhistory.apps.GlobalHistoryConfig',
'wiki.plugins.help.apps.HelpConfig',
'wiki.plugins.images.apps.ImagesConfig',
'wiki.plugins.links.apps.LinksConfig',
'wiki.plugins.macros.apps.MacrosConfig',
'wiki.plugins.notifications.apps.NotificationsConfig',
'vote']
Installed Middleware:
['debug_toolbar.middleware.DebugToolbarMiddleware',
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.contrib.sites.middleware.CurrentSiteMiddleware',
'machina.apps.forum_permission.middleware.ForumPermissionMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
'ircdriven.middleware.TimezoneMiddleware']
Template error:
In template /home/daniel/Repos/website/templates/ircdriven/quotes/main.html, error at line 50
operator does not exist: character varying = numeric
LINE 1: ...content_type_id" = 93 AND "vote_vote"."object_id" = 15663665...
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
40 : <div class="card">
41 : <div class="card-body elegant-color p-0">
42 : <pre style="white-space: pre-wrap;" class="p-2 mb-0 white-text">
43 : {{ quote.quote }}</pre>
44 : </div>
45 : <div class="card-footer m-0 p-1 px-2">
46 : <div class="small text-muted d-inline">Submitted by <a class="black-text" href="{% url 'user_profile' quote.submitter.username %}">{{ quote.submitter.username }}</a></div>
47 : <div class="float-right d-inline">
48 : <div class="badge badge-pill badge-dark d-inline">{{ quote.vote_score }}</div>
49 : {% if request.user.is_authenticated %}
50 : {% vote_exists quote request.user 0 as vote_up %}
51 : {% vote_exists quote request.user 1 as vote_down %}
52 : <div class="form-inline d-inline">
53 : <form class="d-inline" action="{% url 'quotes_home' %}" method="post">
54 : {% csrf_token %}
55 : <input type="hidden" name="id" value="{{ quote.id }}" />
56 : <input type="hidden" name="vote" value="up" />
57 : <button class="btn btn-link p-0 m-0" {% if vote_up %}disabled="disabled"{% endif %} type="submit"><i class="fa-sharp fa-solid fa-arrow-alt-up fa-lg green-text"></i></button>
58 : </form>
59 : <form class="d-inline" action="{% url 'quotes_home' %}" method="post">
60 : {% csrf_token %}
Traceback (most recent call last):
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
return self.cursor.execute(sql, params)
The above exception (operator does not exist: character varying = numeric
LINE 1: ...content_type_id" = 93 AND "vote_vote"."object_id" = 15663665...
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
) was the direct cause of the following exception:
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/daniel/Repos/website/ircdriven/views/quote.py", line 51, in quotes_page
return render(request, 'ircdriven/quotes/main.html', context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/shortcuts.py", line 24, in render
content = loader.render_to_string(template_name, context, request, using=using)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/loader.py", line 62, in render_to_string
return template.render(context, request)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/backends/django.py", line 62, in render
return self.template.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 175, in render
return self._render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/test/utils.py", line 111, in instrumented_test_render
return self.nodelist.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 1000, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 1000, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 958, in render_annotated
return self.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/loader_tags.py", line 157, in render
return compiled_parent._render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/test/utils.py", line 111, in instrumented_test_render
return self.nodelist.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 1000, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 1000, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 958, in render_annotated
return self.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/classytags/core.py", line 151, in render
return str(self.render_tag(context, **kwargs))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/sekizai/templatetags/sekizai_tags.py", line 87, in render_tag
rendered_contents = nodelist.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 1000, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 1000, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 958, in render_annotated
return self.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/defaulttags.py", line 322, in render
return nodelist.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 1000, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 1000, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 958, in render_annotated
return self.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/loader_tags.py", line 63, in render
result = block.nodelist.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 1000, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 1000, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 958, in render_annotated
return self.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/defaulttags.py", line 238, in render
nodelist.append(node.render_annotated(context))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 958, in render_annotated
return self.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/defaulttags.py", line 322, in render
return nodelist.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 1000, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 1000, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/base.py", line 958, in render_annotated
return self.render(context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/template/library.py", line 239, in render
output = self.func(*resolved_args, **resolved_kwargs)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/vote/templatetags/vote.py", line 15, in vote_exists
return model.votes.exists(user.pk, action=action)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/vote/utils.py", line 12, in inner
return func(self, *args, **kwargs)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/vote/managers.py", line 145, in exists
).exists()
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/db/models/query.py", line 892, in exists
return self.query.has_results(using=self.db)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/db/models/sql/query.py", line 589, in has_results
return compiler.has_results()
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1329, in has_results
return bool(self.execute_sql(SINGLE))
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1361, in execute_sql
cursor.execute(sql, params)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/db/backends/utils.py", line 103, in execute
return super().execute(sql, params)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/db/backends/utils.py", line 67, in execute
return self._execute_with_wrappers(
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/db/backends/utils.py", line 84, in _execute
with self.db.wrap_database_errors:
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/db/utils.py", line 91, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/daniel/.pyenv/versions/website/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
return self.cursor.execute(sql, params)
Exception Type: ProgrammingError at /quotes/
Exception Value: operator does not exist: character varying = numeric
LINE 1: ...content_type_id" = 93 AND "vote_vote"."object_id" = 15663665...
^
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
The main piece throwing this is:
50 : {% vote_exists quote request.user 0 as vote_up %}
51 : {% vote_exists quote request.user 1 as vote_down %}
It seems the vote_vote.object filed in the database becomes a varchar type which should be an integer.
Did you do any database migration recently? could you double-check the table schema in your database (something like \d vote_vote in the PostgreSQL command line)
I did do some migrations recently
Table "public.vote_vote"
Column | Type | Collation | Nullable | Default
-----------------+--------------------------+-----------+----------+---------------------------------------
id | bigint | | not null | nextval('vote_vote_id_seq'::regclass)
user_id | character varying(36) | | |
object_id | character varying(36) | | |
create_at | timestamp with time zone | | not null |
content_type_id | integer | | not null |
action | smallint | | not null |
Indexes:
"vote_vote_pkey" PRIMARY KEY, btree (id)
"vote_vote_content_type_id_3e7f4036" btree (content_type_id)
"vote_vote_content_type_id_object_id_d4b2a059_idx" btree (content_type_id, object_id)
"vote_vote_user_id_content_type_id__2491cf2e_uniq" UNIQUE CONSTRAINT, btree (user_id, content_type_id, object_id, action)
Check constraints:
"vote_vote_action_check" CHECK (action >= 0)
Foreign-key constraints:
"vote_vote_content_type_id_3e7f4036_fk_django_content_type_id" FOREIGN KEY (content_type_id) REFERENCES django_content_type(id) DEFERRABLE INITIALLY DEFERRED
The object_id is a varchar because my database uses uuid for ids. This works before, it only broke on my dev server while trying to migrate to Django 4, and upgraded to Postgresql 14 from 13.
@y2kbadbug If you use uuid for object_id, then where does this numeric ID come from ? "vote_vote"."object_id" = 15663665.. what does your quote table schema looks like now?
It looks like
ircdriven=# \d ircdriven_quote;
Table "public.ircdriven_quote"
Column | Type | Collation | Nullable | Default
---------------+--------------------------+-----------+----------+---------
id | uuid | | not null |
quote | text | | not null |
timestamp | timestamp with time zone | | not null |
channel_id | uuid | | |
submitter_id | bigint | | not null |
approved | boolean | | not null |
num_vote_down | integer | | not null |
num_vote_up | integer | | not null |
vote_score | integer | | not null |
Indexes:
"ircdriven_quotes_pkey" PRIMARY KEY, btree (id)
"ircdriven_q_id_bab217_idx" btree (id, "timestamp")
"ircdriven_q_quote_4c9c71_idx" btree (quote)
"ircdriven_quote_num_vote_down_b1d0397a" btree (num_vote_down)
"ircdriven_quote_num_vote_up_b43b6601" btree (num_vote_up)
"ircdriven_quote_timestamp_ea265334" btree ("timestamp")
"ircdriven_quote_vote_score_e652383f" btree (vote_score)
"ircdriven_quotes_channel_id_39530223" btree (channel_id)
"ircdriven_quotes_submitter_id_d4507f71" btree (submitter_id)
Check constraints:
"ircdriven_quote_num_vote_down_check" CHECK (num_vote_down >= 0)
"ircdriven_quote_num_vote_up_check" CHECK (num_vote_up >= 0)
Foreign-key constraints:
"ircdriven_quotes_channel_id_39530223_fk_ircdriven_channel_id" FOREIGN KEY (channel_id) REFERENCES ircdriven_channel(id) DEFERRABLE INITIALLY DEFERRED
"ircdriven_quotes_submitter_id_d4507f71_fk_ircdriven_user_id" FOREIGN KEY (submitter_id) REFERENCES ircdriven_user(id) DEFERRABLE INITIALLY DEFERRED
EDIT:
I have no idea where it's getting that number from. I am reimporting my database since this appears to only be happening on my dev server.
So it only seems to be appearing on my dev server so I will close this right now. Prod server cannot reproduce.
So it appears to be an issue with Django 4.x. I finally updated my prod server from Django 3.2.x to 4.0.8, and now I am getting the same error.
@shellfly I will continue to investigate and submit a PR if I can figure it out. If there is anything I can do for you, let me know :)
@shellfly I will continue to investigate and submit a PR if I can figure it out. If there is anything I can do for you, let me know :)
This was me by the way. I didn't realize I was on my work account. I have not found a solution to this though. Not sure if you want me to close this?
This is a quick fix that I did. This was required due to Postgresql:
# Generated by Django 4.1.7 on 2023-04-02 07:11
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('vote', '0005_alter_vote_id'),
]
operations = [
migrations.AlterField(
model_name='vote',
name='object_id',
field=models.CharField(max_length=50),
),
migrations.AlterField(
model_name='vote',
name='user_id',
field=models.CharField(max_length=50),
),
]
I fixed it out by seeing this: https://github.com/django/django-contrib-comments/commit/7bcc661982930fb98c5a56ec71bd05a6ba86885a
@y2kbadbug it seems a valid solution to change the field type to be compatible with the content object, I just checked the Django document which suggests the same solution. do you want to make a MR to for this?
https://docs.djangoproject.com/en/4.1/ref/contrib/contenttypes/
The “object_id” field doesn’t have to be the same type as the primary key fields on the related models, but their primary key values must be coercible to the same type as the “object_id” field by its get_db_prep_value() method.
For example, if you want to allow generic relations to models with either IntegerField or CharField primary key fields, you can use CharField for the “object_id” field on your model since integers can be coerced to strings by get_db_prep_value().
I will submit one tomorrow! So far everything works fine from what I tested Get Outlook for Android
I created a PR #87 to fix this. Better late than never, right?