I have this really odd error that I can't seem to figure out. I have solved how to fix it but it could be a weird error for others so I am posting anyways.
I have this view function that allows users to invite team members to their team.
@login_required
def invite_team_member(request):
if request.method == "POST":
form = forms.InviteTeamMemberForm(request.POST, team=request.user.profile.team)
if form.is_valid():
user = form.clean_username_or_email()
try:
models.TeamInvite.objects.create(from_user=request.user, to_user=user, team=request.user.profile.team)
message = _("User successfully invited")
except IntegrityError:
message = _("This user has already been invited to your team")
except ValidationError as e:
if e.code == "team_full":
message = _("Your team is full, no further users can be invited")
else:
raise e
return render(
request,
"tracker/tracker_home/invite_team_member.html",
{"invite_team_member_form": form, "message": message},
)
else:
form = forms.InviteTeamMemberForm(team=request.user.profile.team)
return render(request, "tracker/tracker_home/invite_team_member.html", {"invite_team_member_form": form})
Users enter a username or email into a form and the form determines whether it is valid to invite a user with that username or email.
class InviteTeamMemberForm(forms.Form):
username_or_email = forms.CharField(label=_("Username or Email"))
def __init__(self, *args, **kwargs):
self.team: models.Team = kwargs.pop("team")
super().__init__(*args, **kwargs)
def clean_username_or_email(self):
data = self.cleaned_data["username_or_email"]
try:
user = User.objects.get(Q(username__iexact=data) | Q(email__iexact=data))
if user.profile.team == self.team:
raise ValidationError(_("This user cannot be invited since they are already on this team"))
return user
except User.DoesNotExist:
raise ValidationError(_("A user with that username or email doesn't exist."))
Now this is where it gets weird. This all works great with a Sqlite database but with Postgres, it throws this stacktrace.
Internal Server Error: /tracker/data/invite-team-member/
Traceback (most recent call last):
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
psycopg2.ProgrammingError: can't adapt type 'User'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/sentry_sdk/integrations/django/views.py", line 67, in sentry_wrapped_callback
return callback(request, *args, **kwargs)
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/home/raymonddevries/PycharmProjects/tourdeskagit/tracker/views.py", line 72, in invite_team_member
user = form.clean_username_or_email()
File "/home/raymonddevries/PycharmProjects/tourdeskagit/tracker/forms.py", line 32, in clean_username_or_email
user = User.objects.get(Q(username__iexact=data) | Q(email__iexact=data))
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/db/models/query.py", line 431, in get
num = len(clone)
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/db/models/query.py", line 262, in __len__
self._fetch_all()
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/db/models/query.py", line 1324, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/db/models/query.py", line 51, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1175, in execute_sql
cursor.execute(sql, params)
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/db/backends/utils.py", line 98, in execute
return super().execute(sql, params)
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/sentry_sdk/integrations/django/__init__.py", line 500, in execute
return real_execute(self, sql, params)
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/db/backends/utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/raymonddevries/PycharmProjects/virtualenvs/tourdeskagit/lib/python3.9/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: can't adapt type 'User'
I can't figure out if there something going on behind the scenes that I am missing. Stepping the through the code the database retrieves the user fine when executing user = User.objects.get(Q(username__iexact=data) | Q(email__iexact=data)) however when the user is returned to the view using form.clean_username_or_email() an error occurs. Again this only occurs with postgres, not sqlite.
If anyone has insight on what is going on here let me know. I'm guessing form.clean_username_or_email() is not meant to be called directly from a view function. Still odd this throws a database specific error.