Ordering a Django QuerySet by a datetime's month/day?

前端 未结 5 601
太阳男子
太阳男子 2021-01-02 16:00

I have a list of people, each person having a birthdate, which is predictably stored in a DateField. I\'m trying to create a list of those people—sorted by the

相关标签:
5条回答
  • 2021-01-02 16:38

    For django >= 2.1

    You can sort the QuerySet by using month and day lookup names on DateField.

    SomeModel.objects.order_by('birth_date__month', 'birth_date__day')
    

    For django >= 1.10

    Use database-function Extract to generate extra month and day columns by annotate method, then order_by these columns you can sort the QuerySet by their birthday only.

    from django.db.models.functions import Extract
    
    SomeModel.objects.annotate(
        birth_date__month = Extract('birth_date', 'month'),
        birth_date__day = Extract('birth_date', 'day')
    ).order_by('birth_date__month', 'birth_date__day')
    

    For older django versions

    For older django versions you can do the same using QuerySet.extra(), but you have to write database specific query.

    • MySQL

      SomeModel.objects.extra(select={
              'birth_date_month': 'MONTH(birth_date)',
              'birth_date_day': 'DAY(birth_date)'
          },
          order_by=['birth_date_month','birth_date_day']
      )
      
    • PostgreSQL

      SomeModel.objects.extra(select={
              'birth_date_month': 'EXTRACT(MONTH FROM birth_date)',
              'birth_date_day': 'EXTRACT(DAY FROM birth_date)'
          },
          order_by=['birth_date_month','birth_date_day']
      )
      
    • SQlite

      SomeModel.objects.extra(select={
              'birth_date_month': 'strftime("%m", birth_date)',
              'birth_date_day': 'strftime("%d", birth_date)'
          },
          order_by=['birth_date_month','birth_date_day']
      )
      
    0 讨论(0)
  • 2021-01-02 16:39

    You can use QuerySet.extra() to define a month field and sort by it:

    SomeModel.objects.extra(select={'birthmonth': 'MONTH(birthdate)'},
        order_by=['birthmonth']) 
    
    0 讨论(0)
  • 2021-01-02 16:42

    Newer versions of django have the lookup on DateFields and DateTimeFields. https://docs.djangoproject.com/en/1.11/ref/models/database-functions/#extract

    MyModel.objects.order_by('birthday__month', 'birthday__day')

    0 讨论(0)
  • 2021-01-02 16:43

    I tested using django 1.10.8

    from django.db.models.functions import Extract
    from your_project.your_app.models import Person
    
    
    CHOICE_MONTH = (
        (None, '--'),
        (1, 1),
        (2, 2),
        (3, 3),
        (4, 4),
        (5, 5),
        (6, 6),
        (7, 7),
        (8, 8),
        (9, 9),
        (10, 10),
        (11, 11),
        (12, 12),
    )
    
    class PersonSearchForm(forms.Form):
    
        name = forms.CharField(label=u'name', required=False)
        month = forms.ChoiceField(label='month', choices=CHOICE_MONTH, required=False)
    
        def __init__(self, *args, **kwargs):
            self.corporation = kwargs.pop('corporation', None)
            super(PersonSearchForm, self).__init__(*args, **kwargs)
    
        def get_result_queryset(self):
            q = Q(corporation=self.corporation)
            if self.is_valid():
                name = self.cleaned_data['name']
                if name:
                    q = q & Q(name__icontains=name)
                month = self.cleaned_data['month']
                if month:
                    q = q & Q(month=int(month))
    
            return Person.objects.annotate(month=Extract('birthday', 'month'),
                                           day=Extract('birthday', 'day')).filter(q).order_by('month', 'day')
    
    0 讨论(0)
  • 2021-01-02 16:44

    Post.objects.all().order_by('date_posted__minute').reverse() where date_posted is your attribute you used in your Post model.

    Post is just an example model

    0 讨论(0)
提交回复
热议问题