使用Django中的DB按日期排序

时间:2013-02-25 21:20:37

标签: python django

我有以下model.py。

from django.db import models

class Address(models.Model):
    addr = models.CharField(max_length=150)

    def __unicode__(self):
        return u'%s' % (self.addr)

class Anniversary(models.Model):
    date = models.DateField()

    def __unicode__(self):
        return u'%s' % (self.date)

class Person(models.Model):
    name = models.CharField(max_length=50)
    birthday = models.DateField()
    anniversary = models.ForeignKey(Anniversary)
    address = models.ForeignKey(Address)

    def __unicode__(self):
        return u'%s %s %s %s' % (self.name, self.birthday, self.anniversary, self.address)

我想将所有条目的内容打印到我的模板中。但按出生日期与当前日期排序。即最近的第一个然后是名字。做这个的最好方式是什么。我应该先将它排序,然后将其附加到列表或词典中吗?

任何指针都会很棒。

谢谢,

4 个答案:

答案 0 :(得分:11)

您可以在模型的元类中添加默认排序,例如

class Person(models.Model):
    # fields
    class Meta:
        ordering = ('anniversary__date',)

然后在你的模板中,它就像:

一样简单
<ul>
    {% for person in persons %}
        <li>{{ person.anniversary.date|date:"M d, Y" }} - {{ person.name }}</li>
    {% endfor %}
</ul>

如果您需要在视图中进行自定义排序(根据请求对象过滤掉人员):

def myview(request):
    context = dict(
        persons = Person.objects.exclude(person.id=request.user.id)\
                                .order_by('anniversary__date')
    )
    return render_to_response('app/template.html', context)

N.b。在order_by参数order_by('-attr')之前添加减号会反转排序。

正如@DanielEriksson所提到的,如果你的情况不是假设,那么你似乎应该简化一些事情。

答案 1 :(得分:0)

我认为你正在寻找这个:

          persons = Person.objects.all().order_by(birthday ,anniversary)

在您查看中,您可以使用以下方式获取当前日期:

          import datetime 
          now = datetime.datetime.now()

然后:

          persons = Person.objects.all().order_by(now, anniversary)

希望它有所帮助!

答案 2 :(得分:0)

我个人希望避免在模型中进行排序,因为它更像是一种表示/视图类型的东西。我倾向于在render_to_response中使用sorted进行单值排序,或者使用order_by进行多值排序。在return语句中使用sorted可以让我分割视图/模板之间的差异,因为Django视图不完全是控制器。无论如何,这只是我的偏好。您还可以在模板中使用dictsort进行单值排序。

您已指出要使用多个值排序,首先是最近的出生日期,然后是名称。为此,我将在视图中使用order_by,然后注释我的return语句:

from django.shortcuts import render_to_response

def view_persons(request):

    persons = Person.objects.all().order_by('-birthday', 'name')

    return render_to_response(
        'view_persons.html',
        {
            'persons': persons,  # ordered by most recent birthday, then name
        },
        context_instance=RequestContext(request)
    )

在模板中,您除此之外还有更多工作要做:

{% if persons %}
  <table>
    <thead>
      <tr>
        <th>Birthday</th>
        <th>Name</th>
      </tr>
    </thead>
    <tbody>
  {% for person in persons %}
      <tr>
        <td>{{ person.birthday }}</td>
        <td>{{ person.name }}</td>
      </tr>
  {% endfor %}
    </tbody>
  </table>
{% else %}
  <p>There are no people!</p>
{% endif %}

答案 3 :(得分:0)

我想复杂的是你需要将排序日期与当前日期进行比较,而不是简单地按日期排序。

如果您正在使用Postgres并且乐于坚持使用原始SQL,那么您可能会使用其日期时间函数,例如年龄

http://www.postgresql.org/docs/8.1/static/functions-datetime.html

否则,您需要选择出生日期/周年纪念日大于现在的位置。如果您重构周年纪念模型以将日,月和年存储为单独的字段可能会更简单,这样您就可以忽略过滤时的年份。

我最近在一个问题中发布了一些代码,可能会给你一些提示 - 我需要返回最接近现在的事件。参见:

Is it bad practice to return a tuple from a Django Manager method rather than a queryset?