在Django中使用正则表达式按指定字段获取排序的查询集 [英] Get sorted queryset by specified field with regex in django

查看:50
本文介绍了在Django中使用正则表达式按指定字段获取排序的查询集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Manager中具有以下内容:

I have the following in Manager:

class NullIf(Func):
template = "NULLIF(%(expressions)s, '')"

class MySiteManager(models.Manager):

def get_queryset(self):
    qws = MySiteQuerySet(self.model, using=self._db).filter(
        some_id=settings.BASE_SOME_ID).annotate(
            # This is made for sorting by short labels as by numeric values
            short_label_numeric=Cast(
                NullIf(Func(
                    F('short_label'),
                    Value('^(\D+)|(\w+)'),
                    Value(''),
                    Value('g'),
                    function='regexp_replace')),
                models.BigIntegerField())
            ).order_by('short_label_numeric', 'short_label')

    for q in qws:
        print(q.short_label, end='\n')

    return qws

打印值的输出如下:

1101001011021031041051061071081091111011111211311411511611711811912120121122123124125126127128129131301311321331341351361371381391414014114214314414514614714814915150151152153154155156157158159161718岁1920200度21岁2223242526260261262263264265fs266fs267c268c269c27273c274c275c276c28岁292c303023132c33c3435c3637383c455015025035045055065075085095105115125135145155165175185195205215225246601602603604605606607608609610611612613614615616617618619620621622623770170270370470570670770870971088018028038048058068078088098109901902S1S10S11S12S13S14S15S16S17S18S19S2S20S3S4S5S6S7S8S9

1 10 100 101 102 103 104 105 106 107 108 109 11 110 111 112 113 114 115 116 117 118 119 12 120 121 122 123 124 125 126 127 128 129 13 130 131 132 133 134 135 136 137 138 139 14 140 141 142 143 144 145 146 147 148 149 15 150 151 152 153 154 155 156 157 158 159 16 17 18 19 20 200c 21 22 23 24 25 26 260 261 262 263 264 265fs 266fs 267c 268c 269c 27 273c 274c 275c 276c 28 29 2c 30 302 31 32c 33c 34 35c 36 37 38 3c 4 5 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 524 6 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 7 701 702 703 704 705 706 707 708 709 710 8 801 802 803 804 805 806 807 808 809 810 9 901 902 S1 S10 S11 S12 S13 S14 S15 S16 S17 S18 S19 S2 S20 S3 S4 S5 S6 S7 S8 S9

我的问题是:如何使用输出构建查询集看起来像例如1 2 3 3c 4 5 6 6c ... 264 265fs 266fs 267c 268c 269c ... S1 S2 S3 S4 ???有人有什么假设吗?

And my question: How to build queryset with output looks like e.g. 1 2 3 3c 4 5 6 6c ... 264 265fs 266fs 267c 268c 269c ... S1 S2 S3 S4 ??? Does someone have any assumptions?

推荐答案

主要思想是按数字排序,然后按标签的char部分排序,我无法复制和测试,但解决方案可能如下:

the main idea is order by numeric and then by char part of the label, i can't reproduce and test, but solution may looks like:

首先是sql:

SELECT 
  (regexp_matches(short_label, '^\d+'))[1]::numeric AS ln,
  regexp_matches(short_label, '^\D+') as ls,
  short_label
FROM YOUR_APP_TABLENAME ORDER BY 1, 2, 3;

正负号:

对于第一个SQL条件,我创建自定义函数

for first sql condition i create custom Func

In [1]: from myapp.models import *

In [2]: from django.db.models import F, Func, Value
   ...: 
   ...: class StartNumeric(Func):
   ...:     function = 'REGEXP_MATCHES'
   ...:     template = "(%(function)s(%(expressions)s, '^\d+'))[1]::int"
   ...: 
   ...: qs = Ingredient.objects.annotate(
   ...:     ln=StartNumeric('short_label'),
   ...:     ls=Func('short_label', Value('^\D+'), function='regexp_matches'),
   ...:     ).values('ln').order_by('ln', 'ls', 'short_label')
   ...: 
   ...:     

In [3]: print(qs.query)
SELECT (REGEXP_MATCHES("myapp_ingredient"."short_label", '^\d+'))[1]::int AS "ln" FROM "myapp_ingredient" ORDER BY "ln" ASC, regexp_matches("myapp_ingredient"."short_label", ^\D+) ASC, "myapp_ingredient"."short_label" ASC

In [4]: data = qs.values_list('short_label', flat=True)
   ...: print(list(data))
   ...: 
   ...: 
['1', '2c', '3c', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32c', '33c', '34', '35c', '36', '37', '38', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '200c', '260', '261', '262', '263', '264', '265fs', '266fs', '267c', '268c', '269c', '273c', '274c', '275c', '276c', '302', '501', '502', '503', '504', '505', '506', '507', '508', '509', '510', '511', '512', '513', '514', '515', '516', '517', '518', '519', '520', '521', '522', '524', '601', '602', '603', '604', '605', '606', '607', '608', '609', '610', '611', '612', '613', '614', '615', '616', '617', '618', '619', '620', '621', '622', '623', '701', '702', '703', '703', '704', '705', '706', '707', '708', '709', '710', '801', '802', '803', '804', '805', '806', '807', '808', '809', '810', '901', '902', 'aaaa', 'ddd', 'ddeee', 'rrrrr', 'S1', 'S10', 'S11', 'S12', 'S13', 'S14', 'S15', 'S16', 'S17', 'S18', 'S19', 'S2', 'S20', 'S3', 'S4', 'S5', 'S6', 'S7', 'S8', 'S9', 'vvvv', 'zzzz']

希望有帮助

这篇关于在Django中使用正则表达式按指定字段获取排序的查询集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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