diff --git a/rex/admin.py b/rex/admin.py index ef8252ecc2efe313e4ca1a6c396f96255de7c4b7..eafb14abf6a31ff5ddd48392754191ad80fa7009 100644 --- a/rex/admin.py +++ b/rex/admin.py @@ -4,9 +4,11 @@ from reversion_compare.admin import CompareVersionAdmin from rex.models.university import University, MainCampus from rex.models.location import Country, City +from rex.models.module import BasicModule admin.site.register(Country) admin.site.register(City) +admin.site.register(BasicModule) admin.site.register(University, CompareVersionAdmin) admin.site.register(MainCampus, CompareVersionAdmin) diff --git a/rex/migrations/0001_initial.py b/rex/migrations/0001_initial.py index 687d4a9c5f2406a65feba474e7ed59abf59132e7..ce98ac5dd887846aa0e78bdec8f35508000545f7 100644 --- a/rex/migrations/0001_initial.py +++ b/rex/migrations/0001_initial.py @@ -1,8 +1,9 @@ -# Generated by Django 2.0.3 on 2018-08-18 08:44 +# Generated by Django 2.0.3 on 2018-08-19 11:49 import django.core.validators from django.db import migrations, models import django.db.models.deletion +import rex.models.tools.usefullLinksField import rex.utils.friendly_path @@ -14,6 +15,14 @@ class Migration(migrations.Migration): ] operations = [ + migrations.CreateModel( + name='BasicModule', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('comment', models.TextField()), + ('usefull_links', rex.models.tools.usefullLinksField.UsefullLinksField(validators=[rex.models.tools.usefullLinksField.validate_usefull_links])), + ], + ), migrations.CreateModel( name='City', fields=[ diff --git a/rex/models/module/__init__.py b/rex/models/module/__init__.py index 3b0b8597cf752570f4cbe9837ebc781a6f4d6f66..caa63724ed9cef0a626fbc65aa5d84bd720e4275 100644 --- a/rex/models/module/__init__.py +++ b/rex/models/module/__init__.py @@ -1 +1,2 @@ from .module import Module # noqa: F401 +from .basicModule import BasicModule # noqa: F401 diff --git a/rex/models/module/basicModule.py b/rex/models/module/basicModule.py new file mode 100644 index 0000000000000000000000000000000000000000..241677660706b0935ff9e17a9a159a26549146b2 --- /dev/null +++ b/rex/models/module/basicModule.py @@ -0,0 +1,11 @@ +from django.db import models +from rex.models.tools import UsefullLinksField + + +class BasicModule(models.Model): + + comment = models.TextField() + usefull_links = UsefullLinksField() + + # class Meta: + # abstract = True diff --git a/rex/models/tools/__init__.py b/rex/models/tools/__init__.py index da1a08ceaa94eabae324c5a9ce90faa4dfbfa39a..a666aa722a1d016d3d00efa2ce67de04b7f31aea 100644 --- a/rex/models/tools/__init__.py +++ b/rex/models/tools/__init__.py @@ -1 +1,3 @@ from .DictModeViewSet import DictModeViewSet # noqa: F401 +from .usefullLinksField import UsefullLinksField # noqa: F401 +from .validateWithRestFramework import validate_with_rest_framework # noqa: F401 diff --git a/rex/models/tools/usefullLinksField.py b/rex/models/tools/usefullLinksField.py new file mode 100644 index 0000000000000000000000000000000000000000..f12cc805c7a27fc183c1e8d4eb4a89681cca828d --- /dev/null +++ b/rex/models/tools/usefullLinksField.py @@ -0,0 +1,35 @@ +from django.contrib.postgres.fields import JSONField +from django.core.exceptions import ValidationError + +from rest_framework import serializers +from rex.models.tools.validateWithRestFramework import validate_with_rest_framework + + +class UrlAndDescriptionSerializer(serializers.Serializer): + """ + Simple serialize used to validate each usefull links objs + """ + url = serializers.URLField(required=True) + description = serializers.CharField( + required=False, allow_null=True, allow_blank=True) + + +def validate_usefull_links(value): + """ + Function validate the data that should be stored + in a usefull_links field + """ + + if type(value) is not list: + raise ValidationError("Usefull links must be a JSON array !") + + for obj in value: + validate_with_rest_framework(UrlAndDescriptionSerializer, obj) + + +class UsefullLinksField(JSONField): + description = "A field to store a URL and a description as single JSON data" + + def __init__(self, *args, **kwargs): + kwargs['validators'] = [validate_usefull_links] + super(UsefullLinksField, self).__init__(*args, **kwargs) diff --git a/rex/models/tools/validateWithRestFramework.py b/rex/models/tools/validateWithRestFramework.py new file mode 100644 index 0000000000000000000000000000000000000000..c7bb8f057fecc8627dd9fe6381be8321ab55393d --- /dev/null +++ b/rex/models/tools/validateWithRestFramework.py @@ -0,0 +1,20 @@ +from django.core.exceptions import ValidationError + + +def validate_with_rest_framework(serializer, value): + """ + Function to validate some data (comming from JSON) + against a serializer. + TODO add test for this... + """ + + valid_ser = serializer(data=value) + if not valid_ser.is_valid(): + raise ValidationError(str(valid_ser.errors)) + + # Also checks that no extra fields were added + if type(value) is not list: + allowed_keys = list(valid_ser.get_fields()) + for key in value.keys(): + if key not in allowed_keys: + raise ValidationError("Expected JSON schema not respected")