前提・実現したいこと
Djangoを勉強し始めて1か月程度の者です。
djangoでurl ~~/profile/<ユーザー名>のようにあるアカウントのユーザー名をurlに指定してユーザーのプロフィール情報を表示したいのですが、プロフィール情報のリンク先に飛ばず表示しているページが再度表示されてしまうという現象が発生しています。
以前はリンク先には遷移することができ、Field 'id' expected a number but got ~~(~~はユーザー名)というようなエラーが出ていたのですがいろいろいじっているうちにエラーも表示されなくなり上記のような状態になりました。
なので、直接urlを打ち込む、もしくは管理サイトからサイト上で表示をクリックして該当ページに進んだところ、Generic detail view ProfileDetailView must be called with either an object pk or a slug in the URLconf.というエラーが表示されるようになりました。
発生している問題・エラーメッセージ
AttributeError at /profile/ユーザー名/ Generic detail view ProfileDetailView must be called with either an object pk or a slug in the URLconf. Request Method: GET Request URL: http://127.0.0.1:8000/profile/qq/ Django Version: 3.0.3 Exception Type: AttributeError Exception Value: Generic detail view ProfileDetailView must be called with either an object pk or a slug in the URLconf. Python Version: 3.8.3
該当のソースコード
models.py
from django.db import models from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin from django.contrib.auth.validators import UnicodeUsernameValidator from django.utils import timezone from django.utils.translation import gettext_lazy as _ from django.core.mail import send_mail from django.contrib.auth.base_user import BaseUserManager from django.urls import reverse class UserManager(BaseUserManager): ... class User(AbstractBaseUser, PermissionsMixin): """ An abstract base class implementing a fully featured User model with admin-compliant permissions. Username and password are required. Other fields are optional. """ username_validator = UnicodeUsernameValidator() username = models.CharField( _('username'), max_length=150, unique=True, help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'), validators=[username_validator], error_messages={ 'unique': _("A user with that username already exists."), }, ) ...略... from django.db.models.signals import post_save from django.dispatch import receiver class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) CATEGORY_CHOICES = ( ('M', '男性'), ('F', '女性'), ('O', 'その他'), ) gender = models.CharField(max_length=20, blank=True, choices=CATEGORY_CHOICES) birth_date = models.DateField(null=True, blank=True) location = models.CharField(max_length=30, blank=True) favorite_words = models.CharField(max_length=50, blank=True) def __str__(self): return self.user.username def get_absolute_url(self): return reverse('account:profile', kwargs={'username': self.user.username}) @receiver(post_save, sender=User) def create_user_profile(sender, instance, created, **kwargs): if created: Profile.objects.create(user=instance) @receiver(post_save, sender=User) def save_user_profile(sender, instance, **kwargs): instance.profile.save()
views.py
from django.shortcuts import render, redirect from django.contrib.auth.forms import UserCreationForm from .forms import SignUpForm from django.views.generic import ( DetailView, ) from .models import Profile, User from .helpers import get_current_user from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin def signup(request): ... class ProfileDetailView(LoginRequiredMixin, DetailView): model = Profile template_name = 'account/profile.html' slug_field = 'user' slug_url_kwarg = 'user' #error change def get_context_data(self, **kwargs): context = super(ProfileDetailView, self).get_context_data(**kwargs) username = self.kwargs['username'] context['username'] = username context['user'] = get_current_user(self.request) return context
helper.py
from __future__ import absolute_import from django.contrib.sessions.models import Session from .models import User def get_current_user(request=None): if not request: return None session_key = request.session.session_key session = Session.objects.get(session_key=session_key).get_decoded() uid = session.get('_auth_user_id') return User.objects.get(id=uid)
urls.py
from django.urls import path from . import views from django.contrib.auth import views as auth_views app_name = 'account' urlpatterns = [ path('signup/', views.signup, name='signup'), path('login/', auth_views.LoginView.as_view(template_name='account/login.html'), name='login'), path('logout/', auth_views.LogoutView.as_view(template_name='account/logout.html'), name='logout'), path('profile/<slug:username>/', views.ProfileDetailView.as_view(), name='profile'), ]
profile.htmlへのリンク先
<a class="nav-item nav-link" href="{{ user.get_absolute_url }}">{{ user.username }}</a>
試したこと
adminページからプロフィール情報の入力を行いました。
urls.pyでprofile/slug:username/をprofile/slug:user/に変更すると以下エラーに変化しました。
NoReverseMatch at /admin/r/5/9/ Reverse for 'profile' with keyword arguments '{'username': 'name'}' not found. 1 pattern(s) tried: ['profile/(?P<user>[-a-zA-Z0-9_]+)/$'] Request Method: GET Request URL: http://127.0.0.1:8000/admin/r/5/9/ Django Version: 3.0.3 Exception Type: NoReverseMatch Exception Value: Reverse for 'profile' with keyword arguments '{'username': 'name'}' not found. 1 pattern(s) tried: ['profile/(?P<user>[-a-zA-Z0-9_]+)/$']
また、コードを作成する上で以下のサイトを参考にしました。
https://jyouj.hatenablog.com/entry/2018/05/30/221927
OSはWindows10です。よろしくお願いします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/10 14:57