我有一个非常奇怪的错误,我似乎无法弄清楚。我已经解决了如何修复它,但这对其他人来说可能是一个奇怪的错误,所以我还是发布了。
我有这个查看功能,允许用户邀请团队成员加入他们的团队。
@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})
用户在表单中输入用户名或电子邮件,表单将确定邀请使用该用户名或电子邮件的用户是否有效。
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."))
现在这就是奇怪的地方。这对于 Sqlite 数据库来说效果很好,但是对于 Postgres,它会抛出这个堆栈跟踪。
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'
我不知道幕后是否发生了一些我错过的事情。单步执行代码时,数据库在执行
user = User.objects.get(Q(username__iexact=data) | Q(email__iexact=data))
时可以很好地检索用户,但是当用户使用 form.clean_username_or_email()
返回视图时,会发生错误。同样,这只发生在 postgres 上,而不是 sqlite 上。
如果有人了解这里发生的事情,请告诉我。我猜
form.clean_username_or_email()
并不意味着直接从视图函数调用。仍然很奇怪,这会引发数据库特定的错误。
我的解决方案是使用
user = form.cleaned_data["username_or_email"]
而不是 user = form.clean_username_or_email()
。 相关文档。
这非常令人费解,但事实证明,这可能是由于代码中的上游错误,再加上 django 的 EmailFormField 的过度热心清理所致。
我遇到了同样的问题,结果发现我的
email
变量不是电子邮件,而是用户的字符串表示形式 其中包含用户的电子邮件。
以django的PasswordResetForm为例:
unclean_email = 'User 1: ([email protected])'
form = PasswordResetForm(data={"email": unclean_email})
form.is_valid() # Somehow is True!!!
cleaned_email = form.cleaned_data['email'] # This is stripped to [email protected]
User.objects.get(email__iexact=cleaned_email) # Works
User.objects.get(email__iexact=unclean_email) # Raises the error above
我怀疑 SQLite 正在执行 LIKE 而不是 POSTGRES 优化的不区分大小写的匹配,这很可能产生结果并解释为什么 OP 能够将代码与 SQLite 一起使用。