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()
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
))
36 self
.base_slug
= self
._get
_base
_slug
(obj
)
40 def _get_base_slug(obj
):
43 base_slug
= slugify(obj
.title
)
48 def _get_existing_slugs():
53 """ Gets existing slugs and appends numbers until slug is unique """
54 if not self
.base_slug
:
57 existing_slugs
= self
._get
_existing
_slugs
()
59 if not self
.base_slug
in existing_slugs
:
60 return str(self
.base_slug
)
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
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 """
80 class PodcastSlug(PodcastGroupSlug
):
81 """ Generates slugs for Podcasts """
84 def _get_base_slug(podcast
):
85 base_slug
= SlugGenerator
._get
_base
_slug
(podcast
)
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
)
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
)
115 short_title
= obj
.get_short_title(self
.common_title
)
117 return slugify(short_title
)
120 return slugify(obj
.title
)
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 """
133 self
.merged_slugs
.append(self
.slug
)
135 self
.merged_slugs
= list(set(self
.merged_slugs
) - set([slug
]))
140 def remove_slug(self
, slug
):
141 """ Removes the slug from the object """
144 if self
.slug
== slug
:
147 # remove from merged slugs
148 self
.merged_slugs
= list(set(self
.merged_slugs
) - set([slug
]))