[Migration] fix issues with users from Django Auth
[mygpo.git] / mygpo / core / slugs.py
blobd4b8bb4f43e41e768a5d9e46aff9d8b61c1d00a8
1 from collections import defaultdict
3 from itertools import count
5 from couchdbkit.ext.django.schema import *
7 from django.utils.text import slugify
9 from mygpo.podcasts.models import Slug, Episode
10 from mygpo.decorators import repeat_on_conflict
11 from mygpo.utils import partition
14 # TODO: move to feed-downloader?
15 def assign_missing_episode_slugs(podcast):
16 common_title = podcast.get_common_episode_title()
18 episodes = Episode.objects.filter(podcast=podcast, slugs__isnull=True)
20 for episode in episodes:
21 slug = EpisodeSlug(episode, common_title).get_slug()
22 if slug:
23 episode.set_slug(slug)
26 class SlugGenerator(object):
27 """ Generates a unique slug for an object """
30 def __init__(self, obj, override_existing=False):
31 if obj.slug and not override_existing:
32 raise ValueError('%(obj)s already has slug %(slug)s' % \
33 dict(obj=obj, slug=obj.slug))
35 self.obj = obj
36 self.base_slug = self._get_base_slug(obj)
39 @staticmethod
40 def _get_base_slug(obj):
41 if not obj.title:
42 return None
43 base_slug = slugify(obj.title)
44 return base_slug
47 @staticmethod
48 def _get_existing_slugs():
49 return []
52 def get_slug(self):
53 """ Gets existing slugs and appends numbers until slug is unique """
54 if not self.base_slug:
55 return None
57 existing_slugs = self._get_existing_slugs()
59 if not self.base_slug in existing_slugs:
60 return str(self.base_slug)
62 for n in count(1):
63 tmp_slug = '%s-%d' % (self.base_slug, n)
64 if not tmp_slug in existing_slugs:
65 # slugify returns SafeUnicode, we need a plain string
66 return str(tmp_slug)
68 def _get_existing_slugs(self):
69 query = Slug.objects.filter(scope=self.obj.scope,
70 slug__startswith=self.base_slug)
71 return [s.slug for s in query]
74 class PodcastGroupSlug(SlugGenerator):
75 """ Generates slugs for Podcast Groups """
77 pass
80 class PodcastSlug(PodcastGroupSlug):
81 """ Generates slugs for Podcasts """
83 @staticmethod
84 def _get_base_slug(podcast):
85 base_slug = SlugGenerator._get_base_slug(podcast)
87 if not base_slug:
88 return None
90 # append group_member_name to slug
91 if podcast.group_member_name:
92 member_slug = slugify(podcast.group_member_name)
93 if member_slug and not member_slug in base_slug:
94 base_slug = '%s-%s' % (base_slug, member_slug)
96 return base_slug
100 class EpisodeSlug(SlugGenerator):
101 """ Generates slugs for Episodes """
103 def __init__(self, episode, common_title, override_existing=False):
104 self.common_title = common_title
105 super(EpisodeSlug, self).__init__(episode, override_existing)
106 self.podcast_id = episode.podcast
109 def _get_base_slug(self, obj):
111 number = obj.get_episode_number(self.common_title)
112 if number:
113 return str(number)
115 short_title = obj.get_short_title(self.common_title)
116 if short_title:
117 return slugify(short_title)
119 if obj.title:
120 return slugify(obj.title)
122 return None
125 class SlugMixin(DocumentSchema):
126 slug = StringProperty()
127 merged_slugs = StringListProperty()
129 def set_slug(self, slug):
130 """ Set the main slug of the object """
132 if self.slug:
133 self.merged_slugs.append(self.slug)
135 self.merged_slugs = list(set(self.merged_slugs) - set([slug]))
137 self.slug = slug
140 def remove_slug(self, slug):
141 """ Removes the slug from the object """
143 # remove main slug
144 if self.slug == slug:
145 self.slug = None
147 # remove from merged slugs
148 self.merged_slugs = list(set(self.merged_slugs) - set([slug]))