kmike / django-faves
This app lets users favorite objects in your database (as well as unfavorite them). Original author is jeffrey.a.croft.
Clone this repository (size: 72.8 KB): HTTPS / SSH
$ hg clone http://bitbucket.org/kmike/django-faves/
| commit 79: | 1627b255b0eb |
| parent 78: | 3c15f0cc9717 |
| branch: | trunk |
| tags: | v0.6.2 |
New template tag is added: inject_faves_to. Some code refactoring is made.
- View kmike's profile
-
kmike's public repos »
- django-contact-form-i18n-ru
- pymorphy
- django-composition
- django-filebrowser
- django-grappelli
- django-robokassa
- GearsUploader
- django-yandex-maps
- django-generic-images
- django-photo-albums
- django-view-cache-utils
- django-sociable
- django-faves
- django-autoslug
- django-contact-form-i18n
- django-coverage
- django-simplepagination
- django-orm-cache
- django-assist-ru
- Send message
9 months ago
Changed (Δ1.8 KB):
raw changeset »
docs/overview.txt (26 lines added, 1 lines removed)
faves/templatetags/faves.py (74 lines added, 31 lines removed)
setup.py (1 lines added, 1 lines removed)
Up to file-list docs/overview.txt:
| … | … | @@ -46,7 +46,7 @@ Views: |
46 |
46 |
Template filters: |
47 |
47 |
|
48 |
48 |
- has_faved |
49 |
- is_ |
|
49 |
- is_favorited |
|
50 |
50 |
|
51 |
51 |
Template tags: |
52 |
52 |
|
| … | … | @@ -56,6 +56,7 @@ Template tags: |
56 |
56 |
- get_faves_for_user |
57 |
57 |
- get_favorited |
58 |
58 |
- get_fave |
59 |
- inject_faves_to |
|
59 |
60 |
|
60 |
61 |
|
61 |
62 |
|
| … | … | @@ -126,3 +127,27 @@ You have 'details' page for 1 object. It |
126 |
127 |
{% else %} |
127 |
128 |
<a href = '{% get_fave_url object "favorites" %}'>remove from favorites</a> |
128 |
129 |
{% endif %} |
130 |
||
131 |
||
132 |
=== New in version 0.6.2 === |
|
133 |
||
134 |
`inject_faves_to` template tag is added. It is similar to `get_favorited` tag |
|
135 |
but instead of setting context variable it adds attribute with Fave instance |
|
136 |
for each favorited object in `objects` list (iterable with django models). |
|
137 |
||
138 |
Syntax:: |
|
139 |
||
140 |
{% inject_faves_to [objects] by [user] of type [fave-type-slug] as [attribute_name] %} |
|
141 |
||
142 |
Example:: |
|
143 |
||
144 |
{% load faves %} |
|
145 |
{% inject_faves_to page.object_list by request.user of type favorites as fave %} |
|
146 |
||
147 |
{% for object in page.object_list %} |
|
148 |
{{ object }} |
|
149 |
{% if object.fave %} |
|
150 |
favorited |
|
151 |
{% endif %} |
|
152 |
{% endfor %} |
|
153 |
| … | … | @@ -12,6 +12,24 @@ register = Library() |
12 |
12 |
Fave = models.get_model('faves', 'fave') |
13 |
13 |
FaveType = models.get_model('faves', 'favetype') |
14 |
14 |
|
15 |
||
16 |
def validate_template_tag_params(bits, arguments_count, keyword_positions): |
|
17 |
''' |
|
18 |
Raises exception if passed params (`bits`) do not match signature. |
|
19 |
Signature is defined by `bits_len` (acceptible number of params) and |
|
20 |
keyword_positions (dictionary with positions in keys and keywords in values, |
|
21 |
for ex. {2:'by', 4:'of', 5:'type', 7:'as'}). |
|
22 |
''' |
|
23 |
||
24 |
if len(bits) != arguments_count+1: |
|
25 |
raise template.TemplateSyntaxError("'%s' tag takes %d arguments" % (bits[0], arguments_count,)) |
|
26 |
||
27 |
for pos in keyword_positions: |
|
28 |
value = keyword_positions[pos] |
|
29 |
if bits[pos] != value: |
|
30 |
raise template.TemplateSyntaxError("argument #%d to '%s' tag must be '%s'" % (pos, bits[0], value)) |
|
31 |
||
32 |
||
15 |
33 |
@register.filter |
16 |
34 |
def has_faved(value, arg): |
17 |
35 |
""" |
| … | … | @@ -106,7 +124,9 @@ def get_unfave_url(object, fave_type_slu |
106 |
124 |
""" |
107 |
125 |
try: |
108 |
126 |
content_type = ContentType.objects.get_for_model(object) |
109 |
return reverse('unfave_object', |
|
127 |
return reverse('unfave_object', kwargs={'fave_type_slug': fave_type_slug, |
|
128 |
'content_type_id': content_type.id, |
|
129 |
'object_id': object.id}) |
|
110 |
130 |
except: |
111 |
131 |
return '' |
112 |
132 |
|
| … | … | @@ -125,7 +145,6 @@ class GetFavoritesForUserNode(template.N |
125 |
145 |
context[self.varname] = Fave.objects.active().filter(type__slug=self.fave_type_slug, user=user, content_type=content_type) |
126 |
146 |
else: |
127 |
147 |
context[self.varname] = Fave.objects.active().filter(type__slug=self.fave_type_slug, user=user) |
128 |
# context[self.varname] = Fave.objects.active().filter(type__slug=self.fave_type_slug, user=user).values('id','content_type_id','object_id') |
|
129 |
148 |
except: |
130 |
149 |
pass |
131 |
150 |
return '' |
| … | … | @@ -162,25 +181,33 @@ def get_faves_for_user(parser, token): |
162 |
181 |
return GetFavoritesForUserNode(bits[1], bits[4], bits[5], bits[7]) |
163 |
182 |
|
164 |
183 |
|
165 |
||
166 |
184 |
class GetFavoritedNode(template.Node): |
167 |
185 |
def __init__(self, object_list, user, fave_type_slug, varname): |
168 |
186 |
self.object_list, self.user, self.fave_type_slug, self.varname = object_list, user, fave_type_slug, varname |
187 |
||
188 |
def return_results(self): |
|
189 |
context[self.varname] = self.faves_dict |
|
169 |
190 |
|
170 |
191 |
def render(self, context): |
171 |
192 |
try: |
172 |
193 |
user = resolve_variable(self.user, context) |
173 |
objects = resolve_variable(self.object_list, context) |
|
174 |
||
175 |
content_type = ContentType.objects.get_for_model(objects[0]) |
|
176 |
id_values = [item.id for item in objects] |
|
194 |
self.objects = resolve_variable(self.object_list, context) |
|
195 |
||
196 |
''' allow single object to be passed by putting it into list ''' |
|
197 |
try: |
|
198 |
it = iter(self.objects) |
|
199 |
except TypeError: |
|
200 |
self.objects = [self.objects] |
|
201 |
||
202 |
content_type = ContentType.objects.get_for_model(self.objects[0]) |
|
177 |
203 |
|
178 |
204 |
faves = Fave.objects.active().filter(type__slug=self.fave_type_slug, |
179 |
205 |
user=user, |
180 |
206 |
content_type=content_type, |
181 |
object_id__in= |
|
207 |
object_id__in=[item.id for item in self.objects]) |
|
208 |
self.faves_dict = dict((fave.object_id, fave) for fave in list(faves)) |
|
182 |
209 |
|
183 |
|
|
210 |
self.return_results() |
|
184 |
211 |
except: |
185 |
212 |
pass |
186 |
213 |
return '' |
| … | … | @@ -210,17 +237,43 @@ def get_favorited(parser, token): |
210 |
237 |
|
211 |
238 |
""" |
212 |
239 |
bits = token.contents.split() |
240 |
validate_template_tag_params(bits, 8, {2:'by', 4:'of', 5:'type', 7:'as'}) |
|
241 |
||
242 |
return GetFavoritedNode(bits[1], bits[3], bits[6], bits[8]) |
|
243 |
||
244 |
||
245 |
||
246 |
class InjectFavesToNode(GetFavoritedNode): |
|
247 |
def return_results(self): |
|
248 |
for object in self.objects: |
|
249 |
if self.faves_dict.has_key(object.id): |
|
250 |
object.__setattr__(self.varname, self.faves_dict[object.id]) |
|
251 |
||
252 |
@register.tag |
|
253 |
def inject_faves_to(parser, token): |
|
254 |
""" |
|
255 |
Adds attribute with Fave instance for each favorited object in `objects` list (iterable with django models) |
|
213 |
256 |
|
214 |
if len(bits) != 9: |
|
215 |
raise template.TemplateSyntaxError("'%s' tag takes 8 arguments" % bits[0]) |
|
216 |
||
217 |
keyword_positions = {2:'by', 4:'of', 5:'type', 7:'as'} |
|
218 |
for pos in keyword_positions: |
|
219 |
value = keyword_positions[pos] |
|
220 |
if bits[pos] != value: |
|
221 |
raise template.TemplateSyntaxError("argument #%d to '%s' tag must be '%s'" % (pos, bits[0], value)) |
|
222 |
||
223 |
return GetFavoritedNode(bits[1], bits[3], bits[6], bits[8]) |
|
257 |
Syntax:: |
|
258 |
||
259 |
{% inject_faves_to [objects] by [user] of type [fave-type-slug] as [attribute_name] %} |
|
260 |
||
261 |
Example:: |
|
262 |
||
263 |
{% inject_faves_to page.object_list by request.user of type favorites as fave %} |
|
264 |
||
265 |
{% for object in page.object_list %} |
|
266 |
{{ object }} |
|
267 |
{% if object.fave %} |
|
268 |
favorited |
|
269 |
{% endif %} |
|
270 |
{% endfor %} |
|
271 |
||
272 |
""" |
|
273 |
bits = token.contents.split() |
|
274 |
validate_template_tag_params(bits, 8, {2:'by', 4:'of', 5:'type', 7:'as'}) |
|
275 |
||
276 |
return InjectFavesToNode(bits[1], bits[3], bits[6], bits[8]) |
|
224 |
277 |
|
225 |
278 |
|
226 |
279 |
|
| … | … | @@ -255,16 +308,6 @@ def get_fave(parser, token): |
255 |
308 |
|
256 |
309 |
""" |
257 |
310 |
bits = token.contents.split() |
258 |
if len(bits) != 10: |
|
259 |
raise template.TemplateSyntaxError("'%s' tag takes nine arguments" % bits[0]) |
|
260 |
if bits[1] != 'by': |
|
261 |
raise template.TemplateSyntaxError("first argument to '%s' tag must be 'by'" % bits[0]) |
|
262 |
if bits[3] != 'on': |
|
263 |
raise template.TemplateSyntaxError("third argument to '%s' tag must be 'on'" % bits[0]) |
|
264 |
if bits[5] != 'of': |
|
265 |
raise template.TemplateSyntaxError("fifth argument to '%s' tag must be 'of'" % bits[0]) |
|
266 |
if bits[6] != 'type': |
|
267 |
raise template.TemplateSyntaxError("sixth argument to '%s' tag must be 'type'" % bits[0]) |
|
268 |
if bits[8] != 'as': |
|
269 |
raise template.TemplateSyntaxError("eighth argument to '%s' tag must be 'as'" % bits[0]) |
|
311 |
validate_template_tag_params(bits, 9, {1:'by', 3:'on', 5:'of', 6:'type', 8:'as'}) |
|
312 |
||
270 |
313 |
return GetFavoriteNode(bits[2], bits[4], bits[7], bits[9]) |
