Django类视图无法将变量传递至模板的问题求助
相关代码
views.py
from django.shortcuts import render from .models import CombatEngraving, ClassEngraving, AllClass, Archetype from django.views import generic from django.shortcuts import HttpResponse, Http404 def index(request): return render(request, 'index.html') class AllClassListView(generic.ListView): model = AllClass paginate_by = 5 context_object_name = 'class_list' template_name = 'catalog/class_list.html' class AllClassDetailView(generic.DetailView): model = AllClass def all_class_detail_view(request, primary_key): try: the_class = AllClass.objects.get(pk=primary_key) except AllClass.DoesNotExist: raise Http404('Class does not exist') return render(request, 'catalog/allclass_detail.html', context={'class': the_class}) class CombatEngravingListView(generic.ListView): model = CombatEngraving paginate_by = 10 context_object_name = 'combat_engraving_list' template_name = 'catalog/combat-engraving.html' class CombatEngravingDetailView(generic.DetailView): model = CombatEngraving def combat_engraving_detail_view(request, primary_key): try: combat_engraving = CombatEngraving.objects.get(pk=primary_key) except CombatEngraving.DoesNotExist: raise Http404('Combat Engraving does not exist') return render(request, 'catalog/combatengraving_detail.html', context={'combat_engraving': combat_engraving})
class_list.html
{% extends "base_generic.html" %} {% block content %} <h1>Class List</h1> {% if class_list %} <ul> {% for class in class_list %} <li> <a href="{{ class.get_absolute_url }}">{{ class.name }}</a>  |{{class.archetype}}|  {{class.first_class_engraving}}  {{class.second_class_engraving}} </li> {% endfor %} </ul> {% else %} <p>There are no class in Trixion.</p> {% endif %} {% endblock %}
allclass_detail.html
{% extends "base_generic.html" %} {% block content %} <h1>{{ class.name }}</h1> <p><strong>Name:</strong> {{ class.name }}</p> <p><strong>Archetype:</strong> {{ class.archetype }}</p> <p><strong>First Class Engraving:</strong> {{ class.first_class_engraving }}</p> <p><strong>Second Class Engraving:</strong> {{ class.second_class_engraving }}</p> {% endblock %}
models.py
from django.urls import reverse from django.db import models from django.db.models import UniqueConstraint from django.db.models.functions import Lower class Archetype(models.Model): name = models.CharField(max_length=40, unique=True,help_text="Name of this archetype(e.g. Martial Artist)") class Meta: ordering = ['name'] def get_absolute_url(self): return reverse('archetype-detail', args=[str(self.id)]) def __str__(self): return self.name class AllClass(models.Model): name = models.CharField(max_length=40, unique=True,help_text="Name of this class(e.g. Wardancer)") archetype = models.ForeignKey('Archetype', on_delete=models.RESTRICT, null=True) first_class_engraving = models.ForeignKey('ClassEngraving', on_delete=models.RESTRICT, null=True, related_name='first_eng') second_class_engraving = models.ForeignKey('ClassEngraving', on_delete=models.RESTRICT, null=True, related_name='second_eng') def __str__(self): return self.name def get_absolute_url(self): return reverse('class-detail', args=[str(self.id)]) class Meta: ordering = ['name'] constraints = [ UniqueConstraint( Lower('name'), name='genre_name_case_insensitive_unique', violation_error_message="Class already exists (case insensitive match)" ), ] class CombatEngraving(models.Model): name = models.CharField(max_length=40, unique=True) description = models.TextField(max_length=1000, unique=True) class Meta: ordering = ['name'] def __str__(self): return self.name def get_absolute_url(self): return reverse('combat-engraving-detail', args=[str(self.id)]) class ClassEngraving(models.Model): name = models.CharField(max_length=40, unique=True) description = models.TextField(max_length=1000) class Meta: ordering = ['name'] def __str__(self): return self.name def get_absolute_url(self): return reverse('class-engraving-detail', args=[str(self.id)])
解决方法
问题核心是你继承了Django的generic.DetailView类视图,但在类内部定义的自定义方法(如all_class_detail_view)不会被类视图自动调用,导致模板无法获取到数据。以下是两种可行的修正方案:
方案1:使用DetailView自带功能(推荐)
DetailView已经封装了获取单条模型数据、传递上下文到模板的逻辑,只需指定必要参数即可:
修改views.py中的两个详情视图:
class AllClassDetailView(generic.DetailView): model = AllClass context_object_name = 'class' # 指定模板中使用的变量名,默认是小写模型名`allclass` template_name = 'catalog/allclass_detail.html' # 若模板符合<app>/<model>_detail.html命名规则,可省略此行 class CombatEngravingDetailView(generic.DetailView): model = CombatEngraving context_object_name = 'combat_engraving' template_name = 'catalog/combatengraving_detail.html'
方案2:改为函数视图
如果更习惯函数式写法,可移除类视图,改用独立的函数视图,并调整路由配置:
修改views.py
# 移除原类视图,替换为以下函数视图 def all_class_detail_view(request, primary_key): try: the_class = AllClass.objects.get(pk=primary_key) except AllClass.DoesNotExist: raise Http404('Class does not exist') return render(request, 'catalog/allclass_detail.html', context={'class': the_class}) def combat_engraving_detail_view(request, primary_key): try: combat_engraving = CombatEngraving.objects.get(pk=primary_key) except CombatEngraving.DoesNotExist: raise Http404('Combat Engraving does not exist') return render(request, 'catalog/combatengraving_detail.html', context={'combat_engraving': combat_engraving})
修改urls.py
将对应路由改为指向函数视图:
path('class/<int:primary_key>/', views.all_class_detail_view, name='class-detail'), path('combat-engraving/<int:primary_key>/', views.combat_engraving_detail_view, name='combat-engraving-detail'),
补充:类视图自定义逻辑的正确方式
若需在类视图中添加自定义逻辑,应重写get_object()或get_context_data()方法,而非定义新的自定义方法。例如:
class AllClassDetailView(generic.DetailView): model = AllClass context_object_name = 'class' template_name = 'catalog/allclass_detail.html' def get_object(self, queryset=None): # 自定义获取对象的逻辑,比如额外过滤或处理 obj = super().get_object(queryset=queryset) # 可在此对obj进行额外操作 return obj
内容的提问来源于stack exchange,提问作者Trantor
相关产品推荐
相关产品推荐

