9
9
from django .contrib .contenttypes .models import ContentType
10
10
try :
11
11
from django .contrib .contenttypes .fields import GenericForeignKey
12
- except ImportError :
12
+ except ImportError : # Django 1.8
13
13
from django .contrib .contenttypes .generic import GenericForeignKey
14
14
15
15
from . import settings
28
28
############
29
29
30
30
class TagManager (models .Manager ):
31
+
31
32
def update_tags (self , obj , tag_names ):
32
33
"""
33
34
Update tags associated with an object.
@@ -40,12 +41,13 @@ def update_tags(self, obj, tag_names):
40
41
updated_tag_names = [t .lower () for t in updated_tag_names ]
41
42
42
43
# Remove tags which no longer apply
43
- tags_for_removal = [tag for tag in current_tags \
44
+ tags_for_removal = [tag for tag in current_tags
44
45
if tag .name not in updated_tag_names ]
45
46
if len (tags_for_removal ):
46
- TaggedItem ._default_manager .filter (content_type__pk = ctype .pk ,
47
- object_id = obj .pk ,
48
- tag__in = tags_for_removal ).delete ()
47
+ TaggedItem ._default_manager .filter (
48
+ content_type__pk = ctype .pk ,
49
+ object_id = obj .pk ,
50
+ tag__in = tags_for_removal ).delete ()
49
51
# Add new tags
50
52
current_tag_names = [tag .name for tag in current_tags ]
51
53
for tag_name in updated_tag_names :
@@ -59,9 +61,11 @@ def add_tag(self, obj, tag_name):
59
61
"""
60
62
tag_names = parse_tag_input (tag_name )
61
63
if not len (tag_names ):
62
- raise AttributeError (_ ('No tags were given: "%s".' ) % tag_name )
64
+ raise AttributeError (
65
+ _ ('No tags were given: "%s".' ) % tag_name )
63
66
if len (tag_names ) > 1 :
64
- raise AttributeError (_ ('Multiple tags were given: "%s".' ) % tag_name )
67
+ raise AttributeError (
68
+ _ ('Multiple tags were given: "%s".' ) % tag_name )
65
69
tag_name = tag_names [0 ]
66
70
if settings .FORCE_LOWERCASE_TAGS :
67
71
tag_name = tag_name .lower ()
@@ -79,12 +83,14 @@ def get_for_object(self, obj):
79
83
return self .filter (items__content_type__pk = ctype .pk ,
80
84
items__object_id = obj .pk )
81
85
82
- def _get_usage (self , model , counts = False , min_count = None , extra_joins = None , extra_criteria = None , params = None ):
86
+ def _get_usage (self , model , counts = False , min_count = None ,
87
+ extra_joins = None , extra_criteria = None , params = None ):
83
88
"""
84
89
Perform the custom SQL query for ``usage_for_model`` and
85
90
``usage_for_queryset``.
86
91
"""
87
- if min_count is not None : counts = True
92
+ if min_count is not None :
93
+ counts = True
88
94
89
95
model_table = qn (model ._meta .db_table )
90
96
model_pk = '%s.%s' % (model_table , qn (model ._meta .pk .column ))
@@ -116,7 +122,8 @@ def _get_usage(self, model, counts=False, min_count=None, extra_joins=None, extr
116
122
params .append (min_count )
117
123
118
124
cursor = connection .cursor ()
119
- cursor .execute (query % (extra_joins , extra_criteria , min_count_sql ), params )
125
+ cursor .execute (query % (extra_joins , extra_criteria , min_count_sql ),
126
+ params )
120
127
tags = []
121
128
for row in cursor .fetchall ():
122
129
t = self .model (* row [:2 ])
@@ -125,7 +132,8 @@ def _get_usage(self, model, counts=False, min_count=None, extra_joins=None, extr
125
132
tags .append (t )
126
133
return tags
127
134
128
- def usage_for_model (self , model , counts = False , min_count = None , filters = None ):
135
+ def usage_for_model (self , model , counts = False , min_count = None ,
136
+ filters = None ):
129
137
"""
130
138
Obtain a list of tags associated with instances of the given
131
139
Model class.
@@ -143,7 +151,8 @@ def usage_for_model(self, model, counts=False, min_count=None, filters=None):
143
151
of field lookups to be applied to the given Model as the
144
152
``filters`` argument.
145
153
"""
146
- if filters is None : filters = {}
154
+ if filters is None :
155
+ filters = {}
147
156
148
157
queryset = model ._default_manager .filter ()
149
158
for f in filters .items ():
@@ -185,7 +194,8 @@ def usage_for_queryset(self, queryset, counts=False, min_count=None):
185
194
extra_criteria = 'AND %s' % where
186
195
else :
187
196
extra_criteria = ''
188
- return self ._get_usage (queryset .model , counts , min_count , extra_joins , extra_criteria , params )
197
+ return self ._get_usage (queryset .model , counts , min_count ,
198
+ extra_joins , extra_criteria , params )
189
199
190
200
def related_for_model (self , tags , model , counts = False , min_count = None ):
191
201
"""
@@ -200,13 +210,16 @@ def related_for_model(self, tags, model, counts=False, min_count=None):
200
210
greater than or equal to ``min_count`` will be returned.
201
211
Passing a value for ``min_count`` implies ``counts=True``.
202
212
"""
203
- if min_count is not None : counts = True
213
+ if min_count is not None :
214
+ counts = True
215
+
204
216
tags = get_tag_list (tags )
205
217
tag_count = len (tags )
206
218
tagged_item_table = qn (TaggedItem ._meta .db_table )
207
219
query = """
208
220
SELECT %(tag)s.id, %(tag)s.name%(count_sql)s
209
- FROM %(tagged_item)s INNER JOIN %(tag)s ON %(tagged_item)s.tag_id = %(tag)s.id
221
+ FROM %(tagged_item)s INNER JOIN %(tag)s ON
222
+ %(tagged_item)s.tag_id = %(tag)s.id
210
223
WHERE %(tagged_item)s.content_type_id = %(content_type_id)s
211
224
AND %(tagged_item)s.object_id IN
212
225
(
@@ -223,12 +236,14 @@ def related_for_model(self, tags, model, counts=False, min_count=None):
223
236
%(min_count_sql)s
224
237
ORDER BY %(tag)s.name ASC""" % {
225
238
'tag' : qn (self .model ._meta .db_table ),
226
- 'count_sql' : counts and ', COUNT(%s.object_id)' % tagged_item_table or '' ,
239
+ 'count_sql' : counts and ', COUNT(%s.object_id)' %
240
+ tagged_item_table or '' ,
227
241
'tagged_item' : tagged_item_table ,
228
242
'content_type_id' : ContentType .objects .get_for_model (model ).pk ,
229
243
'tag_id_placeholders' : ',' .join (['%s' ] * tag_count ),
230
244
'tag_count' : tag_count ,
231
- 'min_count_sql' : min_count is not None and ('HAVING COUNT(%s.object_id) >= %%s' % tagged_item_table ) or '' ,
245
+ 'min_count_sql' : min_count is not None and (
246
+ 'HAVING COUNT(%s.object_id) >= %%s' % tagged_item_table ) or '' ,
232
247
}
233
248
234
249
params = [tag .pk for tag in tags ] * 2
@@ -274,6 +289,7 @@ def cloud_for_model(self, model, steps=4, distribution=LOGARITHMIC,
274
289
min_count = min_count ))
275
290
return calculate_cloud (tags , steps , distribution )
276
291
292
+
277
293
class TaggedItemManager (models .Manager ):
278
294
"""
279
295
FIXME There's currently no way to get the ``GROUP BY`` and ``HAVING``
@@ -287,6 +303,7 @@ class TaggedItemManager(models.Manager):
287
303
Now that the queryset-refactor branch is in the trunk, this can be
288
304
tidied up significantly.
289
305
"""
306
+
290
307
def get_by_model (self , queryset_or_model , tags ):
291
308
"""
292
309
Create a ``QuerySet`` containing instances of the specified
@@ -412,7 +429,8 @@ def get_related(self, obj, queryset_or_model, num=None):
412
429
related_content_type = ContentType .objects .get_for_model (model )
413
430
query = """
414
431
SELECT %(model_pk)s, COUNT(related_tagged_item.object_id) AS %(count)s
415
- FROM %(model)s, %(tagged_item)s, %(tag)s, %(tagged_item)s related_tagged_item
432
+ FROM %(model)s, %(tagged_item)s, %(tag)s,
433
+ %(tagged_item)s related_tagged_item
416
434
WHERE %(tagged_item)s.object_id = %%s
417
435
AND %(tagged_item)s.content_type_id = %(content_type_id)s
418
436
AND %(tag)s.id = %(tagged_item)s.tag_id
@@ -448,10 +466,10 @@ def get_related(self, obj, queryset_or_model, num=None):
448
466
cursor .execute (query , params )
449
467
object_ids = [row [0 ] for row in cursor .fetchall ()]
450
468
if len (object_ids ) > 0 :
451
- # Use in_bulk here instead of an id__in lookup, because id__in would
452
- # clobber the ordering.
469
+ # Use in_bulk here instead of an id__in lookup,
470
+ # because id__in would clobber the ordering.
453
471
object_dict = queryset .in_bulk (object_ids )
454
- return [object_dict [object_id ] for object_id in object_ids \
472
+ return [object_dict [object_id ] for object_id in object_ids
455
473
if object_id in object_dict ]
456
474
else :
457
475
return []
@@ -466,7 +484,9 @@ class Tag(models.Model):
466
484
"""
467
485
A tag.
468
486
"""
469
- name = models .CharField (_ ('name' ), max_length = 50 , unique = True , db_index = True )
487
+ name = models .CharField (
488
+ _ ('name' ), max_length = 50 ,
489
+ unique = True , db_index = True )
470
490
471
491
objects = TagManager ()
472
492
@@ -484,10 +504,21 @@ class TaggedItem(models.Model):
484
504
"""
485
505
Holds the relationship between a tag and the item being tagged.
486
506
"""
487
- tag = models .ForeignKey (Tag , verbose_name = _ ('tag' ), related_name = 'items' )
488
- content_type = models .ForeignKey (ContentType , verbose_name = _ ('content type' ))
489
- object_id = models .PositiveIntegerField (_ ('object id' ), db_index = True )
490
- object = GenericForeignKey ('content_type' , 'object_id' )
507
+ tag = models .ForeignKey (
508
+ Tag ,
509
+ verbose_name = _ ('tag' ),
510
+ related_name = 'items' )
511
+
512
+ content_type = models .ForeignKey (
513
+ ContentType ,
514
+ verbose_name = _ ('content type' ))
515
+
516
+ object_id = models .PositiveIntegerField (
517
+ _ ('object id' ),
518
+ db_index = True )
519
+
520
+ object = GenericForeignKey (
521
+ 'content_type' , 'object_id' )
491
522
492
523
objects = TaggedItemManager ()
493
524
0 commit comments