【问题标题】:Order model by field with choices带有选项的按字段排序模型
【发布时间】:2012-06-17 21:50:44
【问题描述】:

我正在尝试使用具有预定义选项的字段在 Django 应用程序中订购模型。我可以按字母顺序排序,但由于选择是星期几,这与我需要的不太匹配。这是模型:

class Slot( models.Model ):

    DAY_CHOICES = (
        ('SUN', 'Sunday'),
        ('MON', 'Monday'),
        ('TUE', 'Tuesday'),
        ('WED', 'Wednesday'),
        ('THU', 'Thursday'),
        ('FRI', 'Friday'),
        ('SAT', 'Saturday'),
    )

    day = models.CharField( max_length=3, choices=DAY_CHOICES )
    start = models.TimeField()
    end = models.TimeField()
    template = models.ForeignKey( Template )

这是将模型拉入管理视图的内联:

class SlotInline( admin.TabularInline ):
    model = Slot
    ordering = ('day','start',)

我知道我可能会使用一个整数作为存储值,但是有没有一种通用的方法可以将自定义排序顺序强加到具有选项的字段上?

【问题讨论】:

    标签: python django django-models


    【解决方案1】:

    您应该将数据存储为整数(例如 0 = 星期日),并使用选项将该整数映射到日期。那么排序就简单了。

    【讨论】:

    • 我在问题中指出了这种方法 - 我正在寻找一种更通用的按选择排序的方法。它在这种情况下有效,但是当排序顺序需要更改时会发生什么?我不应该仅仅因为我想以不同的方式显示它就需要修改我的模型。
    【解决方案2】:

    引用https://docs.djangoproject.com/en/dev/ref/models/fields/#field-choices最后一段话:

    但是,如果您发现自己的黑客选择是动态的,那么您就是 最好使用带有 ForeignKey 的适当数据库表。 选择适用于不会发生太大变化(如果有的话)的静态数据。

    所以我会说答案是否定的,您最好使用带有订购字段的单独 Day 模型

    class Day(models.Model):
        name = models.CharField(max_length=9)
        ordering = models.PositiveIntegerField()
    
        class Meta:
            ordering = ['ordering']
    

    尽管 7 件物品感觉有点矫枉过正!

    【讨论】:

      【解决方案3】:

      如果您正在编写自己的视图而不是使用管理视图,您可能会在原始 SQL 中进行排序。我以前在 Oracle 中做过类似的事情:

      ORDER BY decode(day, 'SUN', 0, 'MON', 1 )
      

      我不知道您如何将其与 QuerySet.order_by() 匹配 - 也许您需要使用 QuerySet.raw() 来使用直接 SQL 进行查询。

      【讨论】:

        【解决方案4】:

        也许你应该看看这个库:https://github.com/bigjason/django-choices

        我不知道做这种事情的任何基本知识,与可以指定函数名称的字段不同,您不能在排序时这样做。您可以做的唯一特别的事情是指定 get_ordering。

        【讨论】:

          【解决方案5】:

          您可以使用extra,尽管实现可能不够优雅,需要针对复杂的查询和不同的选择进行调整:

          # generate 'WHEN foo THEN bar's
          switch = ' '.join("WHEN '{}' THEN {}".format(x[0],i) for i,x in enumerate(Slot.DAY_CHOICES))
          # basic queryset
          Slot.objects.extra(select={'day_index':'CASE day {} END'.format(switch)}).order_by('day_index', 'start')
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-01-08
            • 1970-01-01
            • 1970-01-01
            • 2015-02-18
            • 1970-01-01
            • 1970-01-01
            • 2015-08-31
            • 1970-01-01
            相关资源
            最近更新 更多