ListView (django) 中 get_context_data 的问题
problems with get_context_data in ListView (django)
我需要在模板中显示两个模型:
models.py:
class Dimension(TimeStampedModel):
level = models.ForeignKey('Level', verbose_name=_('Level'), on_delete=models.CASCADE)
name = models.CharField(verbose_name=('Name'), max_length=200)
active = models.BooleanField(verbose_name=_('Active'), default=True)
sort_order = models.PositiveIntegerField(verbose_name=_('sort order'), default=0)
class Meta:
verbose_name = _('Dimension')
verbose_name_plural = _('Dimensions')
def __str__(self):
return self.name
class Subdimension(TimeStampedModel):
dimension = models.ForeignKey('Dimension', verbose_name=_('Dimension'), on_delete=models.CASCADE)
name = models.CharField(verbose_name=('Name'), max_length=200)
active = models.BooleanField(verbose_name=_('Active'), default=True)
sort_order = models.PositiveIntegerField(verbose_name=_('sort order'), default=0)
objects = managers.SubdimensionManager()
class Meta:
verbose_name = _('Subdimension')
verbose_name_plural = _('Subdimensions')
def __str__(self):
return self.name
并为此创建了一个 ListView
views.py
class DimensionListView(generic.ListView):
model = models.Dimension
template_name = 'dimension.html'
context_object_name = 'dimensions'
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
self.user = self.request.user
self.level = self.get_level(pk=kwargs.get('level_pk'))
return super(DimensionListView, self).dispatch(request, *args, **kwargs)
def get_level(self, pk):
level = get_object_or_404(models.Level, pk=pk)
return level
def get_queryset(self):
queryset = super(DimensionListView, self).get_queryset()
return queryset.filter(active = True, level = self.level)
def get_context_data(self, **kwargs):
context = super(DimensionListView, self).get_context_data(**kwargs)
context['subdimensions'] = models.Subdimension.objects.filter(active=True, dimension__level=self.level )
return context
dimension_list_view = DimensionListView.as_view()
我需要创建一个相同的过滤器 'dimension' 以便在模板中仅显示该维度的子维度。
我的模板dimension.html:
{% include 'base.html'%}
{% block content %}
<div class="row">
{% for dimension in dimensions %}
<div class="col">
<div class="card" style="width: 18rem;">
<a class="">{{dimension.name}}</a>
<div class="card-body">
<ul>
{% for subdimension in subdimensions %}
<li>{{subdimension.name}}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
但如果你注意到了,请显示所有卡片中的所有子维度,而不仅仅是这些维度的子维度。
Manager.py 仅 returns 具有过滤器 active=True 和 order_by('sort_order')
的对象
您可以使用低效渲染来实现,但如果您有 100-200 个子维度 - 这应该不是问题。
{% for dimension in dimensions %}
<div class="col">
<div class="card" style="width: 18rem;">
<a class="">{{dimension.name}}</a>
<div class="card-body">
<ul>
{% for subdimension in subdimensions %}
{% if subdimension.dimension == dimension %}
<li>{{subdimension.name}}</li>
{% endif %}
{% endfor %}
</ul>
</div>
</div>
</div>
{% endfor %}
或者,您可以在视图中用相应的子维度注释所有维度。
# views.py
class DimensionListView(generic.ListView):
...
def get_queryset(self):
queryset = super(DimensionListView, self).get_queryset()
# Save db hits with `prefetch_related`
return queryset.filter(active = True, level = self.level).prefetch_related('subdimension_set')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
dims = list(context['dimensions'])
for d in dims:
d.all_subdimensions = list(d.subdimension_set.all())
context['dimensions'] = dims
return context
然后在模板中
{% for dimension in dimensions %}
<div class="col">
<div class="card" style="width: 18rem;">
<a class="">{{dimension.name}}</a>
<div class="card-body">
<ul>
{% for subdimension in dimension.all_dimensions %}
<li>{{subdimension.name}}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endfor %}
(...或切换到 Jinja2
模板呈现以直接在模板中访问 dimension.subdimension_set.all()
)
你也可以看看 LoginRequiredMixin
而不是 method_decorator(login_required)
我需要在模板中显示两个模型:
models.py:
class Dimension(TimeStampedModel):
level = models.ForeignKey('Level', verbose_name=_('Level'), on_delete=models.CASCADE)
name = models.CharField(verbose_name=('Name'), max_length=200)
active = models.BooleanField(verbose_name=_('Active'), default=True)
sort_order = models.PositiveIntegerField(verbose_name=_('sort order'), default=0)
class Meta:
verbose_name = _('Dimension')
verbose_name_plural = _('Dimensions')
def __str__(self):
return self.name
class Subdimension(TimeStampedModel):
dimension = models.ForeignKey('Dimension', verbose_name=_('Dimension'), on_delete=models.CASCADE)
name = models.CharField(verbose_name=('Name'), max_length=200)
active = models.BooleanField(verbose_name=_('Active'), default=True)
sort_order = models.PositiveIntegerField(verbose_name=_('sort order'), default=0)
objects = managers.SubdimensionManager()
class Meta:
verbose_name = _('Subdimension')
verbose_name_plural = _('Subdimensions')
def __str__(self):
return self.name
并为此创建了一个 ListView
views.py
class DimensionListView(generic.ListView):
model = models.Dimension
template_name = 'dimension.html'
context_object_name = 'dimensions'
@method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
self.user = self.request.user
self.level = self.get_level(pk=kwargs.get('level_pk'))
return super(DimensionListView, self).dispatch(request, *args, **kwargs)
def get_level(self, pk):
level = get_object_or_404(models.Level, pk=pk)
return level
def get_queryset(self):
queryset = super(DimensionListView, self).get_queryset()
return queryset.filter(active = True, level = self.level)
def get_context_data(self, **kwargs):
context = super(DimensionListView, self).get_context_data(**kwargs)
context['subdimensions'] = models.Subdimension.objects.filter(active=True, dimension__level=self.level )
return context
dimension_list_view = DimensionListView.as_view()
我需要创建一个相同的过滤器 'dimension' 以便在模板中仅显示该维度的子维度。
我的模板dimension.html:
{% include 'base.html'%}
{% block content %}
<div class="row">
{% for dimension in dimensions %}
<div class="col">
<div class="card" style="width: 18rem;">
<a class="">{{dimension.name}}</a>
<div class="card-body">
<ul>
{% for subdimension in subdimensions %}
<li>{{subdimension.name}}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
但如果你注意到了,请显示所有卡片中的所有子维度,而不仅仅是这些维度的子维度。
Manager.py 仅 returns 具有过滤器 active=True 和 order_by('sort_order')
的对象您可以使用低效渲染来实现,但如果您有 100-200 个子维度 - 这应该不是问题。
{% for dimension in dimensions %}
<div class="col">
<div class="card" style="width: 18rem;">
<a class="">{{dimension.name}}</a>
<div class="card-body">
<ul>
{% for subdimension in subdimensions %}
{% if subdimension.dimension == dimension %}
<li>{{subdimension.name}}</li>
{% endif %}
{% endfor %}
</ul>
</div>
</div>
</div>
{% endfor %}
或者,您可以在视图中用相应的子维度注释所有维度。
# views.py
class DimensionListView(generic.ListView):
...
def get_queryset(self):
queryset = super(DimensionListView, self).get_queryset()
# Save db hits with `prefetch_related`
return queryset.filter(active = True, level = self.level).prefetch_related('subdimension_set')
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
dims = list(context['dimensions'])
for d in dims:
d.all_subdimensions = list(d.subdimension_set.all())
context['dimensions'] = dims
return context
然后在模板中
{% for dimension in dimensions %}
<div class="col">
<div class="card" style="width: 18rem;">
<a class="">{{dimension.name}}</a>
<div class="card-body">
<ul>
{% for subdimension in dimension.all_dimensions %}
<li>{{subdimension.name}}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endfor %}
(...或切换到 Jinja2
模板呈现以直接在模板中访问 dimension.subdimension_set.all()
)
你也可以看看 LoginRequiredMixin
而不是 method_decorator(login_required)