Commit 7db3e41d authored by Florent Chehab's avatar Florent Chehab
Browse files

Merge branch 'feature_moderation' into 'frontend'

Feature moderation

See merge request chehabfl/outgoing_rex!13
parents f1c99e79 1a6bb9ab
from django.db import models
from backend.models.module import BasicModule
from backend.models.module import BasicModule, BasicModuleSerializer, BasicModuleViewSet
from backend.models.location import City
from rest_framework import viewsets, permissions
from backend.models.module import BasicModuleSerializer
####################
......@@ -20,8 +18,8 @@ class CityTransportSerializer(BasicModuleSerializer):
fields = '__all__'
class CityTransportViewSet(viewsets.ModelViewSet): # TODO switch to dict
permission_classes = (permissions.DjangoModelPermissions,)
class CityTransportViewSet(BasicModuleViewSet):
queryset = CityTransport.objects.all() # pylint: disable=E1101
serializer_class = CityTransportSerializer
......@@ -45,8 +43,8 @@ class CityTourismSerializer(BasicModuleSerializer):
fields = '__all__'
class CityTourismViewSet(viewsets.ModelViewSet): # TODO switch to dict
permission_classes = (permissions.DjangoModelPermissions,)
class CityTourismViewSet(BasicModuleViewSet):
queryset = CityTourism.objects.all() # pylint: disable=E1101
serializer_class = CityTourismSerializer
......@@ -70,8 +68,7 @@ class CityOtherStuffSerializer(BasicModuleSerializer):
fields = '__all__'
# TODO switch to dict
class CityOtherStuffViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.DjangoModelPermissions,)
class CityOtherStuffViewSet(BasicModuleViewSet):
queryset = CityOtherStuff.objects.all() # pylint: disable=E1101
serializer_class = CityOtherStuffSerializer
from django.db import models
from backend.models.location import City
from backend.models.module import VersionnedModuleSerializer
from backend.models.module import Photo
from rest_framework import viewsets, permissions
from backend.models.module import Photo, PhotoSerializer, PhotoViewSet
class CityPhoto(Photo):
......@@ -16,14 +14,13 @@ class CityPhoto(Photo):
unique_together = ('city', 'photo')
class CityPhotoSerializer(VersionnedModuleSerializer):
class CityPhotoSerializer(PhotoSerializer):
class Meta:
model = CityPhoto
fields = '__all__'
class CityPhotoViewSet(viewsets.ModelViewSet): # TODO switch to dict
permission_classes = (permissions.DjangoModelPermissions,)
class CityPhotoViewSet(PhotoViewSet):
queryset = CityPhoto.objects.all() # pylint: disable=E1101
serializer_class = CityPhotoSerializer
from django.db import models
from rest_framework import serializers, permissions
from backend.models.tools import DictModeViewSet
from backend.models.my_model import MyModel, MyModelSerializer, MyModelVersionnedViewSet
# Data model based on : https://unstats.un.org/unsd/methodology/m49/overview/
class Country(models.Model):
class Country(MyModel):
name = models.CharField(max_length=200)
iso_alpha2_code = models.CharField(primary_key=True, max_length=2)
iso_alpha3_code = models.CharField(
......@@ -20,19 +19,13 @@ class Country(models.Model):
max_length=3, null=True, blank=True)
"""
API RELATED STUFF BELLOW
"""
class CountrySerializer(serializers.ModelSerializer):
class CountrySerializer(MyModelSerializer):
class Meta:
model = Country
fields = '__all__'
class CountryViewSet(DictModeViewSet):
permission_classes = (permissions.DjangoModelPermissions,)
class CountryViewSet(MyModelVersionnedViewSet):
queryset = Country.objects.all() # pylint: disable=E1101
serializer_class = CountrySerializer
from django.db import models
from backend.models.module import BasicModule
from backend.models.module import BasicModule, BasicModuleSerializer, BasicModuleViewSet
from backend.models.location import Country
from rest_framework import viewsets, permissions
from backend.models.module import BasicModuleSerializer
####################
......@@ -20,9 +18,8 @@ class CountryVisaAdministrativeSerializer(BasicModuleSerializer):
fields = '__all__'
# TODO switch to dict
class CountryVisaAdministrativeViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.DjangoModelPermissions,)
class CountryVisaAdministrativeViewSet(BasicModuleViewSet):
queryset = CountryVisaAdministrative.objects.all() # pylint: disable=E1101
serializer_class = CountryVisaAdministrativeSerializer
......@@ -47,9 +44,8 @@ class CountryHealthInsuranceSerializer(BasicModuleSerializer):
fields = '__all__'
# TODO switch to dict
class CountryHealthInsuranceViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.DjangoModelPermissions,)
class CountryHealthInsuranceViewSet(BasicModuleViewSet):
queryset = CountryHealthInsurance.objects.all() # pylint: disable=E1101
serializer_class = CountryHealthInsuranceSerializer
......@@ -73,9 +69,8 @@ class CountryOtherInsuranceSerializer(BasicModuleSerializer):
fields = '__all__'
# TODO switch to dict
class CountryOtherInsuranceViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.DjangoModelPermissions,)
class CountryOtherInsuranceViewSet(BasicModuleViewSet):
queryset = CountryOtherInsurance.objects.all() # pylint: disable=E1101
serializer_class = CountryOtherInsuranceSerializer
......@@ -98,8 +93,8 @@ class CountryCultureSerializer(BasicModuleSerializer):
fields = '__all__'
class CountryCultureViewSet(viewsets.ModelViewSet): # TODO switch to dict
permission_classes = (permissions.DjangoModelPermissions,)
class CountryCultureViewSet(BasicModuleViewSet):
queryset = CountryCulture.objects.all() # pylint: disable=E1101
serializer_class = CountryCultureSerializer
......@@ -122,8 +117,8 @@ class CountryTransportSerializer(BasicModuleSerializer):
fields = '__all__'
class CountryTransportViewSet(viewsets.ModelViewSet): # TODO switch to dict
permission_classes = (permissions.DjangoModelPermissions,)
class CountryTransportViewSet(BasicModuleViewSet):
queryset = CountryTransport.objects.all() # pylint: disable=E1101
serializer_class = CountryTransportSerializer
......@@ -147,8 +142,8 @@ class CountryTourismSerializer(BasicModuleSerializer):
fields = '__all__'
class CountryTourismViewSet(viewsets.ModelViewSet): # TODO switch to dict
permission_classes = (permissions.DjangoModelPermissions,)
class CountryTourismViewSet(BasicModuleViewSet):
queryset = CountryTourism.objects.all() # pylint: disable=E1101
serializer_class = CountryTourismSerializer
......@@ -172,8 +167,7 @@ class CountryOtherStuffSerializer(BasicModuleSerializer):
fields = '__all__'
# TODO switch to dict
class CountryOtherStuffViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.DjangoModelPermissions,)
class CountryOtherStuffViewSet(BasicModuleViewSet):
queryset = CountryOtherStuff.objects.all() # pylint: disable=E1101
serializer_class = CountryOtherStuffSerializer
from django.db import models
from backend.models.location import Country
from backend.models.module import DriRestrictedModule, DriRestrictedModuleSerializer
from rest_framework import viewsets, permissions
from backend.models.module import DriRestrictedModule, DriRestrictedModuleSerializer, DriRestrictedModuleViewSet
class CountryDri(DriRestrictedModule):
......@@ -16,7 +15,6 @@ class CountryDriSerializer(DriRestrictedModuleSerializer):
fields = '__all__'
class CountryDriViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.DjangoModelPermissions,)
class CountryDriViewSet(DriRestrictedModuleViewSet):
queryset = CountryDri.objects.all() # pylint: disable=E1101
serializer_class = CountryDriSerializer
from django.db import models
from backend.models.location import Country
from backend.models.module import VersionnedModuleSerializer
from backend.models.module import Photo
from rest_framework import viewsets, permissions
from backend.models.module import Photo, PhotoSerializer, PhotoViewSet
class CountryPhoto(Photo):
......@@ -16,14 +14,13 @@ class CountryPhoto(Photo):
unique_together = ('country', 'photo')
class CountryPhotoSerializer(VersionnedModuleSerializer):
class CountryPhotoSerializer(PhotoSerializer):
class Meta:
model = CountryPhoto
fields = '__all__'
class CountryPhotoViewSet(viewsets.ModelViewSet): # TODO switch to dict
permission_classes = (permissions.DjangoModelPermissions,)
class CountryPhotoViewSet(PhotoViewSet):
queryset = CountryPhoto.objects.all() # pylint: disable=E1101
serializer_class = CountryPhotoSerializer
from django.db import models
from backend.models.location import Country
from backend.models.module import Scholarship, BasicModuleSerializer
from rest_framework import viewsets, permissions
from backend.models.module import Scholarship, ScholarshipSerializer, ScholarshipViewSet
class CountryScholarship(Scholarship):
......@@ -9,14 +8,13 @@ class CountryScholarship(Scholarship):
Country, related_name="country_scholarhip")
class CountryScholarshipSerializer(BasicModuleSerializer):
class CountryScholarshipSerializer(ScholarshipSerializer):
class Meta:
model = CountryScholarship
fields = '__all__'
class CountryScholarshipViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.DjangoModelPermissions,)
class CountryScholarshipViewSet(ScholarshipViewSet):
queryset = CountryScholarship.objects.all() # pylint: disable=E1101
serializer_class = CountryScholarshipSerializer
from .versionnedModule import VersionnedModule, VersionnedModuleSerializer # noqa: F401
from .basicModule import BasicModule, BasicModuleSerializer # noqa: F401
from .scholarship import Scholarship # noqa: F401
from .photo import Photo # noqa: F401
from .driRestrictedModule import DriRestrictedModule, DriRestrictedModuleSerializer # noqa: F401
from .basicModule import BasicModule, BasicModuleSerializer, BasicModuleViewSet # noqa: F401
from .scholarship import Scholarship, ScholarshipSerializer, ScholarshipViewSet # noqa: F401
from .photo import Photo, PhotoSerializer, PhotoViewSet # noqa: F401
from .driRestrictedModule import DriRestrictedModule, DriRestrictedModuleSerializer, DriRestrictedModuleViewSet # noqa: F401
from .currency import Currency, CurrencyViewSet, CurrencySerializer # noqa: F401
# MyModelVersionned, MyModelVersionnedSerializer # noqa: F401
from django.db import models
from backend.models.tools import UsefullLinksField
from backend.models.module import VersionnedModule, VersionnedModuleSerializer
from backend.models.my_model import MyModelVersionned, MyModelVersionnedSerializer, MyModelVersionnedViewSet
class BasicModule(VersionnedModule):
class BasicModule(MyModelVersionned):
comment = models.TextField(blank=True)
usefull_links = UsefullLinksField(blank=True)
......@@ -12,8 +12,12 @@ class BasicModule(VersionnedModule):
abstract = True
class BasicModuleSerializer(VersionnedModuleSerializer):
class BasicModuleSerializer(MyModelVersionnedSerializer):
class Meta:
model = BasicModule
fields = '__all__'
class BasicModuleViewSet(MyModelVersionnedViewSet):
serializer_class = BasicModuleSerializer
from django.db import models
from rest_framework import serializers, viewsets, permissions
from rest_framework import permissions
from django.core.validators import MinValueValidator
from backend.models.my_model import MyModel, MyModelSerializer, MyModelViewSet
class Currency(models.Model):
class Currency(MyModel):
code = models.CharField(primary_key=True, max_length=15)
name = models.CharField(max_length=100)
symbol = models.CharField(max_length=5)
......@@ -14,13 +15,13 @@ class Currency(models.Model):
)
class CurrencySerializer(serializers.ModelSerializer):
class CurrencySerializer(MyModelSerializer):
class Meta:
model = Currency
fields = '__all__'
class CurrencyViewSet(viewsets.ModelViewSet):
permission_classes = (permissions.IsAdminUser,)
class CurrencyViewSet(MyModelViewSet):
permission_classes = (permissions.IsAdminUser,) # TODO : change
queryset = Currency.objects.all() # pylint: disable=E1101
serializer_class = CurrencySerializer
from backend.models.module import BasicModule, BasicModuleSerializer
from backend.models.module import BasicModule, BasicModuleSerializer, BasicModuleViewSet
class DriRestrictedModule(BasicModule):
......@@ -8,5 +8,9 @@ class DriRestrictedModule(BasicModule):
class DriRestrictedModuleSerializer(BasicModuleSerializer):
# TODO Check edit restrictions
pass
class Meta:
model = DriRestrictedModule
class DriRestrictedModuleViewSet(BasicModuleViewSet):
serializer_class = DriRestrictedModuleSerializer
from django.db import models
from backend.models.module import VersionnedModule
from backend.models.my_model import MyModelVersionned, MyModelVersionnedSerializer, MyModelVersionnedViewSet
from backend.utils.friendly_path import friendly_path
path_and_rename = friendly_path("uploads/universities/photos/", 'title')
class Photo(VersionnedModule):
class Photo(MyModelVersionned):
photo = models.ImageField(upload_to=path_and_rename, max_length=250,
default='path/to/my/default/image.jpg') # TODO CHANGE !
......@@ -15,3 +15,14 @@ class Photo(VersionnedModule):
class Meta:
abstract = True
class PhotoSerializer(MyModelVersionnedSerializer):
class Meta:
model = Photo
fields = '__all__'
class PhotoViewSet(MyModelVersionnedViewSet):
serializer_class = PhotoSerializer
from django.db import models
from backend.models.module import BasicModule
from backend.models.module import BasicModule, BasicModuleSerializer, BasicModuleViewSet
from .currency import Currency
from rest_framework import serializers
from django.core.validators import MinValueValidator
......@@ -34,3 +34,14 @@ class Scholarship(BasicModule):
class Meta:
abstract = True
class ScholarshipSerializer(BasicModuleSerializer):
class Meta:
model = Scholarship
fields = '__all__'
class ScholarshipViewSet(BasicModuleViewSet):
serializer_class = ScholarshipSerializer
from .myModel import MyModel # noqa: F401
from .myModelSerializer import MyModelSerializer # noqa: F401
from .myModelViewSet import MyModelViewSet # noqa: F401
from .pendingModeration import PendingModeration, PendingModerationSerializer, PendingModerationViewSet # noqa: F401
from .forTestingModeration import ForTestingModeration, ForTestingModerationSerializer, ForTestingModerationViewSet # noqa: F401
from .myModelVersionned import MyModelVersionned, MyModelVersionnedSerializer, MyModelVersionnedViewSet # noqa: F401
from .forTestingVersionning import ForTestingVersionning, ForTestingVersionningSerializer, ForTestingVersionningViewSet # noqa: F401
from .myModel import MyModel
from .myModelSerializer import MyModelSerializer
from .myModelViewSet import MyModelViewSet
from django.db import models
class ForTestingModeration(MyModel):
"""
Simple model for testing purposes
"""
aaa = models.CharField(max_length=100)
class ForTestingModerationSerializer(MyModelSerializer):
"""
Same as above
"""
class Meta:
model = ForTestingModeration
fields = '__all__'
class ForTestingModerationViewSet(MyModelViewSet):
"""
Same as above
"""
serializer_class = ForTestingModerationSerializer
queryset = ForTestingModeration.objects.all()
from .myModelVersionned import MyModelVersionned, MyModelVersionnedSerializer, MyModelVersionnedViewSet
from django.db import models
import reversion
@reversion.register()
class ForTestingVersionning(MyModelVersionned):
"""
Simple model for testing purposes
"""
bbb = models.CharField(max_length=100)
class ForTestingVersionningSerializer(MyModelVersionnedSerializer):
"""
Same as above
"""
class Meta:
model = ForTestingVersionning
fields = '__all__'
class ForTestingVersionningViewSet(MyModelVersionnedViewSet):
"""
Same as above
"""
serializer_class = ForTestingVersionningSerializer
queryset = ForTestingVersionning.objects.all()
from django.db import models
from django.contrib.auth.models import User
class MyModel(models.Model):
"""
All models in the app deppend of this one.
It contains the required attributes for managing eventual moderation data.
All the logic behind moderation is done in myModelSerializer
"""
moderated_by = models.ForeignKey(
User, null=True, on_delete=models.SET_NULL, related_name='+')
moderated_on = models.DateTimeField(null=True)
updated_on = models.DateTimeField(null=True)
updated_by = models.ForeignKey(
User, null=True, on_delete=models.SET_NULL, related_name='+')
class Meta:
abstract = True
from rest_framework import serializers
from django.utils import timezone
from .pendingModeration import PendingModeration
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from backend.utils import is_member
from .myModel import MyModel
class MyModelSerializer(serializers.ModelSerializer):
moderated_on = serializers.DateTimeField(
format="%Y-%m-%d %H:%M:%S", read_only=True)
updated_on = serializers.DateTimeField(
format="%Y-%m-%d %H:%M:%S", read_only=True)
moderated_by = serializers.CharField(read_only=True)
updated_by = serializers.CharField(read_only=True)
# TODO : updated_by_username useless ? See in rest API
updated_by_username = serializers.SerializerMethodField(read_only=True)
def get_updated_by_username(self, obj):
if obj.updated_by:
return obj.updated_by.username
else:
return None
class Meta:
model = MyModel
def moderation_required(self):
user = self.get_user_in_request()
request = self.context['request']
if user.is_staff:
return False
if settings.MODERATION_ACTIVATED:
if request.method in ['POST', 'PUT']: # should be always the case
return not is_member('Moderators', request.user)
return False
def get_user_in_request(self):
return self.context['request'].user
def set_model_attr_no_moder(self, moderated_and_updated):
user = self.get_user_in_request()
now = timezone.now()
self.validated_data['moderated_by'] = user
self.validated_data['moderated_on'] = now
if moderated_and_updated:
self.validated_data['updated_by'] = user
self.validated_data['updated_on'] = now
def clean_validated_data(self):
self.validated_data['moderated_by'] = None
self.validated_data['moderated_on'] = None
self.validated_data['updated_by'] = None
self.validated_data['updated_on'] = None
def get_pending_models(self):
ct = ContentType.objects.get_for_model(self.Meta.model)
return PendingModeration.objects.filter(
content_type=ct, object_id=self.instance.pk)
def save(self, **kwargs):
user = self.get_user_in_request()
self.clean_validated_data()
if self.moderation_required():
if self.instance is None: # we need to create the main model
self.instance = super(
MyModelSerializer, self).save(**kwargs)
objs_pending_db = self.get_pending_models()
self.clean_validated_data() # Make that it is done...
if len(objs_pending_db) > 0:
pending_instance = objs_pending_db[0]
pending_instance.updated_on = timezone.now()
pending_instance.updated_by = user
pending_instance.new_object = self.validated_data
else:
pending_instance = PendingModeration(
referenced_object=self.instance,
updated_by=user,
updated_on=timezone.now(),
new_object=self.validated_data
)
pending_instance.save()
return self.instance
else:
moderated_and_updated = True
if self.instance is None:
self.set_model_attr_no_moder(moderated_and_updated)
return super(MyModelSerializer, self).save(**kwargs)
else:
# We check if we don't have any moderation pending
objs_pending_db = self.get_pending_models()
if len(objs_pending_db) > 0:
obj_pending_db = objs_pending_db[0]
self.clean_validated_data() # Make that it is done...
if obj_pending_db.new_object == self.validated_data:
moderated_and_updated = False
self.validated_data['updated_by'] = obj_pending_db.updated_by
self.validated_data['updated_on'] = obj_pending_db.updated_on
objs_pending_db.delete()
self.set_model_attr_no_moder(moderated_and_updated)