Repository: liqd/a4-opin

Issue:
Use Generic Relation everywhere where generic fks are used



Discussion:

Resolving patch:
diff --git a/euth/documents/models.py b/euth/documents/models.py
--- a/euth/documents/models.py
+++ b/euth/documents/models.py
@@ -1,5 +1,5 @@
 from ckeditor.fields import RichTextField
-from django.contrib.contenttypes.models import ContentType
+from django.contrib.contenttypes.fields import GenericRelation
 from django.core.exceptions import ObjectDoesNotExist, ValidationError
 from django.db import models
 from django.utils.functional import cached_property
@@ -27,18 +27,6 @@ def clean(self, *args, **kwargs):
                 super().clean(*args, **kwargs)
         super().clean(*args, **kwargs)
 
-    @cached_property
-    def paragraphs_sorted(self):
-        return self.paragraphs.all().order_by('weight')
-
-    @cached_property
-    def comments(self):
-        contenttype = ContentType.objects.get_for_model(self)
-        pk = self.id
-        comments = comment_models.Comment.objects.all().filter(
-            content_type=contenttype, object_pk=pk)
-        return comments
-
 
 class Paragraph(base_models.TimeStampedModel):
     name = models.CharField(max_length=120, blank=True)
@@ -47,6 +35,9 @@ class Paragraph(base_models.TimeStampedModel):
     document = models.ForeignKey(Document,
                                  on_delete=models.CASCADE,
                                  related_name='paragraphs')
+    comments = GenericRelation(comment_models.Comment,
+                               related_query_name='paragraph',
+                               object_id_field='object_pk')
 
     class Meta:
         ordering = ('weight',)
@@ -59,14 +50,6 @@ def save(self, *args, **kwargs):
             self.text)
         super().save(*args, **kwargs)
 
-    @cached_property
-    def comments(self):
-        contenttype = ContentType.objects.get_for_model(self)
-        pk = self.id
-        comments = comment_models.Comment.objects.all().filter(
-            content_type=contenttype, object_pk=pk)
-        return comments
-
     @cached_property
     def project(self):
         return self.document.project
diff --git a/euth/documents/phases.py b/euth/documents/phases.py
--- a/euth/documents/phases.py
+++ b/euth/documents/phases.py
@@ -39,7 +39,7 @@ class CommentPhase(phases.PhaseContent):
     description = _('Collect comments for the text.')
 
     features = {
-        'comment': (models.Paragraph,),
+        'comment': (models.Paragraph, models.Document),
     }
 
 
diff --git a/euth/documents/serializers.py b/euth/documents/serializers.py
--- a/euth/documents/serializers.py
+++ b/euth/documents/serializers.py
@@ -7,6 +7,7 @@ class ParagraphSerializer(serializers.Serializer):
     id = serializers.IntegerField(required=False)
     name = serializers.CharField(
         required=False,
+        allow_blank=True,
         max_length=Paragraph._meta.get_field('name').max_length
     )
     weight = serializers.IntegerField()


Test patch:
diff --git a/tests/documents/test_document_models.py b/tests/documents/test_document_models.py
--- a/tests/documents/test_document_models.py
+++ b/tests/documents/test_document_models.py
@@ -1,4 +1,5 @@
 import pytest
+from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ValidationError
 
 from euth.comments import models as comments_models
@@ -35,7 +36,7 @@ def test_document_paragraphs_sorted(document, paragraph_factory):
     paragraph_factory(document=document, weight=2)
     paragraph2 = paragraph_factory(document=document, weight=1)
 
-    assert document.paragraphs_sorted.first() == paragraph2
+    assert document.paragraphs.first() == paragraph2
 
 
 @pytest.mark.django_db
@@ -50,14 +51,16 @@ def test_paragraphs_comments(paragraph, comment_factory):
 def test_delete_document(document, comment_factory):
     for i in range(5):
         comment_factory(content_object=document)
-    comment_count = comments_models.Comment.objects.all().count()
-    assert comment_count == len(document.comments.all())
 
-    assert comment_count == 5
+    def comments_for_document(document):
+        return comments_models.Comment.objects.filter(
+            object_pk=document.pk,
+            content_type=ContentType.objects.get_for_model(document)
+        )
 
+    assert len(comments_for_document(document)) == 5
     document.delete()
-    comment_count = comments_models.Comment.objects.all().count()
-    assert comment_count == 0
+    assert len(comments_for_document(document)) == 0
 
 
 @pytest.mark.django_db