Commit f744905f authored by Florent Chehab's avatar Florent Chehab

Updated backend for performance regarding pending moderation

Added has_pending_moderation attribute
Tests also updated
parent 16f0fb7d
Pipeline #36193 passed with stages
in 5 minutes and 1 second
...@@ -5,69 +5,67 @@ from django.db import migrations, models ...@@ -5,69 +5,67 @@ from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("backend_app", "0001_initial")]
('backend_app', '0001_initial'),
]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='campus', model_name="campus",
name='nb_version', name="nb_version",
field=models.PositiveIntegerField(default=0), field=models.PositiveIntegerField(default=0),
), ),
migrations.AddField( migrations.AddField(
model_name='campustaggeditem', model_name="campustaggeditem",
name='nb_version', name="nb_version",
field=models.PositiveIntegerField(default=0), field=models.PositiveIntegerField(default=0),
), ),
migrations.AddField( migrations.AddField(
model_name='citytaggeditem', model_name="citytaggeditem",
name='nb_version', name="nb_version",
field=models.PositiveIntegerField(default=0), field=models.PositiveIntegerField(default=0),
), ),
migrations.AddField( migrations.AddField(
model_name='countrydri', model_name="countrydri",
name='nb_version', name="nb_version",
field=models.PositiveIntegerField(default=0), field=models.PositiveIntegerField(default=0),
), ),
migrations.AddField( migrations.AddField(
model_name='countryscholarship', model_name="countryscholarship",
name='nb_version', name="nb_version",
field=models.PositiveIntegerField(default=0), field=models.PositiveIntegerField(default=0),
), ),
migrations.AddField( migrations.AddField(
model_name='countrytaggeditem', model_name="countrytaggeditem",
name='nb_version', name="nb_version",
field=models.PositiveIntegerField(default=0), field=models.PositiveIntegerField(default=0),
), ),
migrations.AddField( migrations.AddField(
model_name='fortestingversioning', model_name="fortestingversioning",
name='nb_version', name="nb_version",
field=models.PositiveIntegerField(default=0), field=models.PositiveIntegerField(default=0),
), ),
migrations.AddField( migrations.AddField(
model_name='universitydri', model_name="universitydri",
name='nb_version', name="nb_version",
field=models.PositiveIntegerField(default=0), field=models.PositiveIntegerField(default=0),
), ),
migrations.AddField( migrations.AddField(
model_name='universityinfo', model_name="universityinfo",
name='nb_version', name="nb_version",
field=models.PositiveIntegerField(default=0), field=models.PositiveIntegerField(default=0),
), ),
migrations.AddField( migrations.AddField(
model_name='universityscholarship', model_name="universityscholarship",
name='nb_version', name="nb_version",
field=models.PositiveIntegerField(default=0), field=models.PositiveIntegerField(default=0),
), ),
migrations.AddField( migrations.AddField(
model_name='universitysemestersdates', model_name="universitysemestersdates",
name='nb_version', name="nb_version",
field=models.PositiveIntegerField(default=0), field=models.PositiveIntegerField(default=0),
), ),
migrations.AddField( migrations.AddField(
model_name='universitytaggeditem', model_name="universitytaggeditem",
name='nb_version', name="nb_version",
field=models.PositiveIntegerField(default=0), field=models.PositiveIntegerField(default=0),
), ),
] ]
...@@ -5,69 +5,55 @@ from django.db import migrations ...@@ -5,69 +5,55 @@ from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [("backend_app", "0002_auto_20190310_1726")]
('backend_app', '0002_auto_20190310_1726'),
]
operations = [ operations = [
migrations.RenameField( migrations.RenameField(
model_name='campus', model_name="campus", old_name="nb_version", new_name="nb_versions"
old_name='nb_version',
new_name='nb_versions',
), ),
migrations.RenameField( migrations.RenameField(
model_name='campustaggeditem', model_name="campustaggeditem", old_name="nb_version", new_name="nb_versions"
old_name='nb_version',
new_name='nb_versions',
), ),
migrations.RenameField( migrations.RenameField(
model_name='citytaggeditem', model_name="citytaggeditem", old_name="nb_version", new_name="nb_versions"
old_name='nb_version',
new_name='nb_versions',
), ),
migrations.RenameField( migrations.RenameField(
model_name='countrydri', model_name="countrydri", old_name="nb_version", new_name="nb_versions"
old_name='nb_version',
new_name='nb_versions',
), ),
migrations.RenameField( migrations.RenameField(
model_name='countryscholarship', model_name="countryscholarship",
old_name='nb_version', old_name="nb_version",
new_name='nb_versions', new_name="nb_versions",
), ),
migrations.RenameField( migrations.RenameField(
model_name='countrytaggeditem', model_name="countrytaggeditem",
old_name='nb_version', old_name="nb_version",
new_name='nb_versions', new_name="nb_versions",
), ),
migrations.RenameField( migrations.RenameField(
model_name='fortestingversioning', model_name="fortestingversioning",
old_name='nb_version', old_name="nb_version",
new_name='nb_versions', new_name="nb_versions",
), ),
migrations.RenameField( migrations.RenameField(
model_name='universitydri', model_name="universitydri", old_name="nb_version", new_name="nb_versions"
old_name='nb_version',
new_name='nb_versions',
), ),
migrations.RenameField( migrations.RenameField(
model_name='universityinfo', model_name="universityinfo", old_name="nb_version", new_name="nb_versions"
old_name='nb_version',
new_name='nb_versions',
), ),
migrations.RenameField( migrations.RenameField(
model_name='universityscholarship', model_name="universityscholarship",
old_name='nb_version', old_name="nb_version",
new_name='nb_versions', new_name="nb_versions",
), ),
migrations.RenameField( migrations.RenameField(
model_name='universitysemestersdates', model_name="universitysemestersdates",
old_name='nb_version', old_name="nb_version",
new_name='nb_versions', new_name="nb_versions",
), ),
migrations.RenameField( migrations.RenameField(
model_name='universitytaggeditem', model_name="universitytaggeditem",
old_name='nb_version', old_name="nb_version",
new_name='nb_versions', new_name="nb_versions",
), ),
] ]
# Generated by Django 2.1.7 on 2019-03-10 16:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("backend_app", "0003_auto_20190310_1731")]
operations = [
migrations.AddField(
model_name="campus",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="campustaggeditem",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="city",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="citytaggeditem",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="country",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="countrydri",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="countryscholarship",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="countrytaggeditem",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="currency",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="department",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="fortestingmoderation",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="fortestingversioning",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="offer",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="previousdeparture",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="previousdeparturefeedback",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="recommendation",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="recommendationlist",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="specialty",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="tag",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="university",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="universitydri",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="universityinfo",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="universityscholarship",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="universitysemestersdates",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="universitytaggeditem",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="userdata",
name="has_pending_moderation",
field=models.BooleanField(default=False),
),
]
...@@ -48,6 +48,9 @@ class MyModel(models.Model): ...@@ -48,6 +48,9 @@ class MyModel(models.Model):
# Add the link to pending moderation # Add the link to pending moderation
pending_moderation = GenericRelation(PendingModeration) pending_moderation = GenericRelation(PendingModeration)
# A bit of optimization: we store if there is something pending moderation
has_pending_moderation = models.BooleanField(default=False)
class Meta: class Meta:
abstract = True abstract = True
......
...@@ -9,7 +9,7 @@ from rest_framework.validators import ValidationError ...@@ -9,7 +9,7 @@ from rest_framework.validators import ValidationError
from shared.obj_moderation_permission import DEFAULT_OBJ_MODERATION_LV from shared.obj_moderation_permission import DEFAULT_OBJ_MODERATION_LV
from .myModel import MyModel from .myModel import MyModel
from .pendingModeration import PendingModeration, PendingModerationSerializer from .pendingModeration import PendingModeration
CLEANED_MY_MODEL_DATA = { CLEANED_MY_MODEL_DATA = {
"moderated_by": None, "moderated_by": None,
...@@ -44,7 +44,7 @@ class MyModelSerializer(MySerializerWithJSON): ...@@ -44,7 +44,7 @@ class MyModelSerializer(MySerializerWithJSON):
moderated_by = serializers.CharField(read_only=True) moderated_by = serializers.CharField(read_only=True)
moderated_on = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True) moderated_on = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)
pending_moderation = serializers.SerializerMethodField() has_pending_moderation = serializers.BooleanField(read_only=True)
model_config = serializers.SerializerMethodField() model_config = serializers.SerializerMethodField()
# For easier handling on the client side, we force an id field # For easier handling on the client side, we force an id field
...@@ -59,27 +59,6 @@ class MyModelSerializer(MySerializerWithJSON): ...@@ -59,27 +59,6 @@ class MyModelSerializer(MySerializerWithJSON):
return self.Meta.model.model_config return self.Meta.model.model_config
# Optimization
# Class attribute to force the pending moderation to return the pending moderation data
# Or versionned element to return the number of versions
FORCE_FULL_DISPLAY = False
def get_pending_moderation(self, obj: MyModel):
"""
Serializer for the `pending_moderation` field
"""
# Optimization, in list mode, fetching all the pending moderation information is not optimal at all
if not self.FORCE_FULL_DISPLAY and self.context["view"].action == "list":
return None
else:
ct = ContentType.objects.get_for_model(self.Meta.model)
pending = PendingModeration.objects.filter(
content_type=ct, object_id=obj.pk
)
return PendingModerationSerializer(
pending, many=True, read_only=True, context=self.context
).data
def get_id(self, obj: MyModel): def get_id(self, obj: MyModel):
""" """
Serializer for the id field. Serializer for the id field.
...@@ -193,6 +172,10 @@ class MyModelSerializer(MySerializerWithJSON): ...@@ -193,6 +172,10 @@ class MyModelSerializer(MySerializerWithJSON):
"new_object": data_to_save, "new_object": data_to_save,
}, },
) )
# Performance optimization, we store the fact that there is an object pending moderation
self.instance.has_pending_moderation = True
self.instance.save()
return self.instance return self.instance
else: # Moderation is not needed, we need to check whether it's a moderation or an update with no moderation else: # Moderation is not needed, we need to check whether it's a moderation or an update with no moderation
...@@ -200,7 +183,7 @@ class MyModelSerializer(MySerializerWithJSON): ...@@ -200,7 +183,7 @@ class MyModelSerializer(MySerializerWithJSON):
moderated_and_updated = True moderated_and_updated = True
if self.instance is None: if self.instance is None:
self.set_model_attr_no_moder(user, moderated_and_updated) self.set_model_attr_no_moder(user, moderated_and_updated)
return super().save(*args, **kwargs) instance = super().save(*args, **kwargs)
else: else:
try: try:
pending_instance = PendingModeration.objects.get( pending_instance = PendingModeration.objects.get(
...@@ -226,4 +209,9 @@ class MyModelSerializer(MySerializerWithJSON): ...@@ -226,4 +209,9 @@ class MyModelSerializer(MySerializerWithJSON):
pass pass
self.set_model_attr_no_moder(user, moderated_and_updated) self.set_model_attr_no_moder(user, moderated_and_updated)
return super().save(*args, **kwargs) instance = super().save(*args, **kwargs)
# Performance optimization to know if has pending moderation
instance.has_pending_moderation = False
instance.save()
return instance
...@@ -40,6 +40,4 @@ class MyModelViewSet(viewsets.ModelViewSet): ...@@ -40,6 +40,4 @@ class MyModelViewSet(viewsets.ModelViewSet):
Extended default rest framework behavior Extended default rest framework behavior
to prefetch some table and enhance performances to prefetch some table and enhance performances
""" """
return self.queryset.prefetch_related( return self.queryset.prefetch_related("moderated_by", "updated_by")
"moderated_by", "updated_by", "pending_moderation"
)
...@@ -53,8 +53,6 @@ class ScholarshipSerializer(BasicModuleSerializer): ...@@ -53,8 +53,6 @@ class ScholarshipSerializer(BasicModuleSerializer):
Serializer for the scholarship class Serializer for the scholarship class
""" """
FORCE_FULL_DISPLAY = True
def validate(self, attrs): def validate(self, attrs):
""" """
Custom attribute validation Custom attribute validation
......
...@@ -27,8 +27,6 @@ class TaggedItemSerializer(BasicModuleSerializer): ...@@ -27,8 +27,6 @@ class TaggedItemSerializer(BasicModuleSerializer):
Serializer for tagged items Serializer for tagged items
""" """
FORCE_FULL_DISPLAY = True
def validate(self, attrs): def validate(self, attrs):
attrs = super().validate(attrs) attrs = super().validate(attrs)
......
...@@ -18,8 +18,6 @@ class CountryDri(BasicModule): ...@@ -18,8 +18,6 @@ class CountryDri(BasicModule):
class CountryDriSerializer(BasicModuleSerializer): class CountryDriSerializer(BasicModuleSerializer):
FORCE_FULL_DISPLAY = True
class Meta: class Meta:
model = CountryDri model = CountryDri
fields = "__all__" fields = "__all__"
......
...@@ -18,8 +18,6 @@ class UniversityDri(BasicModule): ...@@ -18,8 +18,6 @@ class UniversityDri(BasicModule):
class UniversityDriSerializer(BasicModuleSerializer): class UniversityDriSerializer(BasicModuleSerializer):
FORCE_FULL_DISPLAY = True
class Meta: class Meta:
model = UniversityDri model = UniversityDri
fields = "__all__" fields = "__all__"
......
...@@ -20,8 +20,6 @@ class UniversityScholarship(Scholarship): ...@@ -20,8 +20,6 @@ class UniversityScholarship(Scholarship):
class UniversityScholarshipSerializer(ScholarshipSerializer): class UniversityScholarshipSerializer(ScholarshipSerializer):
FORCE_FULL_DISPLAY = True
class Meta: class Meta:
model = UniversityScholarship model = UniversityScholarship
fields = "__all__" fields = "__all__"
......
...@@ -63,6 +63,9 @@ class ModerationTestCase(WithUserTestCase): ...@@ -63,6 +63,9 @@ class ModerationTestCase(WithUserTestCase):
self._test_val_null(instance.updated_on, null) self._test_val_null(instance.updated_on, null)
self._test_val_null(instance.updated_by, null) self._test_val_null(instance.updated_by, null)
def _test_has_pending_moderation_val(self, instance, has: bool):
self.assertEqual(instance.has_pending_moderation, has)
def _test_new_obj_val(self, instance, data): def _test_new_obj_val(self, instance, data):
self.assertEqual(instance.new_object["aaa"], data["aaa"]) self.assertEqual(instance.new_object["aaa"], data["aaa"])
...@@ -84,6 +87,7 @@ class ModerationTestCase(WithUserTestCase): ...@@ -84,6 +87,7 @@ class ModerationTestCase(WithUserTestCase):
self._test_updated_val(instance, null=True) self._test_updated_val(instance, null=True)
self._test_moderated_val(instance, null=True) self._test_moderated_val(instance, null=True)
self._test_has_pending_moderation_val(instance, True)
instance_in_moderation = self._test_retreive_instance_in_moderation(instance) instance_in_moderation = self._test_retreive_instance_in_moderation(instance)
self._test_updated_val(instance_in_moderation, null=False) self._test_updated_val(instance_in_moderation, null=False)
...@@ -97,6 +101,7 @@ class ModerationTestCase(WithUserTestCase): ...@@ -97,6 +101,7 @@ class ModerationTestCase(WithUserTestCase):
self._test_updated_val(instance, null=True) self._test_updated_val(instance, null=True)
self._test_moderated_val(instance, null=True) self._test_moderated_val(instance, null=True)
self._test_has_pending_moderation_val(instance, True)
instance_in_moderation = self._test_retreive_instance_in_moderation(instance) instance_in_moderation = self._test_retreive_instance_in_moderation(instance)
self._test_updated_val(instance_in_moderation, null=False) self._test_updated_val(instance_in_moderation, null=False)
...@@ -118,6 +123,7 @@ class ModerationTestCase(WithUserTestCase): ...@@ -118,6 +123,7 @@ class ModerationTestCase(WithUserTestCase):
instance_in_moderation = self._test_retreive_instance_in_moderation( instance_in_moderation = self._test_retreive_instance_in_moderation(
instance, True instance, True
) )
self._test_has_pending_moderation_val(instance, False)
# Phase 4 # Phase 4
# Put that require moderation # Put that require moderation
...@@ -127,6 +133,7 @@ class ModerationTestCase(WithUserTestCase): ...@@ -127,6 +133,7 @@ class ModerationTestCase(WithUserTestCase):
self._test_updated_val(instance, null=False) # Not True self._test_updated_val(instance, null=False) # Not True
self._test_moderated_val(instance, null=False) # Not True self._test_moderated_val(instance, null=False) # Not True
self._test_has_pending_moderation_val(instance, True)
instance_in_moderation = self._test_retreive_instance_in_moderation(instance) instance_in_moderation = self._test_retreive_instance_in_moderation(instance)
self._test_updated_val(instance_in_moderation, null=False) self._test_updated_val(instance_in_moderation, null=False)
...@@ -147,6 +154,7 @@ class ModerationTestCase(WithUserTestCase): ...@@ -147,6 +154,7 @@ class ModerationTestCase(WithUserTestCase):
instance_in_moderation = self._test_retreive_instance_in_moderation( instance_in_moderation = self._test_retreive_instance_in_moderation(
instance, True instance, True
) )
self._test_has_pending_moderation_val(instance, False)
#### ####
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment