From ee3b8d45943b223770cc1c11b052e90e84cfb480 Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Thu, 17 Mar 2016 15:53:40 +0200 Subject: [PATCH] Allow plugin data to be posted as a comment without other content Refs #154 --- .../migrations/0011_contentless_comments.py | 25 +++++++++++++++++++ democracy/models/comment.py | 4 ++- democracy/tests/test_comment.py | 10 +------- democracy/views/hearing_comment.py | 12 +++++++-- democracy/views/section_comment.py | 2 ++ 5 files changed, 41 insertions(+), 12 deletions(-) create mode 100644 democracy/migrations/0011_contentless_comments.py diff --git a/democracy/migrations/0011_contentless_comments.py b/democracy/migrations/0011_contentless_comments.py new file mode 100644 index 00000000..dbbeedb5 --- /dev/null +++ b/democracy/migrations/0011_contentless_comments.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.2 on 2016-03-17 13:46 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('democracy', '0010_auto_20160315_1026'), + ] + + operations = [ + migrations.AlterField( + model_name='hearingcomment', + name='content', + field=models.TextField(blank=True, verbose_name='content'), + ), + migrations.AlterField( + model_name='sectioncomment', + name='content', + field=models.TextField(blank=True, verbose_name='content'), + ), + ] diff --git a/democracy/models/comment.py b/democracy/models/comment.py index c472ede5..f8b947e9 100644 --- a/democracy/models/comment.py +++ b/democracy/models/comment.py @@ -10,7 +10,7 @@ class BaseComment(BaseModel): parent_field = None # Required for factories and API parent_model = None # Required for factories and API title = models.CharField(verbose_name=_('title'), blank=True, max_length=255) - content = models.TextField(verbose_name=_('content')) + content = models.TextField(verbose_name=_('content'), blank=True) authorization_code = models.CharField(verbose_name=_('authorization code'), max_length=32, blank=True) author_name = models.CharField(verbose_name=_('author name'), max_length=255, blank=True, null=True, editable=False) plugin_identifier = models.CharField(verbose_name=_('plugin identifier'), blank=True, max_length=255) @@ -54,6 +54,8 @@ def parent_id(self): return getattr(self, "%s_id" % self.parent_field, None) def save(self, *args, **kwargs): + if not (self.plugin_data or self.content): + raise ValueError("Comments must have either plugin data or textual content") if not self.author_name: self.author_name = (str(self.created_by) if self.created_by_id else None) return super(BaseComment, self).save(*args, **kwargs) diff --git a/democracy/tests/test_comment.py b/democracy/tests/test_comment.py index d1103d15..1293c832 100644 --- a/democracy/tests/test_comment.py +++ b/democracy/tests/test_comment.py @@ -146,15 +146,6 @@ def test_56_add_comment_to_section_without_data(api_client, default_hearing): assert response.status_code == 400 -@pytest.mark.django_db -def test_56_add_comment_to_section_invalid_key(api_client, default_hearing): - section = default_hearing.sections.first() - url = get_hearing_detail_url(default_hearing.id, 'sections/%s/comments' % section.id) - response = api_client.post(url, data={'invalidKey': 'Yes it is'}) - # expect bad request, we have invalid key in payload - assert response.status_code == 400 - - @pytest.mark.django_db def test_56_add_comment_to_section(john_doe_api_client, default_hearing): section = default_hearing.sections.first() @@ -333,6 +324,7 @@ def test_add_plugin_data_to_comment(api_client, default_hearing, case): section.save() url = get_hearing_detail_url(default_hearing.id, 'sections/%s/comments' % section.id) comment_data = get_comment_data( + content="", plugin_data=("foo6" if case == "plug-valid" else "invalid555") ) response = api_client.post(url, data=comment_data) diff --git a/democracy/views/hearing_comment.py b/democracy/views/hearing_comment.py index 40f025d7..2e8c417d 100644 --- a/democracy/views/hearing_comment.py +++ b/democracy/views/hearing_comment.py @@ -1,20 +1,28 @@ +from rest_framework.exceptions import ValidationError + from democracy.models import HearingComment from democracy.views.comment import COMMENT_FIELDS, BaseCommentSerializer, BaseCommentViewSet class HearingCommentSerializer(BaseCommentSerializer): - class Meta: model = HearingComment fields = ['hearing'] + COMMENT_FIELDS class HearingCommentCreateSerializer(BaseCommentSerializer): - class Meta: model = HearingComment fields = ['content', 'hearing', 'authorization_code'] + def validate(self, attrs): + attrs = super().validate(attrs) + + if not attrs.get("content"): + raise ValidationError("Content must be supplied.") + + return attrs + class HearingCommentViewSet(BaseCommentViewSet): model = HearingComment diff --git a/democracy/views/section_comment.py b/democracy/views/section_comment.py index 2ef16ba9..bd242676 100644 --- a/democracy/views/section_comment.py +++ b/democracy/views/section_comment.py @@ -39,6 +39,8 @@ def validate(self, attrs): detail.setdefault("plugin_data", []).extend(detail.pop(api_settings.NON_FIELD_ERRORS_KEY, ())) raise ValidationError(detail=detail) attrs["plugin_identifier"] = section.plugin_identifier + if not (attrs.get("plugin_data") or attrs.get("content")): + raise ValidationError("Either content or plugin data must be supplied.") return attrs