【问题标题】:Nested List within Bootstrap 4Bootstrap 4中的嵌套列表
【发布时间】:2021-10-16 05:20:39
【问题描述】:

我有一张包含以下信息的表格:

Name    | Address
John    | 6432 Newcastle Way
Rob     | 893 Lake Point St
Rob     | 1900 Harbor Lane
Rob     | 124 Marginal St

我正在尝试创建一个嵌套列表...也就是说,要显示两个总行(一个用于 John,一个用于 Rob)并在该行内,有另一个列表显示每个不同的地址(因此 Rob 在其中有 3 行他的行)。

这个输出没有给我独特的价值,也没有对它们进行分组......有什么想法可以调整这个或我能找到的任何演练吗?

Views.py

from django.http import HttpResponse
from django.views.generic import TemplateView,ListView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy

from .models import Book

class BookList(ListView):
    queryset = Book.objects.all().distinct('name')

HTML 尝试 1

<ul class="list-group">
    {% for book in object_list %}
    <li style="margin-bottom: 25px;">
    <div class="card" style="width: 18rem;">
      <div class="card-body">
        <h5 class="card-title">{{ book.name }}</h5>
        <h6 class="card-subtitle mb-2 text-muted">{{ book.address }}</h6>
        <a href="{% url 'books_cbv:book_edit' book.id %}">Edit</a>
        <a href="{% url 'books_cbv:book_delete' book.id %}">Delete</a>
      </div>
    </div>
    </li>
    {% endfor %}
</ul>

HTML 尝试 2

<table>
{% for book in object_list %}
    <li>{{ book.name }}
      <li>
          {{ book.address }}
      </li>
    </li>
{% endfor %}
</table>

models.py

class Book(models.Model):
    name = models.CharField(max_length=200)
    address = models.CharField(max_length=200, default='none')
    birthdate = models.CharField(max_length=200, default='none')
    deathdate = models.CharField(max_length=200, default='none')
    description = models.CharField(max_length=1000, default='none')

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('books_cbv:book_edit', kwargs={'pk': self.pk}) 

    def make_list(self):
        def append_children(parent, self):
            children = [[x['address']] for x in d if x['name'] == parent[0]]
            if children:
                parent.append(children)
                for child in children:
                    append_children(child, self)

        results = [[x['address']] for x in d if x['name'] == 'top']
        for parent in results:
            append_children(parent, self)

        return results

【问题讨论】:

    标签: python django bootstrap-4


    【解决方案1】:

    看看你的问题,如果我理解正确,你正试图用你的示例数据做一个这样的表格:

    Name    | Address
    -----------------
    John    | 6432 Newcastle Way
    Rob     | 893 Lake Point St, 1900 Harbor Lane, 124 Marginal St
    

    如果这就是您要查找的内容,那么您将需要更改您的标记。

    标记问题

    表格元素不适用于 li 标记,它们具有用于行和条目以及列的显式标记。详情可见here

    这将是正确标记的示例,其中每个数据具有正确的标题和行:

    <table style="width:100%">
      <tr>
        <!-- These are table headings -->
        <th>Name</th>
        <th>Address</th>
      </tr>
    
      <!-- These are each row -->
    {% for book in object_list %}
      <tr>
        <td>{{ book.name }}</td>
        <td>{{ book.address }}</td>
      </tr>
    {% endfor %}
    
    </table>
    

    后端数据

    现在您提到您正在尝试显示与名称关联的所有地址。就我个人而言,我会通过以下两种方式之一来做到这一点:有一个函数迭代你所有的书对象并返回一个字典

    1. 将名称作为键,将地址列表作为值,或者如果您只需要该列表用于这个模板,
    2. 让它成为一个字典,其中书名的键和地址的值作为字符串。

    例如:

    
    def get_addresses_for_name() -> dict:
        result = {}
        # Iterate through book objects and set result[book.name] to a list of addresses or str
        for book in Book.objects.all():
           # Gets existing addresses, and if key does not yet exist, set to book.address
           addresses = result.get(book.name, book.address)
           
           if addresses != book.address: # If other addresses already exist at the key
               result[book.name] = f"{addresses}, {book.address}"
        return result
    
    
    print(result["rob"]) # "893 Lake Point St, 1900 Harbor Lane, 124 Marginal St"
    print(result["john"]) # "6432 Newcastle Way"
    

    可能有一种方法可以用过滤器替换 Book.objects.all() 调用,这样您就可以获取具有特定名称的对象,但我现在没有测试环境来测试正确的语法。如果你想这样做,那么可以在here找到详细信息。

    一旦你有了那个代码,就让它成为你的书对象上的一个方法,你可以这样做:

    <table style="width:100%">
      <tr>
        <!-- These are table headings -->
        <th>Name</th>
        <th>Address</th>
      </tr>
    
      <!-- These are each row -->
    {% for book in object_list %}
      <tr>
        <td>{{ book.name }}</td>
        <td>{{ book.get_addresses_for_name()[book.name]}}</td>
      </tr>
    {% endfor %}
    
    </table>
    

    这是一个有点冗长的解决方案,不是最优化的,但不知道项目中的任何其他设置应该可以工作。

    另外,如果速度太慢,您可能只想预取地址字典,并将其设置为可以重复使用的变量,如下所示:

    <table style="width:100%">
      <tr>
        <!-- These are table headings -->
        <th>Name</th>
        <th>Address</th>
      </tr>
    
      <!-- These are each row -->
    
    {# Gets the dictionary of address values #}
    {% set address_dict = Book.objects.all().first().get_addresses_for_name()[book.name] %}
    {% for book in object_list %}
      <tr>
        <td>{{ book.name }}</td>
        <td>{{ address_dict[book.name]}}</td>
      </tr>
    {% endfor %}
    
    </table>
    

    【讨论】:

    • 所以对于 get_addresses_for_name() 函数,这在我的 models.py 中,对吗?然后迭代只会拿走我的桌子并从中创建一个字典?我尝试将其与另一种解决方案一起采用...在上面发布了我的更新
    • @RCarmody 是的。最简单的方法是使其成为类上的方法或 django 过滤器(如果您从未使用过它们,则会更加复杂)。 Django 有一个用于迭代所有模型的内置函数 &lt;class&gt;.objects.all()
    • @RCarmody 再次检查答案以获得更充实的 get_addresses_for_name() 版本,并查看最后一个示例以了解更复杂但更快的实现方式。
    猜你喜欢
    • 1970-01-01
    • 2020-12-07
    • 2020-02-03
    • 2021-06-03
    • 2019-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    相关资源
    最近更新 更多