1 # -*- coding: utf-8 -*-
2 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
3 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
5 from django.contrib.auth.models import User
6 from django.db import models
7 from django.db.models import permalink
8 from django.utils.translation import ugettext_lazy as _
9 from newtagging.models import TagBase
12 # Those are hard-coded here so that makemessages sees them.
14 ('author', _('author')),
15 ('epoch', _('epoch')),
17 ('genre', _('genre')),
18 ('theme', _('theme')),
25 """A tag attachable to books and fragments (and possibly anything).
27 Used to represent searchable metadata (authors, epochs, genres, kinds),
28 fragment themes (motifs) and some book hierarchy related kludges."""
29 name = models.CharField(_('name'), max_length=50, db_index=True)
30 slug = models.SlugField(_('slug'), max_length=120, db_index=True)
31 sort_key = models.CharField(_('sort key'), max_length=120, db_index=True)
32 category = models.CharField(_('category'), max_length=50, blank=False, null=False,
33 db_index=True, choices=TAG_CATEGORIES)
34 description = models.TextField(_('description'), blank=True)
36 user = models.ForeignKey(User, blank=True, null=True)
37 book_count = models.IntegerField(_('book count'), blank=True, null=True)
38 gazeta_link = models.CharField(blank=True, max_length=240)
39 wiki_link = models.CharField(blank=True, max_length=240)
41 created_at = models.DateTimeField(_('creation date'), auto_now_add=True, db_index=True)
42 changed_at = models.DateTimeField(_('creation date'), auto_now=True, db_index=True)
44 class UrlDeprecationWarning(DeprecationWarning):
55 categories_dict = dict((item[::-1] for item in categories_rev.iteritems()))
58 ordering = ('sort_key',)
59 verbose_name = _('tag')
60 verbose_name_plural = _('tags')
61 unique_together = (("slug", "category"),)
62 app_label = 'catalogue'
64 def __unicode__(self):
68 return "Tag(slug=%r)" % self.slug
71 def get_absolute_url(self):
72 return ('catalogue.views.tagged_object_list', [self.url_chunk])
76 def create_url(cls, category, slug):
77 return ('catalogue.views.tagged_object_list', [
78 '/'.join((cls.categories_dict[category], slug))
81 def has_description(self):
82 return len(self.description) > 0
83 has_description.short_description = _('description')
84 has_description.boolean = True
87 """Returns global book count for book tags, fragment count for themes."""
88 from catalogue.models import Book, Fragment
90 if self.category == 'book':
92 objects = Book.objects.none()
93 elif self.category == 'theme':
94 objects = Fragment.tagged.with_all((self,))
96 objects = Book.tagged.with_all((self,)).order_by()
97 if self.category != 'set':
98 # eliminate descendants
99 l_tags = Tag.objects.filter(slug__in=[book.book_tag_slug() for book in objects.iterator()])
100 descendants_keys = [book.pk for book in Book.tagged.with_any(l_tags).iterator()]
102 objects = objects.exclude(pk__in=descendants_keys)
103 return objects.count()
106 def get_tag_list(tags):
107 if isinstance(tags, basestring):
112 tags_splitted = tags.split('/')
113 for name in tags_splitted:
115 real_tags.append(Tag.objects.get(slug=name, category=category))
117 elif name in Tag.categories_rev:
118 category = Tag.categories_rev[name]
121 real_tags.append(Tag.objects.exclude(category='book').get(slug=name))
123 except Tag.MultipleObjectsReturned, e:
124 ambiguous_slugs.append(name)
127 # something strange left off
128 raise Tag.DoesNotExist()
130 # some tags should be qualified
131 e = Tag.MultipleObjectsReturned()
133 e.ambiguous_slugs = ambiguous_slugs
136 e = Tag.UrlDeprecationWarning()
141 return TagBase.get_tag_list(tags)
145 return '/'.join((Tag.categories_dict[self.category], self.slug))
148 def tags_from_info(info):
149 from fnpdjango.utils.text.slughifi import slughifi
150 from sortify import sortify
152 categories = (('kinds', 'kind'), ('genres', 'genre'), ('authors', 'author'), ('epochs', 'epoch'))
153 for field_name, category in categories:
155 tag_names = getattr(info, field_name)
158 tag_names = [getattr(info, category)]
160 # For instance, Pictures do not have 'genre' field.
162 for tag_name in tag_names:
163 tag_sort_key = tag_name
164 if category == 'author':
165 tag_sort_key = tag_name.last_name
166 tag_name = tag_name.readable()
167 tag, created = Tag.objects.get_or_create(slug=slughifi(tag_name), category=category)
170 tag.sort_key = sortify(tag_sort_key.lower())
172 meta_tags.append(tag)