Django出现NoReverseMatch错误:如何为模型生成详情页URL?
解决Django产品详情页URL生成的NoReverseMatch错误
错误信息
NoReverseMatch at /earrings
Reverse for 'product-detail' with arguments '('', '')' not found. 1 pattern(s) tried: ['product/(?P[0-9]+)/(?P[-a-zA-Z0-9_]+)/\Z']
现有配置
模型代码
class Product(models.Model): name = models.CharField(max_length=400) price = models.IntegerField(default=0) description = RichTextField(null=True, blank=True) slug = models.SlugField(unique=True, null=True, blank=True, max_length=400) create_at = models.DateTimeField(null=True, blank=True) id = models.AutoField(primary_key=True) def get_absolute_url(self): return reverse('product-detail', kwargs={'pk': self.pk, 'slug': self.slug}) def __str__(self): return f'{self.name}'
视图代码
class ProductDetailView(DetailView): # this is the product detailView model = Product template_name = 'tehApp/product_detail.html' context_object_name = 'products' def get_context_data(self, *args, **kwargs): context = super(Product, self).get_context_data(*args, **kwargs) context['Bar'] = Bar.objects.first() context['Products'] = Product.objects.all() return context def get_object(self): return get_object_or_404(Product, pk=self.kwargs['pk'])
URL配置
urlpatterns = [ path('product/<int:pk>/<slug:slug>/', ProductDetailView.as_view(), name='product-detail'), ]
模板代码
{% for product in products %} <div class="item" data-name="{{ product.name }}" data-price="{{ product.price }}" data-date="{{ product.create_at|date:"Y-m-d\TH:i:s" }}"> <div class="relative"> <div class="relative thumbnail"> {% with images=product.images.all %} {% if images|length > 0 %} <a href="{% url 'product-detail' product.pk product.slug %}"> <img width="250px" height="250px" class="" src="{{ images.0.image.url }}" alt=""> </a> {% endif %} {% if images|length > 1 %} <img width="100%" height="100%" class="hidden" src="{{ images.1.image.url }}" alt=""> {% endif %} {% endwith %} <a href="{% url 'product-detail' product.pk product.slug %}" class="absolute top-0 w-full h-full bg-transparent"></a> <div class="hidden quickaddtocart">Add to Cart</div> </div> <p class="caption"><a href="{% url 'product-detail' product.pk product.slug %}">{{ product.name }}</a></p> <div class="caption-price">${{ product.price }}</div> </div> </div> {% endfor %}
问题分析与解决方案
1. 修复视图父类调用错误
视图中get_context_data方法的super(Product, self)是错误调用,需替换为当前视图类,否则会导致上下文数据异常:
def get_context_data(self, *args, **kwargs): context = super(ProductDetailView, self).get_context_data(*args, **kwargs) context['Bar'] = Bar.objects.first() context['Products'] = Product.objects.all() return context
2. 确保Product对象slug非空
错误提示传递空参数,说明部分Product的slug字段未赋值。URL配置中<slug:slug>为必填参数,需保证每个产品都有有效slug:
- 方法一:重写模型
save方法自动生成slug:
from django.utils.text import slugify class Product(models.Model): # ... 其他字段 ... def save(self, *args, **kwargs): if not self.slug: self.slug = slugify(self.name) # 处理slug重复情况 counter = 1 while Product.objects.filter(slug=self.slug).exists(): self.slug = f'{slugify(self.name)}-{counter}' counter += 1 super().save(*args, **kwargs)
- 方法二:批量更新现有空slug的产品(在Django Shell执行):
from django.utils.text import slugify from yourapp.models import Product for product in Product.objects.filter(slug__isnull=True): product.slug = slugify(product.name) product.save()
3. 优化URL生成逻辑
模板中可直接调用模型的get_absolute_url方法,减少重复代码并利用模型层逻辑:
<a href="{{ product.get_absolute_url }}"> <img width="250px" height="250px" class="" src="{{ images.0.image.url }}" alt=""> </a>
内容的提问来源于stack exchange,提问作者box
相关产品推荐
相关产品推荐

