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 @@
"name": "photos",
"config": {
"photos": {
"type": "list",
"type": "array",
"content": {
"url": {
"type": "url",
......
# Generated by Django 2.0.3 on 2018-08-29 19:43
# Generated by Django 2.0.3 on 2018-08-30 20:53
import backend.models.tools.usefullLinksField
import backend.utils.friendly_path
from django.conf import settings
import django.contrib.postgres.fields.jsonb
......@@ -25,8 +24,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('usefull_links', backend.models.tools.usefullLinksField.UsefullLinksField(blank=True, default=list, validators=[backend.models.tools.usefullLinksField.validate_usefull_links])),
('custom_content', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('usefull_links', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=list)),
('is_main_campus', models.BooleanField()),
('name', models.CharField(max_length=200, null=True)),
('comment', models.TextField(blank=True, null=True)),
......@@ -48,17 +46,6 @@ class Migration(migrations.Migration):
'abstract': False,
},
),
migrations.CreateModel(
name='CityPhoto',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('photo', models.ImageField(default='path/to/my/default/image.jpg', max_length=250, upload_to=backend.utils.friendly_path.friendly_path('uploads/universities/photos/', 'title'))),
('title', models.CharField(max_length=200)),
('description', models.TextField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='Country',
fields=[
......@@ -85,24 +72,12 @@ class Migration(migrations.Migration):
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('comment', models.TextField(blank=True)),
('usefull_links', backend.models.tools.usefullLinksField.UsefullLinksField(blank=True, default=list, validators=[backend.models.tools.usefullLinksField.validate_usefull_links])),
('custom_content', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('usefull_links', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=list)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='CountryPhoto',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('photo', models.ImageField(default='path/to/my/default/image.jpg', max_length=250, upload_to=backend.utils.friendly_path.friendly_path('uploads/universities/photos/', 'title'))),
('title', models.CharField(max_length=200)),
('description', models.TextField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='CountryScholarship',
fields=[
......@@ -110,8 +85,7 @@ class Migration(migrations.Migration):
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('comment', models.TextField(blank=True)),
('usefull_links', backend.models.tools.usefullLinksField.UsefullLinksField(blank=True, default=list, validators=[backend.models.tools.usefullLinksField.validate_usefull_links])),
('custom_content', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('usefull_links', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=list)),
('type', models.CharField(max_length=200)),
('amount_min', models.DecimalField(decimal_places=2, max_digits=20, validators=[django.core.validators.MinValueValidator(0)])),
('amount_max', models.DecimalField(decimal_places=2, max_digits=20, validators=[django.core.validators.MinValueValidator(0)])),
......@@ -302,7 +276,7 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('name', models.CharField(max_length=100)),
('name', models.CharField(max_length=100, unique=True)),
('config', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('moderated_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('updated_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
......@@ -333,26 +307,13 @@ class Migration(migrations.Migration):
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('comment', models.TextField(blank=True)),
('usefull_links', backend.models.tools.usefullLinksField.UsefullLinksField(blank=True, default=list, validators=[backend.models.tools.usefullLinksField.validate_usefull_links])),
('custom_content', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('usefull_links', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=list)),
('moderated_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='UniversityPhoto',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('photo', models.ImageField(default='path/to/my/default/image.jpg', max_length=250, upload_to=backend.utils.friendly_path.friendly_path('uploads/universities/photos/', 'title'))),
('title', models.CharField(max_length=200)),
('description', models.TextField(blank=True, null=True)),
('moderated_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='UniversityScholarship',
fields=[
......@@ -360,8 +321,7 @@ class Migration(migrations.Migration):
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('comment', models.TextField(blank=True)),
('usefull_links', backend.models.tools.usefullLinksField.UsefullLinksField(blank=True, default=list, validators=[backend.models.tools.usefullLinksField.validate_usefull_links])),
('custom_content', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('usefull_links', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=list)),
('type', models.CharField(max_length=200)),
('amount_min', models.DecimalField(decimal_places=2, max_digits=20, validators=[django.core.validators.MinValueValidator(0)])),
('amount_max', models.DecimalField(decimal_places=2, max_digits=20, validators=[django.core.validators.MinValueValidator(0)])),
......@@ -392,9 +352,6 @@ class Migration(migrations.Migration):
fields=[
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('comment', models.TextField(blank=True)),
('usefull_links', backend.models.tools.usefullLinksField.UsefullLinksField(blank=True, default=list, validators=[backend.models.tools.usefullLinksField.validate_usefull_links])),
('custom_content', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('campus', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, primary_key=True, related_name='city_items', serialize=False, to='backend.Campus')),
('moderated_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('tag', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='backend.Tag')),
......@@ -406,9 +363,6 @@ class Migration(migrations.Migration):
fields=[
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('comment', models.TextField(blank=True)),
('usefull_links', backend.models.tools.usefullLinksField.UsefullLinksField(blank=True, default=list, validators=[backend.models.tools.usefullLinksField.validate_usefull_links])),
('custom_content', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('city', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, primary_key=True, related_name='city_items', serialize=False, to='backend.City')),
('moderated_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('tag', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='backend.Tag')),
......@@ -420,10 +374,7 @@ class Migration(migrations.Migration):
fields=[
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('comment', models.TextField(blank=True)),
('usefull_links', backend.models.tools.usefullLinksField.UsefullLinksField(blank=True, default=list, validators=[backend.models.tools.usefullLinksField.validate_usefull_links])),
('custom_content', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('country', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, primary_key=True, related_name='city_items', serialize=False, to='backend.Country')),
('country', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, primary_key=True, related_name='country_items', serialize=False, to='backend.Country')),
('moderated_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('tag', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='backend.Tag')),
('updated_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
......@@ -435,8 +386,7 @@ class Migration(migrations.Migration):
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('comment', models.TextField(blank=True)),
('usefull_links', backend.models.tools.usefullLinksField.UsefullLinksField(blank=True, default=list, validators=[backend.models.tools.usefullLinksField.validate_usefull_links])),
('custom_content', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('usefull_links', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=list)),
('university', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='university_info', serialize=False, to='backend.University')),
('cost_exchange', models.DecimalField(decimal_places=2, max_digits=20, null=True, validators=[django.core.validators.MinValueValidator(0)])),
('cost_double_degree', models.DecimalField(decimal_places=2, max_digits=20, null=True, validators=[django.core.validators.MinValueValidator(0)])),
......@@ -454,8 +404,7 @@ class Migration(migrations.Migration):
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('comment', models.TextField(blank=True)),
('usefull_links', backend.models.tools.usefullLinksField.UsefullLinksField(blank=True, default=list, validators=[backend.models.tools.usefullLinksField.validate_usefull_links])),
('custom_content', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('usefull_links', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=list)),
('university', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='university_semesters_dates', serialize=False, to='backend.University')),
('spring_begin', models.DateField(blank=True, null=True)),
('spring_end', models.DateField(blank=True, null=True)),
......@@ -473,9 +422,6 @@ class Migration(migrations.Migration):
fields=[
('moderated_on', models.DateTimeField(null=True)),
('updated_on', models.DateTimeField(null=True)),
('comment', models.TextField(blank=True)),
('usefull_links', backend.models.tools.usefullLinksField.UsefullLinksField(blank=True, default=list, validators=[backend.models.tools.usefullLinksField.validate_usefull_links])),
('custom_content', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict)),
('university', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, primary_key=True, related_name='city_items', serialize=False, to='backend.University')),
('moderated_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
('tag', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='backend.Tag')),
......@@ -512,16 +458,6 @@ class Migration(migrations.Migration):
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='universityphoto',
name='university',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='university_photos', to='backend.University'),
),
migrations.AddField(
model_name='universityphoto',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='universitydri',
name='university',
......@@ -627,21 +563,6 @@ class Migration(migrations.Migration):
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='countryphoto',
name='country',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='country_photos', to='backend.Country'),
),
migrations.AddField(
model_name='countryphoto',
name='moderated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='countryphoto',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='countrydri',
name='country',
......@@ -667,21 +588,6 @@ class Migration(migrations.Migration):
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='cityphoto',
name='city',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='city_photos', to='backend.City'),
),
migrations.AddField(
model_name='cityphoto',
name='moderated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='cityphoto',
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='city',
name='country',
......@@ -717,10 +623,6 @@ class Migration(migrations.Migration):
name='updated_by',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL),
),
migrations.AlterUniqueTogether(
name='universityphoto',
unique_together={('university', 'photo')},
),
migrations.AlterUniqueTogether(
name='specialty',
unique_together={('code', 'department')},
......@@ -741,14 +643,6 @@ class Migration(migrations.Migration):
name='offer',
unique_together={('semester', 'university')},
),
migrations.AlterUniqueTogether(
name='countryphoto',
unique_together={('country', 'photo')},
),
migrations.AlterUniqueTogether(
name='cityphoto',
unique_together={('city', 'photo')},
),
migrations.AlterUniqueTogether(
name='campus',
unique_together={('is_main_campus', 'university')},
......
# 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 backend.models.tools import UsefullLinksField
from backend.models.my_model import MyModelVersionned, MyModelVersionnedSerializer, MyModelVersionnedViewSet
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):
comment = models.TextField(blank=True)
usefull_links = UsefullLinksField(blank=True, default=list)
custom_content = JSONField(blank=True, default=dict)
usefull_links = JSONField(blank=True, default=list)
class Meta:
abstract = True
......@@ -16,6 +36,12 @@ class BasicModule(MyModelVersionned):
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:
model = BasicModule
fields = '__all__'
......
from .tag import Tag, TagSerializer, TagViewSet # 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 backend.models.module import BasicModule, BasicModuleSerializer, BasicModuleViewSet
from backend.models.my_model import MyModelVersionned, MyModelVersionnedSerializer, MyModelVersionnedViewSet
from .tag import Tag
from .tagged_item_validation import tagged_item_validation
class TaggedItem(BasicModule):
class TaggedItem(MyModelVersionned):
tag = models.ForeignKey(Tag, related_name='+', on_delete=models.PROTECT)
class Meta:
abstract = True
class TaggedItemSerializer(BasicModuleSerializer):
class TaggedItemSerializer(MyModelVersionnedSerializer):
def validate(self, attrs):
tagged_item_validation(attrs)
return attrs
class TaggedItemViewSet(BasicModuleViewSet):
class TaggedItemViewSet(MyModelVersionnedViewSet):
def extend_queryset(self):
return self.mymodel_queryset.prefetch_related('tag')
......@@ -25,9 +25,9 @@ def validate_content_against_config(config, content):
validate_url(field_config, field_submitted)
elif field_type == 'text':
validate_text(field_config, field_submitted)
elif field_type == 'list':
elif field_type == 'array':
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:
validate_content_against_config(field_config['content'], item)
else:
......
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 .isOwner import IsOwner # 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