Django 有没有自动排序模型字段的方法?

1 投票
2 回答
902 浏览
提问于 2025-04-15 23:34

基本上,我正在做一个比较大的Django项目。这是一个私人网页门户,用户可以在这里管理各种与手机相关的任务。

门户的几个页面会向用户展示模型对象的列表,并在HTML表格中列出它们的所有属性(这样用户就可以直观地浏览这些项目的列表)。

我遇到的问题是:我找不到一种Django风格或Python风格的方法来按字段名称对这些模型对象进行排序。举个例子,这里有一个视图,它列出了所有的Partyline模型对象:

def list_partylines(request):
    """
    List all `Partyline`s that we own.
    """

    # Figure out which sort term to use.
    sort_field = request.REQUEST.get('sortby', 'did').strip()
    if sort_field.startswith('-'):
        search = sort_field[1:]
        sort_toggle = ''
    else:
        search = sort_field
        sort_toggle = '-'

    # Check to see if the sort term is valid.
    if not (search in Partyline._meta.get_all_field_names()):
        sort_field = 'did'

    if is_user_type(request.user, ['admin']):
        partylines = Partyline.objects.all().order_by(sort_field)
    else:
        partylines = get_my_partylines(request.user, sort_field)

    variables = RequestContext(request, {
        'partylines': partylines,
        'sort_toggle': sort_toggle
    })
    return render_to_response('portal/partylines/list.html', variables)

这个排序的代码基本上允许用户通过指定一个 /url/?sortby=model_field_name 的参数来进行排序,这样每当用户点击页面上显示的HTML表格名称时,就会返回一个排序后的对象列表。

因为我在不同的应用中有多个视图都显示模型对象的列表,并且都需要排序,所以我在想有没有一种通用的方法来进行排序,这样我就不需要每次都写相同的代码了?

抱歉如果这个问题有点不清楚,我在努力找到合适的方式来表达这个问题。

谢谢。

2 个回答

0

django.contrib.admin.views.main.ChangeList 这个地方,有一个很好的例子展示了如何以通用的方式来实现这个功能。虽然这个例子做的事情比排序要多,但你可以看看它的代码,获取一些灵感和想法。你也可以关注一下 django.contrib.admin.options.ModelAdmin,特别是里面的 changelist 方法,这样可以帮助你更好地理解相关内容。

2

我建议你可以通过自定义的查询集来实现这个功能。在你的模型里,你可以定义一个叫做 QuerySet 的类,并在里面添加你的排序逻辑。为了让所有的逻辑都保持在模型对象里,我还建议把 get_my_partylines 的内容也放到这个查询集中。

## This class is used to replicate QuerySet methods into a manager.
## This way:  Partyline.objects.for_user(foo) works the same as
## Partyline.objects.filter(date=today).for_user(foo)
class CustomQuerySetManager(models.Manager):
    def get_query_set(self):
        return self.model.QuerySet(self.model)
    def __getattr__(self, attr, *args):
        try:
            return getattr(self.__class__, attr, *args)
        except AttributeError:
            return getattr(self.get_query_set(), attr, *args)


class Partyline(models.Model):
    ## Define fields, blah blah.
    objects = CustomQuerySetManager()
    class QuerySet(QuerySet):
        def sort_for_request(self, request):
            sort_field = request.REQUEST.get('sortby', 'did').strip()
            reverse_order = False
            if sort_field.startswith('-'):
                search = sort_field[1:]
            else:
                search = sort_field
                reverse_order = True

            # Check to see if the sort term is valid.
            if not (search in Partyline._meta.get_all_field_names()):
                sort_field = 'did'

            partylines = self.all().order_by(sort_field)
            if reverse_order:
                partylines.reverse()
            return partylines
        def for_user(self, user):
            if is_user_type(request.user, ['admin']):
                return self.all()
            else:
                ## Code from get_my_partylines goes here.
                return self.all() ## Temporary.

views.py:

def list_partylines(request):
    """
    List all `Partyline`s that we own.
    """
    partylines = Partylines.objects.for_user(request.user).sort_for_request(request)

撰写回答