Home > Blockchain >  Django DetailView ValueError: Field 'id' expected a number but got 'Ryan'
Django DetailView ValueError: Field 'id' expected a number but got 'Ryan'

Time:08-05

I created a profile page that uses DetailView, but the profile page just doesn't work on newly created users and is giving me this error message:

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'.

The url

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

The view:

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

and the template:

{% extends 'blog/base.html' %}
{% block title %}{{ view.kwargs.username }}'s Profile{% endblock title %}
{% block content %}
    <div >
        <div >
            <img  src="{{ profile_user.profile.image.url }}">
            <div >
                <h2 >{{ view.kwargs.username }}</h2>
                <p >{{ profile_user.email }}</p>
                <p >{{ profile_user.profile.rank }}</p>
                <p >{{ profile_user.profile.bio }}</p>
            </div>
        </div>
        {% if profile_user == user %}
            <a  href="{% url 'change_profile' %}">Edit Profile</a>
        {% endif %}
    </div>
    ...

I am not sure if it is something related to the User creation/registration, so I also included the registration function

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})

the signals

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()

and the Profile model

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)

I am new to django, I know I've probably provided a lot of useless information, thank you for your help:)

CodePudding user response:

You are using the username to get the Request

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

I'm guessing that teacher is a Profile in your model, in any case, you are filtering by the username and teacher is a ForeginKey that is specting an id to filter. So, what you need to do is remove the username and filter only teacher=user. Please note that if teacher is not a ForeignKey to user you may need to use teacher__user=user as a filter.

CodePudding user response:

In Teacher == user.username you are trying to compare an int and a str.

I'm guessing that you have both models related with a Foreign key in user to a teacher. Try use the id on that relation to match with teacher.

Edit: You may wonder why your "teacher" is int when you (probably) declared a str name for the model, and the answer is that django provides by default autoincremental integer ids to all models and uses that id to create Foreign keys. You could also match the user.id with the teacher Foreign key to the user model, if that's how you structured you relationship.

  • Related