如何自定义Django查询 [英] How to custom sort a Django queryset

查看:153
本文介绍了如何自定义Django查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  class DVD(models.Model):
title = models.CharField(max_length = 100)
class DVDAdmin(admin.ModelAdmin):
ordering =('title',)

sample_titles = {鱼叫万达 ,好,坏,未排序,
A River Runs Upstream,The Incredibles,

我想生成一个按标题排序的查询集,但是将标题视为减去列表中的任何前导词,例如(a,an,the,) 。所以The Incredibles将排在A River Runs Upstream等之前。我不想只是在数据库中或在结果视图中截断数据。我想为querysets创建一个内部自定义排序。



一种看起来像是的方法可能是工作,是创建一个自定义的Changelist在这里将查询器排序为:

  from django.contrib.admin.views.main import Changelist 
class title_sortlist
def apply_special_ordering(self,queryset):
qs_desc = self.models.objects.all()。order_by(' - title')
return qs_desc
def get_query_set (self,request,* args,** kwargs):
queryset = super(title_sortlist,self).get_query_set(request)
queryset = self.apply_special_ordering(queryset)
return queryset

class DVDAdmin(admin.ModelAdmin):
ordering =('title',)
def get_changelist(self,request,** kwargs):
return title_sortlist

这适用于标准排序 - 降序排序将覆盖模型的升序排序。然而,我还没有想出如何采用查询和自定义排序。



另一种可能性是动态添加一个字段到模型,将其称为 cut_title ,进行适当的编辑,然后按该字段进行排序。不过,我刚刚开始阅读有关动态模式的变化,而且还不清楚如何做(更不用说,它似乎略有不同,比普通的猴子修补更多)。



第三个选项,我正在阅读Django有一个额外的选项,可以在其中添加额外的SQL,包括新的字段。我不知道如何添加一个代表编辑的标题的新SQL字段,但是Django SQL可以调用Python函数吗?



那么什么方法(如果有的话)最适合通过(修改)标题排序查询器?

解决方案

@bebraw在评论中其实是正确的。



创建一个特殊的排序字段是如何完成的。这也适用于像SOLR这样的搜索框架。您甚至可以使用特殊文本分析来根据语言进行排序。



在您的情况下,如果删除停止词(简短的文章列表) ,您将创建一个常规模型字段,从另一个字段复制数据,并删除停止字。



使用常规数据库字段的好处是:您可以创建一个DB索引(例如,在UPPER(值))上,并且能够对DB索引支持的不区分大小写进行排序(您将不得不添加一个额外的字段与QuerySet.extra对UPPER(值)进行排序。



这将允许快速排序和分页结果。如果您在Django中执行所有操作,您将不得不检索整个数据。这可能足够快了几百行,但如果数据增加,根本就不会缩放。



然而,数据。停止词语的反例是标题要或不要,完全由你可以轻易地分类为停止词,并且在通过这样的过滤器时简单地被消灭。


Given a data model with Title strings, say:

class DVD(models.Model):
    title = models.CharField(max_length=100)
class DVDAdmin(admin.ModelAdmin):
    ordering = ('title',)

sample_titles = {"A Fish Called Wanda", "The Good, the Bad, and the Unsorted",
                 "A River Runs Upstream", "The Incredibles",}

I want to generate a queryset sorted by title, but considering the title as minus any leading words that are in a list, such as ("a", "an", "the",). So "The Incredibles" would sort before "A River Runs Upstream", etc. I don't want to just truncate the data, either in the database or in the resulting view. I want to create an internal custom sort for querysets.

One approach that seems like it might work, is to create a custom Changelist, then sort the queryset there, as:

from django.contrib.admin.views.main import Changelist
class title_sortlist(Changelist):
    def apply_special_ordering(self, queryset):
        qs_desc = self.models.objects.all().order_by('-title')
        return qs_desc
    def get_query_set(self, request, *args, **kwargs):
        queryset = super(title_sortlist, self).get_query_set(request)
        queryset = self.apply_special_ordering(queryset)
        return queryset

class DVDAdmin(admin.ModelAdmin):
    ordering = ('title',)
    def get_changelist(self, request, **kwargs):
        return title_sortlist

This works for standard sorting - the descending sort does override the model's ascending sort. However, I haven't figured out how take a queryset and custom sort it.

Another possibility might be to dynamically add a field to the model, call it cut_title, suitably edited, then just sort by that field. However, I've just starting reading about dynamic model changes, and it's not clear how to do it (not to mention, it seems slightly wonky, more so than regular monkey-patching).

A third option, I was reading that Django has an extra option for querysets, where you can add additional SQL, including new fields. I have no idea how to add a new SQL field that represents the edited title, though - can Django SQL call a Python function, maybe?

So what approach, if any, would be best for sorting a queryset by (modified) title?

解决方案

@bebraw in the comments is actually right.

Creating a special sort field is how it is done. This is custom for search frameworks like SOLR, as well. You even might apply special text analysis to sort according to language.

In your case, if it's just as simple as to remove the stop words (a short list of articles), you would create a regular model field that copies the data from the other field and removes the stop words.

The benefit from using a regular DB field: you can create a DB index (e.g. on UPPER(value)) and be able to sort case insensitive supported by the DB index (you will have to add an extra field with QuerySet.extra to sort on UPPER(value)).

This will allow fast sorted and paged results. If you do everything in Django you will have to retrieve the whole data. This might be fast enough for some hundreds of rows but will not scale at all if the data increases.

HOWEVER: Be careful with stop words depending on your data. The anti example to stop words is the title "To Be or Not To Be" which consists completely of what you might easily classify as stop words and would simply be annihilated when running through such a filter.

这篇关于如何自定义Django查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆