Django中基于Category Model实现商品分类筛选、导航栏展示及HTML渲染的技术咨询
Let's fix your code issues and walk through how to implement category-based product filtering, add categories to your navigation bar, and render everything in HTML.
1. Fix the CategoryView in views.py
Your current CategoryView has two critical issues: it doesn't retrieve the slug from the request (so the variable is undefined) and it fetches all categories instead of the specific one the user clicked on. Here's the corrected version:
from django.shortcuts import render, get_object_or_404 from django.views import View from .models import Product, Category class ProductView(View): def get(self, request, *args, **kwargs): products = Product.objects.filter(is_active=True) # Pass all categories to the template for navigation bar rendering categories = Category.objects.all() context = { 'products': products, 'categories': categories } return render(request, 'Product/products.html', context) class ProductDetailView(View): def get(self, request, slug): # Use get_object_or_404 to handle missing products gracefully (avoids crashes) product = get_object_or_404(Product, slug=slug) categories = Category.objects.all() context = { 'product': product, 'categories': categories } return render(request, 'Product/productdetail.html', context) class CategoryView(View): def get(self, request, slug): # Fetch the specific category using its slug current_category = get_object_or_404(Category, slug=slug) # Filter products to only active items in this category products = Product.objects.filter(category=current_category, is_active=True) # Pass all categories for consistent navigation all_categories = Category.objects.all() context = { 'current_category': current_category, 'products': products, 'categories': all_categories } return render(request, 'Product/category.html', context)
2. Configure URLs (urls.py)
Map your views to URLs so users can access category pages and product details. Add these paths to your app's urls.py:
from django.urls import path from . import views urlpatterns = [ path('', views.ProductView.as_view(), name='product-list'), path('product/<slug:slug>/', views.ProductDetailView.as_view(), name='product-detail'), path('category/<slug:slug>/', views.CategoryView.as_view(), name='category-detail'), ]
3. Add Categories to Navigation Bar (Base Template)
Create a base.html template that all other templates extend — this ensures your navigation bar appears on every page:
<!DOCTYPE html> <html> <head> <title>Your E-commerce Store</title> </head> <body> <!-- Navigation Bar --> <nav style="margin-bottom: 20px;"> <a href="{% url 'product-list' %}">Home</a> <span style="margin: 0 10px;">|</span> {% for category in categories %} <a href="{% url 'category-detail' category.slug %}">{{ category.category }}</a> {% if not forloop.last %}<span style="margin: 0 10px;">|</span>{% endif %} {% endfor %} </nav> <!-- Content Block (overridden by child templates) --> {% block content %}{% endblock %} </body> </html>
4. Render Products in Templates
Product List Page (products.html)
Extend the base template and loop through all active products:
{% extends 'base.html' %} {% block content %} <h1>All Products</h1> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 20px;"> {% for product in products %} <div style="border: 1px solid #eee; padding: 15px; border-radius: 8px;"> {% if product.image %} <img src="{{ product.image.url }}" alt="{{ product.title }}" style="width: 100%; height: 200px; object-fit: cover;"> {% endif %} <h3 style="margin-top: 10px;"> <a href="{% url 'product-detail' product.slug %}">{{ product.title }}</a> </h3> <p style="color: #888; margin: 5px 0;">Category: {{ product.category.category }}</p> <p style="font-weight: bold; font-size: 1.1em;">${{ product.selling_price }}</p> </div> {% empty %} <p>No active products available right now.</p> {% endfor %} </div> {% endblock %}
Category Page (category.html)
Render products filtered to the selected category:
{% extends 'base.html' %} {% block content %} <h1>{{ current_category.category }}</h1> <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 20px;"> {% for product in products %} <div style="border: 1px solid #eee; padding: 15px; border-radius: 8px;"> {% if product.image %} <img src="{{ product.image.url }}" alt="{{ product.title }}" style="width: 100%; height: 200px; object-fit: cover;"> {% endif %} <h3 style="margin-top: 10px;"> <a href="{% url 'product-detail' product.slug %}">{{ product.title }}</a> </h3> <p style="font-weight: bold; font-size: 1.1em;">${{ product.selling_price }}</p> </div> {% empty %} <p>No products in this category yet.</p> {% endfor %} </div> {% endblock %}
Product Detail Page (productdetail.html)
Show individual product details with a link back to its category:
{% extends 'base.html' %} {% block content %} <div style="max-width: 800px; margin: 0 auto;"> {% if product.image %} <img src="{{ product.image.url }}" alt="{{ product.title }}" style="width: 100%; max-height: 400px; object-fit: contain;"> {% endif %} <h1>{{ product.title }}</h1> <p style="color: #888;">Category: <a href="{% url 'category-detail' product.category.slug %}">{{ product.category.category }}</a></p> <p style="margin: 10px 0;">Original Price: <del>${{ product.actual_price }}</del></p> <p style="font-weight: bold; font-size: 1.2em;">Selling Price: ${{ product.selling_price }}</p> <div style="margin-top: 20px;"> <h3>Description</h3> <p>{{ product.description }}</p> </div> </div> {% endblock %}
Quick Model Improvement
Your Product model has a confusing field name: product = models.ForeignKey(Seller, ...) — rename this to seller to avoid mixing up the product with its seller. Run a migration after making the change:
# Updated Product model field seller = models.ForeignKey(Seller, on_delete=models.CASCADE)
内容的提问来源于stack exchange,提问作者Dhiman




