Commit 4553b543 authored by Florent Chehab's avatar Florent Chehab

updated tagged item ineritance

usefull links validation using custom validation
parent b75e4657
Pipeline #26803 passed with stages
in 2 minutes and 2 seconds
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
"name": "photos", "name": "photos",
"config": { "config": {
"photos": { "photos": {
"type": "list", "type": "array",
"content": { "content": {
"url": { "url": {
"type": "url", "type": "url",
......
This diff is collapsed.
# Generated by Django 2.0.3 on 2018-08-30 14:23
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('backend', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='countrytaggeditem',
name='country',
field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, primary_key=True, related_name='country_items', serialize=False, to='backend.Country'),
),
]
# Generated by Django 2.0.3 on 2018-08-30 20:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('backend', '0002_auto_20180830_1623'),
]
operations = [
migrations.AlterUniqueTogether(
name='cityphoto',
unique_together=set(),
),
migrations.RemoveField(
model_name='cityphoto',
name='city',
),
migrations.RemoveField(
model_name='cityphoto',
name='moderated_by',
),
migrations.RemoveField(
model_name='cityphoto',
name='updated_by',
),
migrations.AlterUniqueTogether(
name='countryphoto',
unique_together=set(),
),
migrations.RemoveField(
model_name='countryphoto',
name='country',
),
migrations.RemoveField(
model_name='countryphoto',
name='moderated_by',
),
migrations.RemoveField(
model_name='countryphoto',
name='updated_by',
),
migrations.AlterUniqueTogether(
name='universityphoto',
unique_together=set(),
),
migrations.RemoveField(
model_name='universityphoto',
name='moderated_by',
),
migrations.RemoveField(
model_name='universityphoto',
name='university',
),
migrations.RemoveField(
model_name='universityphoto',
name='updated_by',
),
migrations.AlterField(
model_name='tag',
name='name',
field=models.CharField(max_length=100, unique=True),
),
migrations.DeleteModel(
name='CityPhoto',
),
migrations.DeleteModel(
name='CountryPhoto',
),
migrations.DeleteModel(
name='UniversityPhoto',
),
]
from django.db import models from django.db import models
from backend.models.tools import UsefullLinksField
from backend.models.my_model import MyModelVersionned, MyModelVersionnedSerializer, MyModelVersionnedViewSet from backend.models.my_model import MyModelVersionned, MyModelVersionnedSerializer, MyModelVersionnedViewSet
from django.contrib.postgres.fields import JSONField from django.contrib.postgres.fields import JSONField
from backend.models.tag.tagged_item_validation import validate_content_against_config
USEFULL_LINKS_CONFIG = {
"usefull_links": {
"type": "array",
"content": {
"url": {
"type": "url",
"required": True,
"validators": {}
},
"description": {
"type": "text",
"required": True,
"validators": {
"max_length": 500
}
}
},
"required": True
}
}
class BasicModule(MyModelVersionned): class BasicModule(MyModelVersionned):
comment = models.TextField(blank=True) comment = models.TextField(blank=True)
usefull_links = UsefullLinksField(blank=True, default=list) usefull_links = JSONField(blank=True, default=list)
custom_content = JSONField(blank=True, default=dict)
class Meta: class Meta:
abstract = True abstract = True
...@@ -16,6 +36,12 @@ class BasicModule(MyModelVersionned): ...@@ -16,6 +36,12 @@ class BasicModule(MyModelVersionned):
class BasicModuleSerializer(MyModelVersionnedSerializer): class BasicModuleSerializer(MyModelVersionnedSerializer):
def validate(self, attrs):
content = {'usefull_links': attrs['usefull_links']}
config = USEFULL_LINKS_CONFIG
validate_content_against_config(config, content)
return attrs
class Meta: class Meta:
model = BasicModule model = BasicModule
fields = '__all__' fields = '__all__'
......
from .tag import Tag, TagSerializer, TagViewSet # noqa: F401 from .tag import Tag, TagSerializer, TagViewSet # noqa: F401
from .taggedItem import TaggedItem, TaggedItemSerializer, TaggedItemViewSet # noqa: F401 from .taggedItem import TaggedItem, TaggedItemSerializer, TaggedItemViewSet # noqa: F401
from .tagged_item_validation import validate_content_against_config # noqa: F401
from django.db import models from django.db import models
from backend.models.module import BasicModule, BasicModuleSerializer, BasicModuleViewSet from backend.models.my_model import MyModelVersionned, MyModelVersionnedSerializer, MyModelVersionnedViewSet
from .tag import Tag from .tag import Tag
from .tagged_item_validation import tagged_item_validation from .tagged_item_validation import tagged_item_validation
class TaggedItem(BasicModule): class TaggedItem(MyModelVersionned):
tag = models.ForeignKey(Tag, related_name='+', on_delete=models.PROTECT) tag = models.ForeignKey(Tag, related_name='+', on_delete=models.PROTECT)
class Meta: class Meta:
abstract = True abstract = True
class TaggedItemSerializer(BasicModuleSerializer): class TaggedItemSerializer(MyModelVersionnedSerializer):
def validate(self, attrs): def validate(self, attrs):
tagged_item_validation(attrs) tagged_item_validation(attrs)
return attrs return attrs
class TaggedItemViewSet(BasicModuleViewSet): class TaggedItemViewSet(MyModelVersionnedViewSet):
def extend_queryset(self): def extend_queryset(self):
return self.mymodel_queryset.prefetch_related('tag') return self.mymodel_queryset.prefetch_related('tag')
...@@ -25,9 +25,9 @@ def validate_content_against_config(config, content): ...@@ -25,9 +25,9 @@ def validate_content_against_config(config, content):
validate_url(field_config, field_submitted) validate_url(field_config, field_submitted)
elif field_type == 'text': elif field_type == 'text':
validate_text(field_config, field_submitted) validate_text(field_config, field_submitted)
elif field_type == 'list': elif field_type == 'array':
if type(field_submitted) is not list: if type(field_submitted) is not list:
raise ValidationError("A list is required here !") raise ValidationError("A array is required here !")
for item in field_submitted: for item in field_submitted:
validate_content_against_config(field_config['content'], item) validate_content_against_config(field_config['content'], item)
else: else:
......
from .DictModeViewSet import DictModeViewSet # noqa: F401 from .DictModeViewSet import DictModeViewSet # noqa: F401
from .usefullLinksField import UsefullLinksField # noqa: F401
from .validateWithRestFramework import validate_with_rest_framework # noqa: F401
from .noDeleteIfNotAdmin import NoDeleteIfNotAdmin # noqa: F401 from .noDeleteIfNotAdmin import NoDeleteIfNotAdmin # noqa: F401
from .isOwner import IsOwner # noqa: F401 from .isOwner import IsOwner # noqa: F401
from .noDelete import NoDelete # noqa: F401 from .noDelete import NoDelete # noqa: F401
......
from django.contrib.postgres.fields import JSONField
from rest_framework import serializers
from backend.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 serializers.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]
kwargs['default'] = list
super(UsefullLinksField, self).__init__(*args, **kwargs)
from rest_framework import serializers
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 serializers.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 serializers.ValidationError(
"Expected JSON schema not respected")
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