【问题标题】:Showing listview and detailview in the same template using forloops in Django在 Django 中使用 for 循环在同一模板中显示列表视图和详细视图
【发布时间】:2018-12-25 02:45:47
【问题描述】:

我想在订单历史记录页面(ListView)中添加一些订单详细信息(DetailView),请参见下面的图片示例(我在 photoshop 上制作了图片)。我能够获得灰色部分(要显示的订单列表),但我无法正确显示在此页面中的项目详细信息。如果我单击查看订单详细信息,它会转到详细信息页面,我可以在其中显示所有这些。但我也需要在 ListPage 中做一个小总结。请参见下面的示例。 如何更改视图或模板以实现此目的?在下面查看我的视图和模板

以下是我需要的订单历史记录页面的外观

下面是我的我的models.py

  class Order(models.Model):
        token = models.CharField(max_length=250, blank=True)
        total = models.DecimalField(max_digits=6, decimal_places=2, verbose_name='USD Order Total')
        emailAddress = models.EmailField(max_length=100, blank=True, verbose_name='Email Address')
        created = models.DateTimeField(auto_now_add=True)
        billingName = models.CharField(max_length=350, blank=True)
        billingAddress1 = models.CharField(max_length=350, blank=True)
        billingCity = models.CharField(max_length=100, blank=True)
        billingZipcode = models.CharField(max_length=10, blank=True)
        billingCountry = models.CharField(max_length=50, blank=True)



    class OrderItem(models.Model):
        product = models.CharField(max_length=250)
        quantity = models.IntegerField()
        price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='USD Price')
        order = models.ForeignKey(Order, on_delete=models.CASCADE)
        image = models.ImageField()

下面是我的模板

{% block body %}
    <div>
        <div class="text-center">
            <br/>
            <h1 class="text-center my_title">Order Purchase History</h1>
            <br/>
            {% if order_details %}
                {% for order in order_details %}
                <div class="row order_detail_div" >
                    <div class="col-md-2">
                        <b>Order Number: 1234{{ order.id }}</b><br/>
                        <small><em>Order Date: {{ order.created|date:"M d Y" }}</em></small>
                    </div>
                    <div class="col-md-1"></div>
                    <div class="col-md-3 text-left">
                        <b>Status: Paid</b><br/>
                        <b>Total items in Order: ()</b>
                    </div>
                    <div class="col-md-1"></div>
                    <div class="col-md-3 order_total_text">
                        <b>Order Total: ${{ order.total }}</b>
                    </div>
                    <div class="col-md-2 view_order_details">
                        <b><a href="{% url 'order:order_detail' order.id %}">View Order Details</a></b>
                    </div>
                </div>
                {% for item in order_items %} <!-- This gets the order items from the Order -->
                <div class="row order_item_detail_div">
                    <div class="col-md-2">
                        <img src="{{ item.image }}" >
                    </div>
                     <div class="col-md-2">
                        {{ item.product}}
                    </div>
                    <div class="col-md-2">
                        {{ item.id}}
                    </div>
                   <div class="col-md-2">
                        {{ item.quantity}}
                    </div>
                    <div class="col-md-2">
                        {{ item.price}}
                    </div>
               </div>
               {% endfor %}
            <br/>
            {% endfor %}

            {% else %}
                <p>
                    You do not have any orders yet.<br/><br/>
                    <a href="{% url 'home' %}" class="btn btn-secondary">Add more recipes</a>
                </p>
            {% endif %}
        </div>
    </div>
    <br/>
    <br/>
{% endblock %}

Views.py 第一次尝试 错误: 出于某种原因,终端中的打印语句正确显示,但在浏览器中显示。 见下图代码

class OrderHistory(LoginRequiredMixin, ListView):
    model = Order
    template_name = 'order/order_list.html'

    def get_context_data(self, **kwargs):
        context = super(OrderHistory, self).get_context_data()
        context['order_details'] = Order.objects.filter(emailAddress=self.request.user.email) #The code is correct till here
        order_details = Order.objects.filter(emailAddress=self.request.user.email)
        for order in order_details:
            print("Order items are", OrderItem.objects.filter(order=order))
            context['order_items'] = OrderItem.objects.filter(order=order)
        return context

灰色的订单详细信息是正确的,但 OrderItems 与订单不对应。它应该像第一张图片(上图)

Views.py 第二次尝试错误:我认为会在 views.py 中执行 OrderItem.objects.all()) 并且模板中的 forloop 将修复视图,但以下是我得到的错误

 class OrderHistory(LoginRequiredMixin, ListView):
model = Order
template_name = 'order/order_list.html'

def get_context_data(self, **kwargs):
    context = super(OrderHistory, self).get_context_data()
    context['order_details'] = Order.objects.filter(emailAddress=self.request.user.email) #The code is correct till here        
    print("Order items are", OrderItem.objects.all())
    context['order_items'] = OrderItem.objects.all()
    return context

这两个项目不属于订单,这也是不正确的。请参阅第一张图片以了解它应该如何。包含订单详情的灰色部分仍然正确

【问题讨论】:

  • 即使有所有信息,它仍然有点混乱......你有没有设法实现你想要的任何东西?究竟是什么问题? Django 弹出任何错误?

标签: django python-3.x django-models django-templates django-views


【解决方案1】:

这有点令人困惑,但我想我设法得到了积分......

问题就在这里...因为 Django 不是动态的,他们会在处理完所有内容后将您的数据发送到您的模板...您在这里所做的是覆盖 context['order_items'] 的每个值,因此他们只会发送到模板最后的数据。

for order in order_details:
    context['order_items'] = OrderItem.objects.filter(order=order)

当您在没有 forloop 的情况下更改为 context['order_items'] = OrderItem.objects.all() 时,现在您在没有设置任何订单的情况下获得了所有订单项...所以当您尝试从第一个订单显示 OrderItem 时,它们将显示所有 OrderItem。

解决方案是使用 TEMPLATETAGS,这样您就可以在处理 HTML 时过滤数据...

所以您需要根据您的订单过滤您的 OrderItem...因为在您的页面中您将显示许多订单,您必须根据此订单过滤 OrderItem

在您的应用程序中创建一个名为 templatetags 的文件夹,创建一个文件作为您的模板标签(不要忘记创建 __init__.py 文件)在这种情况下,我们将调用 order_templatetags.py

app/templatetags/order_templatetags.py

from django import template
from .models import OrderItem

register = template.Library()

@register.filter
def filter_order_items(self):
    return OrderItem.objects.filter(order__id=self.id)

在您的 HTML 中

<!-- IN TOP OF YOUR HTML (After Extends if you have it) PLACE THIS CODE -->
{% load order_templatetags %}

<!-- REST OF YOUR HTML CODE -->

{% for order in order_details %}
    <!-- REST OF YOUR HTML CODE -->

    {% for item in order|filter_order_items %} <!-- This gets the order items from the Order -->
        <!-- YOUR HTML STUFFS -->
    {% endfor %}

{% endfor %}

我的片段:https://github.com/Diegow3b/django-utils-snippet/blob/master/template_tag.MD

Django 文档:https://docs.djangoproject.com/en/2.0/howto/custom-template-tags/

【讨论】:

  • 我相信这也可以。但是我还没有测试过。在看到这个答案之前,我使用了以下解决方案
  • 好的,但我不确定您是否能够在 order_cushions 中运行任何过滤器,例如“is_active”或类似的东西
  • 通常使用@register.filter,但你也可以使用简单的标签
【解决方案2】:

好吧,我终于弄明白了

models.py(在订单字段中添加related_name)

class OrderItem(models.Model):
        product = models.CharField(max_length=250)
        quantity = models.IntegerField()
        price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='USD Price')
        order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name="order_cushions")
        image = models.ImageField()

views.py 是

class OrderHistory(LoginRequiredMixin, ListView):
    model = Order
    template_name = 'order/order_list.html'

    def get_context_data(self, **kwargs):
        context = super(OrderHistory, self).get_context_data()
        context['order_details'] = Order.objects.filter(emailAddress=self.request.user.email)
        print("Order items are", OrderItem.objects.all())
        context['order_items'] = OrderItem.objects.all()
        return context

最后在 templates.py 中

    {% for order in order_details %}
        {% for item in order.order_cushions.all %} #this is the models related_name
          {{item.image}} #this will get your image
          {{item.product}}
           {{item.price}}
           {{item.quantity}} #decorate using bootstrap the way you like 
     {% endfor %}
    {% endfor %}

【讨论】:

    【解决方案3】:

    我的方法是使用 Order 中的方法返回一个查询集

    models.py

    class Order(models.Model):
        ...
        def items(self):
            return OrderItem.objects.filter(order=self)
    

    在循环中调用项目

    Orderlist.html

    {% for order in order_details %}
        {% for item in order.items %}
            <!-- YOUR HTML STUFFS -->
        {% endfor %}
    {% endfor %}
    

    【讨论】:

      猜你喜欢
      • 2016-10-25
      • 1970-01-01
      • 2016-04-14
      • 2020-12-18
      • 2020-02-02
      • 1970-01-01
      • 2018-08-11
      • 2017-01-22
      • 2020-10-30
      相关资源
      最近更新 更多