You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django导航栏下拉菜单调用show_profile_page遇NoReverseMatch错误

Django导航栏下拉菜单调用个人资料URL触发NoReverseMatch错误

Reverse for 'show_profile_page' with arguments '('',)' not found. 1 pattern(s) tried: ['subs/(?P[0-9]+)/profile/\Z']

我在导航栏添加「编辑设置/查看个人资料页」下拉选项时遇到上述错误,该功能之前在其他模板中调用正常,放到下拉菜单后就报错,求排查方向。

urls.py(subs应用)

from django.urls import path 
from .views import UserRegisterView, UserEditView, PasswordsChangeView, ShowProfilePageView, EditProfilePageView
from . import views

urlpatterns = [
    path('register/', UserRegisterView.as_view(), name='register'),
    path('edit_profile/', UserEditView.as_view(), name='edit_profile'),
    path('password/', PasswordsChangeView.as_view(template_name='registration/change-password.html')),
    path('password_success', views.password_success, name="password_success"),
    path('<int:pk>/profile/', ShowProfilePageView.as_view(), name="show_profile_page"),
    path('<int:pk>/edit_profile_page/', EditProfilePageView.as_view(), name="edit_profile_page")
]

models.py

from django.db import models
from django.conf import settings
from django.contrib.auth.models import User
from django.urls import reverse
from datetime import datetime, date
from ckeditor.fields import RichTextField

class Post(models.Model):
    title = models.CharField(max_length=255)
    title_tag = models.CharField(max_length=255)
    header_image = models.ImageField(null=True, blank=True, upload_to="images/")
    description = models.CharField(max_length=50)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    body = RichTextField(blank=True, null=True)
    timestamp = models.DateField(auto_now_add=True)
    category = models.CharField(max_length=255, default='News')
    likes = models.ManyToManyField(User, related_name='post_user')

    def total_likes(self):
        return self.likes.count()

    def __str__(self):
        return self.title + ' | ' + str(self.author)

    def get_absolute_url(self):
        return reverse('home')

class Category(models.Model):
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('home')

class Profile(models.Model):
    user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
    bio = models.TextField()
    profile_pic = models.ImageField(null=True, blank=True, upload_to="images/profile")
    site_url = models.CharField(max_length=255, null=True, blank=True)
    facebook_url = models.CharField(max_length=255, null=True, blank=True)
    instagram_url = models.CharField(max_length=255, null=True, blank=True)

    def __str__(self):
        return str(self.user)

views.py(subs应用)

from django.shortcuts import render, get_object_or_404
from django.views import generic
from django.views.generic import DetailView
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, PasswordChangeForm
from django.urls import reverse_lazy
from .forms import SignUpForms, EditProfileForm, PasswordUpdateForm
from django.contrib.auth.views import PasswordChangeView
from nooz2.models import Profile

class UserRegisterView(generic.CreateView):
    form_class = SignUpForms
    template_name = 'registration/register.html'
    success_url = reverse_lazy('login')

class UserEditView(generic.UpdateView):
    form_class = EditProfileForm
    template_name = 'registration/edit_profile.html'
    success_url = reverse_lazy('home')

    def get_object(self):
        return self.request.user

class PasswordsChangeView(PasswordChangeView):
    form_class = PasswordUpdateForm
    success_url = reverse_lazy('password_success')

def password_success(request):
    return render(request, 'registration/password_success.html', {})

class ShowProfilePageView(DetailView):
    model = Profile
    template_name = 'registration/user_profile.html'

    def get_context_data(self, *args, **kwargs):
        context = super(ShowProfilePageView, self).get_context_data(*args, **kwargs)
        page_user = get_object_or_404(Profile, id=self.kwargs['pk'])
        context["page_user"] = page_user
        return context

class EditProfilePageView(generic.UpdateView):
        model = Profile
        template_name = 'registration/edit_profile_page.html'
        fields = ['bio', 'profile_pic', 'site_url', 'facebook_url', 'instagram_url']
        success_url = reverse_lazy('home')

forms.py

from django.contrib.auth.forms import UserCreationForm, UserChangeForm, PasswordChangeForm
from django.contrib.auth.models import User
from django import forms

class SignUpForms(UserCreationForm):
    email = forms.EmailField(widget=forms.EmailInput(attrs={'class': 'form-control'}))
    first_name = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'class': 'form-control'}))
    last_name = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'class': 'form-control'}))

    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2')

    def __init__(self, *args, **kwargs):
        super(SignUpForms, self).__init__(*args, **kwargs)
        self.fields['username'].widget.attrs['class'] = 'form-control'
        self.fields['password1'].widget.attrs['class'] = 'form-control'
        self.fields['password2'].widget.attrs['class'] = 'form-control'

class EditProfileForm(UserChangeForm):
    email = forms.EmailField(widget=forms.EmailInput(attrs={'class': 'form-control'}))
    first_name = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'class': 'form-control'}))
    last_name = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'class': 'form-control'}))
    username = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'class': 'form-control'}))
    last_login = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'class': 'form-control'}))
    is_superuser = forms.CharField(max_length=100, widget=forms.CheckboxInput(attrs={'class': 'form-check'}))
    is_staff = forms.CharField(max_length=100, widget=forms.CheckboxInput(attrs={'class': 'form-check'}))
    is_active = forms.CharField(max_length=100, widget=forms.CheckboxInput(attrs={'class': 'form-check'}))
    date_joined = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'class': 'form-control'}))

    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name', 'email', 'password', 'is_superuser', 'is_staff', 'is_active', 'date_joined')

class PasswordUpdateForm(PasswordChangeForm):
    old_password = forms.CharField(max_length=100, widget=forms.PasswordInput(attrs={'class': 'form-control', 'type':'password'}))
    new_password1 = forms.CharField(max_length=100, widget=forms.PasswordInput(attrs={'class': 'form-control', 'type':'password'}))
    new_password2 = forms.CharField(max_length=100, widget=forms.PasswordInput(attrs={'class': 'form-control', 'type':'password'}))

    class Meta:
        model = User
        fields = ('old_password', 'new_password1', 'new_password2')
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
    <div class="container-fluid">
      <a class="navbar-brand" href="{% url 'home' %}">Nooz</a>
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarNavDropdown">
        <ul class="navbar-nav">
          <!-- Dropdown code for categories -->
          {% if category_menu %}
          <li class="nav-item dropdown">
            <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
              Categories
            </a>
            <ul class="dropdown-menu">
              <!-- generates list of categories -->
              {% for item in category_menu %}
              <li><a class="dropdown-item" href="{% url 'category' item|slugify|title %}">{{ item }}</a></li>
              {% endfor %}
            </ul>
          </li>
          {% endif %}

          {% if user.is_authenticated %}
          <li class="nav-item">
            <a class="nav-link" href="{% url 'new_post' %}">Add Post</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="{% url 'add_category' %}">Add Category</a>
          </li>
          
          <li class="nav-item dropdown">  
            <a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
              Profile
            </a>
            <ul class="dropdown-menu dropdown-menu-dark">
              <li><a class="nav-link dropdown-item" href="{% url 'edit_profile' %}">Settings</a></li>
              <li><a class="nav-link dropdown-item" href="{% url 'show_profile_page' user.profile.id %}">View Profile Page</a></li>
              <li><a class="nav-link dropdown-item" href="{% url 'edit_profile_page' user.profile.id %}">Edit Profile Page</a></li>
              <li><a class="nav-link dropdown-item" href="{% url 'logout' %}">Logout</a></li>
            </ul>
          </li>
          
        {% else %}
          <li class="nav-item">
            <a class="nav-link" href="{% url 'register' %}">Register</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="{% url 'login' %}">Login</a>
          </li>
        {% endif %}
        </ul>
      </div>
    </div>
  </nav>

已尝试操作

  • 检查拼写错误
  • 修改urls.py添加后缀/
  • 移除user.profile.id参数测试

排查与解决建议

核心原因

错误提示arguments '('',)'说明传递给show_profile_page的参数是空字符串,问题出在user.profile.id:你在Profile模型中设置了user = models.OneToOneField(User, null=True, ...),意味着部分用户可能没有关联的Profile实例,此时user.profile会被模板静默处理为None,导致user.profile.id变成空值,无法匹配URL中要求的<int:pk>整数参数。

解决步骤

  1. 自动为新用户创建Profile实例
    在subs应用中新建signals.py,添加信号监听用户创建事件,自动生成对应Profile:

    from django.db.models.signals import post_save
    from django.contrib.auth.models import User
    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()
    

    然后在subs/apps.py的ready()方法中注册信号:

    from django.apps import AppConfig
    
    class SubsConfig(AppConfig):
        default_auto_field = 'django.db.models.BigAutoField'
        name = 'subs'
    
        def ready(self):
            import subs.signals
    

    这样新注册的用户会自动生成Profile,避免user.profile不存在的情况。

  2. 处理已有无Profile的用户
    进入Django shell,为没有Profile的用户批量创建:

    from django.contrib.auth.models import User
    from subs.models import Profile
    
    for user in User.objects.all():
        Profile.objects.get_or_create(user=user)
    
  3. 模板中增加存在性判断(可选)
    为了更健壮,在模板中先判断Profile是否存在再渲染链接:

    <ul class="dropdown-menu dropdown-menu-dark">
      <li><a class="nav-link dropdown-item" href="{% url 'edit_profile' %}">Settings</a></li>
      {% if user.profile %}
      <li><a class="nav-link dropdown-item" href="{% url 'show_profile_page' user.profile.id %}">View Profile Page</a></li>
      <li><a class="nav-link dropdown-item" href="{% url 'edit_profile_page' user.profile.id %}">Edit Profile Page</a></li>
      {% endif %}
      <li><a class="nav-link dropdown-item" href="{% url 'logout' %}">Logout</a></li>
    </ul>
    
  4. 优化URL参数(可选)
    可以把URL中的pk改为用户ID,这样即使Profile不存在也能通过用户ID获取(但需要修改视图逻辑):

    • 修改urls.py:
      path('<int:user_pk>/profile/', ShowProfilePageView.as_view(), name="show_profile_page"),
      
    • 修改视图:
      class ShowProfilePageView(DetailView):
          model = Profile
          template_name = 'registration/user_profile.html'
      
          def get_object(self):
              return get_object_or_404(Profile, user_id=self.kwargs['user_pk'])
      
    • 模板中改为:
      {% url 'show_profile_page' user.id %}
      

内容的提问来源于stack exchange,提问作者mpysys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 02:45:34