From 256e7d939b02aed77e4b022038037bad6a5f79a9 Mon Sep 17 00:00:00 2001 From: Serghei Mihai Date: Fri, 20 Jan 2017 15:31:02 +0100 Subject: [PATCH] api: use categories slugs instead of ids (#13791) --- corbo/api_views.py | 8 ++++---- corbo/forms.py | 6 ++++++ corbo/migrations/0008_category_slug.py | 20 ++++++++++++++++++++ corbo/models.py | 1 + tests/test_api.py | 12 +++++++----- 5 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 corbo/migrations/0008_category_slug.py diff --git a/corbo/api_views.py b/corbo/api_views.py index 34af784..4f6dca0 100644 --- a/corbo/api_views.py +++ b/corbo/api_views.py @@ -33,7 +33,7 @@ class NewslettersView(APIView): newsletters = [] transports = [{'id': identifier, 'text': name} for identifier, name in channel_choices] for c in Category.objects.all(): - newsletter = {'id': str(c.pk), 'text': c.name, + newsletter = {'id': c.slug, 'text': c.name, 'transports': transports} newsletters.append(newsletter) return Response({'data': newsletters}) @@ -46,7 +46,7 @@ class SubscriptionsView(APIView): identifier = 'mailto:' + email for s in Subscription.objects.filter(Q(identifier=identifier) | Q(uuid=uuid)): cat_id = s.category.pk - subscriptions[cat_id]['id'] = str(cat_id) + subscriptions[cat_id]['id'] = s.category.slug subscriptions[cat_id]['text'] = s.category.name transport_id, transport_name = identifier.split(':') transport = {'id': transport_id, @@ -59,13 +59,13 @@ class SubscriptionsView(APIView): return subscriptions.values() @transaction.atomic - def update_subscriptions(self, category_id, transports, email, uuid=None): + def update_subscriptions(self, category_slug, transports, email, uuid=None): uuid = uuid or u'' identifier = u'mailto:' if email: identifier += email try: - cat = Category.objects.get(pk=category_id) + cat = Category.objects.get(slug=category_slug) except Category.DoesNotExist: return diff --git a/corbo/forms.py b/corbo/forms.py index 68ae4ea..4bd7f89 100644 --- a/corbo/forms.py +++ b/corbo/forms.py @@ -1,5 +1,6 @@ from django import forms from django.utils.translation import ugettext_lazy as _ +from django.utils.text import slugify from .models import Announce, Category, Broadcast, channel_choices @@ -28,3 +29,8 @@ class CategoryForm(forms.ModelForm): class Meta: fields = ('name', 'rss_feed_url') model = Category + + def save(self, commit=True): + if not self.instance.slug: + self.instance.slug = slugify(self.instance.name) + return super(CategoryForm, self).save(commit=commit) diff --git a/corbo/migrations/0008_category_slug.py b/corbo/migrations/0008_category_slug.py new file mode 100644 index 0000000..4bb4afe --- /dev/null +++ b/corbo/migrations/0008_category_slug.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('corbo', '0007_auto_20160928_1454'), + ] + + operations = [ + migrations.AddField( + model_name='category', + name='slug', + field=models.SlugField(default='', verbose_name='Slug'), + preserve_default=False, + ), + ] diff --git a/corbo/models.py b/corbo/models.py index 44bb2a2..2f32d0d 100644 --- a/corbo/models.py +++ b/corbo/models.py @@ -37,6 +37,7 @@ def transform_image_src(src, **kwargs): class Category(models.Model): name = models.CharField(_('Name'), max_length=64, blank=False, null=False) + slug = models.SlugField(_('Slug')) rss_feed_url = models.URLField(_('Feed URL'), blank=True, null=True, help_text=_('if defined, announces will be automatically created from rss items')) ctime = models.DateTimeField(auto_now_add=True) diff --git a/tests/test_api.py b/tests/test_api.py index 633a8ce..dd2ac45 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -5,20 +5,21 @@ from uuid import uuid4 from django.core.urlresolvers import reverse from django.utils.http import urlencode from django.contrib.auth import get_user_model +from django.utils.text import slugify from corbo.models import Category, Announce, Broadcast, Subscription from corbo.models import channel_choices pytestmark = pytest.mark.django_db -CATEGORIES = ('Alerts', 'News') +CATEGORIES = (u'Alerts', u'News') @pytest.fixture def categories(): categories = [] for category in CATEGORIES: - c, created = Category.objects.get_or_create(name=category) + c, created = Category.objects.get_or_create(name=category, slug=slugify(category)) categories.append(c) return categories @@ -55,6 +56,7 @@ def test_get_newsletters(app, categories, announces, user): for category in data['data']: assert 'id' in category assert 'text' in category + assert category['id'] in [slugify(c) for c in CATEGORIES] assert category['text'] in CATEGORIES assert 'transports' in category assert category['transports'] == [{'id': 'mailto', 'text': 'Email'}] @@ -73,7 +75,7 @@ def test_get_subscriptions_by_email(app, categories, announces, user): assert 'data' in resp.json data = resp.json['data'] for d in data: - assert d['id'] in [str(category.id) for category in categories] + assert d['id'] in [category.slug for category in categories] assert d['text'] in [category.name for category in categories] for t in d['transports']: assert t['id'] == identifier @@ -114,7 +116,7 @@ def test_delete_subscriptions(app, categories, announces, user): def test_simple_subscription(app, categories, user): - payload = {'category_id': 1} + payload = {'category_id': 'alerts'} url = '/api/subscribe/?email=john@example.net' # anonymous @@ -135,7 +137,7 @@ def test_simple_subscription(app, categories, user): data = resp.json['data'] assert len(data) == 1 - assert data[0]['id'] == '1' + assert data[0]['id'] == 'alerts' assert data[0]['text'] == 'Alerts' assert len(data[0]['transports']) == 1 transport = data[0]['transports'][0] -- 2.11.0