具有条件的嵌套对象列表

时间:2014-08-25 13:26:31

标签: python django

我还是django的新手,但我感到惊讶的是我没有找到令人满意的答案,但无论如何。

我有以下模型结构(每天订购食物):

# Extended user profile
class UserProfile(models.Model)
# One day - daily menu
class OrderingDay(models.Model)
# One menu (there
class MenuItem(models.Model)
    date = models.ForeignKey(OrderingDay, null=True, blank=True)

# One user ordered something during the day
class Order(models.Model):
    user = models.ForeignKey(UserProfile)
    date = models.ForeignKey(OrderingDay)
    item = models.ForeignKey(MenuItem)

有些菜单每天都会更改(例如鸡汤仅在星期一,MenuItem.date = not null提供)和一些膳食(汉堡)每天都有(MenuItem.date = null)。

我只想列出当前用户所做的所有订单:

Monday:
     Hamburger
     Chicken Soup

# Nothing on Tuesday - skip

Wednesday:
    Meatballs 

我可以在用户下订单时过滤OrderingDays

class CurrentOrdersListingView(generic.ListView):
    model = OM.OrderingDay
    context_object_name='ordering_days'

    def get_queryset(self):
        return OM.OrderingDay.filter(order__user=self.request.user)\
               .distinct()

但我无法谷歌如何使用重复使用的过滤器列出orders(我发现following relations backwards}。

如何实现模板的以下语法:

{% for od in ordering_days %}
<h2>{{ od.date }}</h2>
    {% for item in od.items_by_current_user %}
        {{ item }}
    {% endfor %}
{% endfor %}

1 个答案:

答案 0 :(得分:2)

Django可帮助您创建最常见的查询,而无需使用原始SQL。实际上找出如何将你想要的内容翻译成Django需要你写下来的内容可能很棘手。在尝试进行查询时,要记住的最有用的事情:使用您想要的内容启动查询。

如果它是您想要的订单,您应该查询订单(而不是像您在您的示例中所做的那样的OrderingDay对象)。

所以你想要一个用户的订单?类似于Order.filter(user=self.request.user)

啊,但你想要按天分组的订单吗?最简单的方法是首先通过向其添加.values()来简化查询输出:``Order.filter(user = self.request.user).values(&#39; date&#39;,&#39; item& #39;)`。这将返回一个简单的dicts列表:

[{'date': 'date 1',
  'item': 'hamburgers'},
 {...},
 {...}]  

然后您可以在模板中使用'regroup' template tag。在您的情况下按'date'重新组合。

或者,您可以在代码中执行此操作。在CurrentOrdersListingView课程中,添加items_per_day()方法,如下所示:

def items_per_day(self):
    ... your custom grouping code ...
    ... return ['date 1': [item1, item2, item3],
                'date 2': [item2],
                ...

只需在模板中调用该方法:

{% for date, items in view.items_per_day %}
  <h2>{{ date }}</h2>
  ....
 {% endfor %}

(视图类的方法自动在模板中以view.method_name形式提供)。


以下是最终使用的解决方案:

您可以使用

选择所有Orders
def get_queryset(self):
    return OM.Order.objects.order_by('date__date')\
           .filter(user=self.request.user)

然后使用sort:

使用regroup(它能够完美地处理模型对象)
{% regroup ordering_days|dictsort:"date.date" by date as ordering_items %}
{% for ordering_day in ordering_items %}
    <h3>{{ ordering_day.grouper.date|date:'l' }}</h3>
    {% for oi in ordering_day.list %}
        {{ oi.item.name }}
    {% endfor %}
{% endfor %}