通过 Django 模板标签中的模板标签访问列表中的项目
Accessing items in a list through template tags in Django template tags
Template tag screenshot and possible solution options
第一次,发布到堆栈溢出。格式不理想还请见谅
html
<tbody>
{% for list in todolist %}
<tr>
<td>
<a href="{% url 'todo_detail' list.pk %}">{{ list.name }}</a>
</td>
<td>
{{ list.items.all|length }}
</td>
<td>
{% comment %}need this to be allCompleted[list.id - 1]
#allCompleted.0 works. allCompleted[0] or allCompleted['0'] does not.{% endcomment %}
{% if allCompleted == True %}
{{ allCompleted|getindex:list.id }}
Yes
{% else %}
No
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
Views.py:
class TodoListListView(ListView):
model = TodoList
context_object_name = "todolist"
template_name = "todos/list.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
allCompletedList = []
for list in TodoList.objects.all():
allCompleted = True
for item in list.items.all():
if item.is_completed == False:
allCompleted = False
allCompletedList.append(allCompleted)
context['allCompleted'] = allCompletedList
print ('context: ', context)
return context
Models.py
class TodoList(models.Model):
name = models.CharField(max_length=100, blank=False)
created_on = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class TodoItem(models.Model):
task = models.CharField(max_length=100)
due_date = models.DateTimeField(null=True, blank=True)
is_completed = models.BooleanField(default=False)
list = models.ForeignKey("Todolist", related_name="items", on_delete=models.CASCADE)
def __str__(self):
return self.task
打印上下文时:
我得到 'allCompleted': [False, True]
这是准确的,因为我在住房杂务中有一些项目没有完成,但我进行了三重检查以确保我的所有编码项目都已完成。
从 HTML 屏幕截图可以看出,我需要这样的东西:
{{ allCompleted[list.id - 1] }} to match with the corresponding list in each row.
但 Django 似乎不喜欢那样。我尝试过很多组合,比如 allCompleted['list.id-1']。奇怪的是,allCompleted.0 = False 但 allCompleted[0] 出现解析错误。我还尝试在我制作的文件 (getindex.py)
下的 app/templatetag 文件夹中创建自定义模板标签
from django import template
from todos.models import TodoItem, TodoList
register = template.Library()
def getindex(lst, idx):
return lst[idx]
register.filter(getindex)
对于我的模板标签,我做了 {{ allCompleted|getindex:list.id-1 }}
,它说 getindex 不是一个有效的过滤器所以我可能没有正确注册它?
如果无法访问 allCompleted[list.id - 1]
,我想到了我的 HTMl 截图中解释的其他解决方案。
与其为此目的使用模板标签,不如以模板易于使用的形式提供模板数据。最有效的方法是将任务留给数据库本身,并编写一个查询,将 allCompleted
作为结果中的一列。您可以使用 Exists() subqueries 来执行此操作:
from django.db.models import Exists, OuterRef
class TodoListListView(ListView):
model = TodoList
context_object_name = "todolist"
template_name = "todos/list.html"
def get_queryset(self):
queryset = super().get_queryset()
subquery = TodoItem.objects.filter(
list=OuterRef('pk'),
is_completed=False
)
queryset = queryset.annotate(all_completed=~Exists(subquery))
return queryset
然后在你的模板中你可以简单地写 {{ list.all_completed }}
:
<tbody>
{% for list in todolist %}
<tr>
<td>
<a href="{% url 'todo_detail' list.pk %}">{{ list.name }}</a>
</td>
<td>
{{ list.items.all|length }}
</td>
<td>
{% if list.all_completed == True %}
Yes
{% else %}
No
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
Template tag screenshot and possible solution options
第一次,发布到堆栈溢出。格式不理想还请见谅
html
<tbody>
{% for list in todolist %}
<tr>
<td>
<a href="{% url 'todo_detail' list.pk %}">{{ list.name }}</a>
</td>
<td>
{{ list.items.all|length }}
</td>
<td>
{% comment %}need this to be allCompleted[list.id - 1]
#allCompleted.0 works. allCompleted[0] or allCompleted['0'] does not.{% endcomment %}
{% if allCompleted == True %}
{{ allCompleted|getindex:list.id }}
Yes
{% else %}
No
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
Views.py:
class TodoListListView(ListView):
model = TodoList
context_object_name = "todolist"
template_name = "todos/list.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
allCompletedList = []
for list in TodoList.objects.all():
allCompleted = True
for item in list.items.all():
if item.is_completed == False:
allCompleted = False
allCompletedList.append(allCompleted)
context['allCompleted'] = allCompletedList
print ('context: ', context)
return context
Models.py
class TodoList(models.Model):
name = models.CharField(max_length=100, blank=False)
created_on = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class TodoItem(models.Model):
task = models.CharField(max_length=100)
due_date = models.DateTimeField(null=True, blank=True)
is_completed = models.BooleanField(default=False)
list = models.ForeignKey("Todolist", related_name="items", on_delete=models.CASCADE)
def __str__(self):
return self.task
打印上下文时: 我得到 'allCompleted': [False, True] 这是准确的,因为我在住房杂务中有一些项目没有完成,但我进行了三重检查以确保我的所有编码项目都已完成。
从 HTML 屏幕截图可以看出,我需要这样的东西:
{{ allCompleted[list.id - 1] }} to match with the corresponding list in each row.
但 Django 似乎不喜欢那样。我尝试过很多组合,比如 allCompleted['list.id-1']。奇怪的是,allCompleted.0 = False 但 allCompleted[0] 出现解析错误。我还尝试在我制作的文件 (getindex.py)
下的 app/templatetag 文件夹中创建自定义模板标签from django import template
from todos.models import TodoItem, TodoList
register = template.Library()
def getindex(lst, idx):
return lst[idx]
register.filter(getindex)
对于我的模板标签,我做了 {{ allCompleted|getindex:list.id-1 }}
,它说 getindex 不是一个有效的过滤器所以我可能没有正确注册它?
如果无法访问 allCompleted[list.id - 1]
,我想到了我的 HTMl 截图中解释的其他解决方案。
与其为此目的使用模板标签,不如以模板易于使用的形式提供模板数据。最有效的方法是将任务留给数据库本身,并编写一个查询,将 allCompleted
作为结果中的一列。您可以使用 Exists() subqueries 来执行此操作:
from django.db.models import Exists, OuterRef
class TodoListListView(ListView):
model = TodoList
context_object_name = "todolist"
template_name = "todos/list.html"
def get_queryset(self):
queryset = super().get_queryset()
subquery = TodoItem.objects.filter(
list=OuterRef('pk'),
is_completed=False
)
queryset = queryset.annotate(all_completed=~Exists(subquery))
return queryset
然后在你的模板中你可以简单地写 {{ list.all_completed }}
:
<tbody>
{% for list in todolist %}
<tr>
<td>
<a href="{% url 'todo_detail' list.pk %}">{{ list.name }}</a>
</td>
<td>
{{ list.items.all|length }}
</td>
<td>
{% if list.all_completed == True %}
Yes
{% else %}
No
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>