Django DetailView ValueError:字段'id'期望一个数字,但得到了'Ryan'



我创建了一个使用DetailView的配置文件页面,但该配置文件页面对新创建的用户不起作用,并给我以下错误消息:

Internal Server Error: /user/Ryan/
Traceback (most recent call last):
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/db/models/fields/__init__.py", line 1822, in get_prep_value
return int(value)
ValueError: invalid literal for int() with base 10: 'Ryan'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/views/generic/base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/views/generic/base.py", line 101, in dispatch
return handler(request, *args, **kwargs)
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/views/generic/detail.py", line 107, in get
context = self.get_context_data(object=self.object)
File "/Users/raymond/Documents/GitHub/Management/blog/views.py", line 32, in get_context_data
context['requests'] = Request.objects.filter(teacher=user.username, completed=False).order_by('-request_time')
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/db/models/query.py", line 974, in filter
return self._filter_or_exclude(False, args, kwargs)
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/db/models/query.py", line 992, in _filter_or_exclude
clone._filter_or_exclude_inplace(negate, args, kwargs)
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/db/models/query.py", line 999, in _filter_or_exclude_inplace
self._query.add_q(Q(*args, **kwargs))
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1375, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1396, in _add_q
child_clause, needed_inner = self.build_filter(
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1329, in build_filter
condition = self.build_lookup(lookups, col, value)
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/db/models/sql/query.py", line 1180, in build_lookup
lookup = lookup_class(lhs, rhs)
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/db/models/lookups.py", line 22, in __init__
self.rhs = self.get_prep_lookup()
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/db/models/fields/related_lookups.py", line 120, in get_prep_lookup
self.rhs = target_field.get_prep_value(self.rhs)
File "/Users/raymond/opt/anaconda3/envs/python388/lib/python3.9/site-packages/django/db/models/fields/__init__.py", line 1824, in get_prep_value
raise e.__class__(
ValueError: Field 'id' expected a number but got 'Ryan'.

url

urlpatterns = [
path('user/<str:username>/', UserProfileView.as_view(), name='user-profile'),
...
]

视图:

class UserProfileView(DetailView):
model = User
template_name = 'blog/user_profile.html'
def get_object(self):
return get_object_or_404(User, pk=self.request.user.id)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
user = get_object_or_404(User, username=self.kwargs.get('username'))
context['profile_user'] = user
if user.is_superuser:
context['requests'] = Request.objects.all().order_by('-request_time')
elif user.profile.teacher_status:
context['requests'] = Request.objects.filter(teacher=user.username, completed=False).order_by('-request_time')
else:
context['requests'] = Request.objects.filter(student=user, completed=False).order_by('-request_time')
return context

和模板:

{% extends 'blog/base.html' %}
{% block title %}{{ view.kwargs.username }}'s Profile{% endblock title %}
{% block content %}
<div class="content-section">
<div class="media">
<img class="rounded-circle account-img" src="{{ profile_user.profile.image.url }}">
<div class="media-body">
<h2 class="account-heading">{{ view.kwargs.username }}</h2>
<p class="text-secondary">{{ profile_user.email }}</p>
<p class="article-content">{{ profile_user.profile.rank }}</p>
<p class="article-content">{{ profile_user.profile.bio }}</p>
</div>
</div>
{% if profile_user == user %}
<a class="btn btn-outline-secondary ml-2" href="{% url 'change_profile' %}">Edit Profile</a>
{% endif %}
</div>
...

我不确定这是否与用户创建/注册有关,所以我还包含了注册功能

def register(request):
if request.method == 'POST':
f = UserRegisterForm(request.POST)
if f.is_valid():
p = f.save()
p.refresh_from_db()
p.profile.rank = f.cleaned_data.get('rank')
p.save()
username = f.cleaned_data.get('username')
messages.success(request, f'Account created for {username}')
return redirect('login')
else:
f = UserRegisterForm()
return render(request, 'users/register.html', {'form':f})

信号

from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Profile
@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()

和配置文件模型

class Profile(models.Model):
RANKS = [(f'{i}K', f'{i}K') for i in range(1,19)]
for i in range(1, 10):
RANKS.append((f'{i}D', f'{i}D'))

user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
bio = models.CharField(max_length=225, blank=True, default='')
rank = models.CharField(max_length=3, default='18K', choices=RANKS)
teacher_status = models.BooleanField(default=False)
def __str__(self) -> str:
return f"{self.user.username}'s Profile"
def save(self, *args, **kwargs):
super(Profile, self).save(*args, **kwargs)
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
img.thumbnail((300,300))
img.save(self.image.path)

我是django的新手,我知道我可能提供了很多无用的信息,谢谢你的帮助:(

您正在使用username获取请求

context['requests'] = Request.objects.filter(teacher=user.username, completed=False).order_by('-request_time')

我猜老师在你的模型中是一个Profile,在任何情况下,你都是通过username进行过滤的,而teacher是一个ForeginKey,它正在检查id进行过滤。因此,您需要做的是删除username并仅过滤teacher=user。请注意,如果教师不是用户的ForeignKey,您可能需要使用teacher__user=user作为过滤器。

在Teacher=user.username中,您试图比较int和str.

我猜你的两个模型都与老师的用户中的外键有关。尝试使用该关系上的id与老师匹配。

编辑:你可能想知道为什么你的"老师";当您(可能(为模型声明str名称时,它是int,答案是django默认情况下为所有模型提供自动增量整数id,并使用该id创建外键。如果你是这样构建关系的,你也可以将user.id与用户模型的教师外键进行匹配。

最新更新