короче хотелось какой-то такой интерфейс чтоб не размазывать код по вс

 1
 2
 3
 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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#короче хотелось какой-то такой интерфейс чтоб не размазывать код по всему проекту
class TechnicOrderSet(OrderSet):
order_fields = {
'views': OrderByField('views'),
'name': OrderByField('name'),
}
default_ordering = ('name', 'desc')
class OrderSet(object):
order_fields = {}
default_ordering = ()
def __init__(self, request, queryset):
self.request, self.queryset = request, queryset
self.order_key, self.order_type = self.get_current_ordering()
def __iter__(self):
for key, field in self.order_fields.items():
classes = []
new_order_type = 'asc'
if self.order_key == key:
classes.append('sorted %sending' % self.order_type)
new_order_type = {'asc': 'desc', 'desc': 'asc'}[self.order_type]
yield {
"text": _('by %s') % field.verbose_name,
"url": self.get_query_string(key, new_order_type),
"classes": ' '.join(classes),
}
def get_current_ordering(self):
ordering = self.request.GET.get('ordering')
if ordering:
order_type = ('asc', 'desc')[ordering.startswith('-')]
order_key = ordering.lstrip('-')
if order_key in self.order_fields:
return order_key, order_type
return self.default_ordering or (None, None)
@property
def ordered_queryset(self):
if not getattr(self, '_qs', None):
if self.order_key:
self._qs = self.order_fields[self.order_key].order(
self.queryset, self.order_type)
else:
self._qs = self.queryset.all()
return self._qs
def get_query_string(self, key, order_type):
query_dict = self.request.GET.copy()
if 'ordering' in query_dict:
del query_dict['ordering']
if 'page' in query_dict:
del query_dict['page']
if not (key, order_type) == self.default_ordering:
query_dict['ordering'] = encode_ordering(key, order_type)
if len(query_dict.keys()):
query_string = '?%s' % query_dict.urlencode()
else:
query_string = ''
return '%s%s' % (self.request.path, query_string)
class AvgOrderField(object):
def __init__(self, field, annotate_name=None, verbose_name=None):
self.field = field
if annotate_name:
self.annotate_name = annotate_name
else:
self.annotate_name = 'avg_%s' % field.split('__')[-1]
self.verbose_name = verbose_name
if not verbose_name:
self.verbose_name = self.annotate_name.replace('_', ' ')
def order(self, queryset, order_type):
return queryset.annotate(**{self.annotate_name: Avg(self.field)}).order_by(
encode_ordering(self.annotate_name, order_type)
)
class OrderByField(object):
def __init__(self, field, verbose_name=None):
self.field = field
self.verbose_name = verbose_name
if not verbose_name:
self.verbose_name = field
def order(self, queryset, order_type):
return queryset.order_by(encode_ordering(self.field, order_type))
def encode_ordering(order_field, order_type):
return '%s%s' % ('-' if order_type == 'desc' else '', order_field)