Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Ajout d'une interface de merge pour les contenus #4151

Closed
wants to merge 97 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
d19997d
First commit
Anto59290 Nov 28, 2016
12e6167
ajout de routes, netoyage, test
Anto59290 Dec 5, 2016
1d6c888
Remove useless routes, add tests, add permissions, typos, styling
Anto59290 Dec 15, 2016
9fb78c1
Ajout de test, retrait de todo
Anto59290 Dec 19, 2016
2ff88ac
Testing
Anto59290 Dec 23, 2016
520c8bd
Tests
Anto59290 Dec 24, 2016
a86b075
Add validator, test
Anto59290 Dec 29, 2016
d64117f
Fixing tests, adding tests
Anto59290 Jan 2, 2017
615f5d4
tests
Anto59290 Jan 3, 2017
fa17b76
fixing test
Anto59290 Jan 4, 2017
4ecf63c
testing'
Anto59290 Jan 5, 2017
89eda18
Remove useless code, update todo list, style
Anto59290 Jan 5, 2017
d209ad7
Update settings.py
Anto59290 Jan 5, 2017
405f17c
First POC
Anto59290 Jan 10, 2017
6b78028
clean, remove useless file
Anto59290 Jan 10, 2017
2b19e0d
Clean, industrialisation du processus, divers bugs réglés
Anto59290 Jan 10, 2017
68ecbb1
ajout de la conclusion
Anto59290 Jan 11, 2017
14e987a
change alert to msg
Anto59290 Jan 12, 2017
8be724e
Nettoyage et style, diverses améliorations visuelles
Anto59290 Jan 12, 2017
0977079
style
Anto59290 Jan 12, 2017
c465f32
style
Anto59290 Jan 12, 2017
cbfe255
ajout du package, simplifie le formulaire
Anto59290 Jan 12, 2017
1daa48a
js plus logique
Anto59290 Jan 12, 2017
25276f0
Documentation JS, Refacto JS, ajout d'un TODO
Anto59290 Jan 13, 2017
1ec13cc
Style
Anto59290 Jan 13, 2017
9335ccc
better UX, remove todo
Anto59290 Jan 17, 2017
1e40465
ajout de l'interface de merge aux autres formulaires
Anto59290 Jan 23, 2017
f64b319
Update forms.py
Anto59290 Jan 23, 2017
e81dc71
ajout aux autres forms
Anto59290 Jan 24, 2017
9a62434
Merge branch 'dev' into 3251_git_diff_2
Anto59290 Jan 26, 2017
0541a3e
Update forms.py
Anto59290 Jan 26, 2017
b091f73
merge
Anto59290 Jan 26, 2017
20bf699
fix style
Anto59290 Jan 26, 2017
a199b20
fix style
Anto59290 Jan 26, 2017
f30e30d
merge
Anto59290 Jan 26, 2017
f32e2ba
Update forms.py
Anto59290 Feb 2, 2017
185cc00
Update settings.py
Anto59290 Feb 21, 2017
4e2dbfb
Update auto-merge.js
Anto59290 Feb 21, 2017
7f2c913
Update forms.py
Anto59290 Feb 28, 2017
3c735ff
Remove mege info
Anto59290 Apr 15, 2017
f411710
Merging
Anto59290 Apr 15, 2017
3227078
Merging
Anto59290 Apr 15, 2017
6b73cfc
Merge branch 'dev' into 3251_git_diff_2
Anto59290 Apr 20, 2017
6033f61
Update forms.py
Anto59290 Apr 20, 2017
e5fe212
Update forms.py
Anto59290 Apr 20, 2017
42d52aa
Update forms.py
Anto59290 Apr 22, 2017
43a76af
Update main.scss
Anto59290 Apr 22, 2017
7e12347
Merge branch 'dev' into 3251_git_diff_2
Anto59290 May 7, 2017
516583f
Merge branch 'dev' of https://github.com/zestedesavoir/zds-site into …
Anto59290 May 9, 2017
dd0444c
Fix styles, add sccs files
Anto59290 May 9, 2017
ed5e0cf
merge
Anto59290 May 9, 2017
c30ad5f
Update models.py
Anto59290 May 10, 2017
ca9952d
Update models.py
Anto59290 May 10, 2017
e61d8cf
Update models.py
Anto59290 May 10, 2017
588b3a9
Update models.py
Anto59290 May 10, 2017
32e5899
Update forms.py
Anto59290 May 10, 2017
868945a
Update forms.py
Anto59290 May 10, 2017
ab60b13
Remove files
Anto59290 May 10, 2017
8feb1ec
Merge branch '3251_git_diff_2' of https://github.com/Anto59290/zds-si…
Anto59290 May 10, 2017
aa4afcc
Fix rebase
Anto59290 May 10, 2017
ba88ccc
Update tests_models.py
Anto59290 May 10, 2017
e924cc3
Update permissions.py
Anto59290 May 10, 2017
21141ef
Update forms.py
Anto59290 May 10, 2017
42b4996
Update tests.py
Anto59290 May 10, 2017
696bb81
Update views.py
Anto59290 May 10, 2017
868f7c3
Update
Anto59290 May 10, 2017
ef875a5
Update urls.py
Anto59290 May 11, 2017
dc5c9e4
Update permissions.py
Anto59290 May 11, 2017
9b94737
Update forms.py
Anto59290 May 11, 2017
0d19446
Update models.py
Anto59290 May 11, 2017
c0d07af
Update urls.py
Anto59290 May 13, 2017
59cd3d4
Merge branch 'dev' into 3251_git_diff_2
Anto59290 May 31, 2017
39ead6e
Remove old code
Anto59290 May 31, 2017
b4567b8
Peping
Anto59290 Jun 1, 2017
d00b293
Style
Anto59290 Jun 1, 2017
c80d546
fix tests
Anto59290 Jun 2, 2017
63075aa
Just PEPing
Anto59290 Jun 3, 2017
fba3423
Just PEPing so more forms
Anto59290 Jun 3, 2017
f64ec59
Merge branch 'dev' into 3251_git_diff_2
Anto59290 Aug 15, 2017
5863c8c
Refacto
Anto59290 Aug 22, 2017
c7e8103
Merge branch 'dev' into 3251_git_diff_2
Anto59290 Aug 26, 2017
2602d09
I hate Js
Anto59290 Aug 27, 2017
cbf62b2
Merge branch 'dev' into 3251_git_diff_2
Anto59290 Aug 27, 2017
fcd9eee
Working example
Anto59290 Sep 18, 2017
3571d27
Merge branch '3251_git_diff_2' of https://github.com/Anto59290/zds-si…
Anto59290 Sep 23, 2017
3df61ec
Code style
Anto59290 Oct 28, 2017
782c8aa
Try to rebase
Anto59290 Nov 2, 2017
21ee83f
Fixing merge
Anto59290 Nov 2, 2017
1623c63
Update settings.py
Anto59290 Nov 2, 2017
dd97dde
Refactoring
Anto59290 Nov 5, 2017
af4f552
Merge branch '3251_git_diff_2' of https://github.com/Anto59290/zds-si…
Anto59290 Nov 5, 2017
08a2c30
Merge branch 'dev' into 3251_git_diff_2
Anto59290 Nov 5, 2017
909b53e
Linting
Anto59290 Nov 5, 2017
af170c0
Linting and remove py2 u
Anto59290 Nov 5, 2017
b95cc17
Update auto-merge.js
Anto59290 Nov 5, 2017
88a9290
Update auto-merge.js
Anto59290 Nov 6, 2017
21255b0
Merge branch 'dev' into 3251_git_diff_2
Anto59290 Jan 1, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add validator, test
Anto59290 committed Dec 29, 2016
commit a86b075ea3b052d035854d3a55c6e99d0ea160a9
15 changes: 8 additions & 7 deletions zds/forum/api/serializer.py
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
from dry_rest_permissions.generics import DRYPermissionsField
from dry_rest_permissions.generics import DRYPermissions
from django.shortcuts import get_object_or_404
from zds.utils.validators import TitleValidator, TextValidator


class ForumSerializer(ModelSerializer):
@@ -21,7 +22,7 @@ class Meta:


# Idem renommer TODO
class TopicActionSerializer(ModelSerializer):
class TopicActionSerializer(ModelSerializer, TitleValidator, TextValidator):
"""
Serializer to create a new topic.
"""
@@ -32,7 +33,7 @@ class Meta:
model = Topic
fields = ('id', 'title', 'subtitle', 'text', 'forum',
'author', 'last_message', 'pubdate',
'permissions', 'slug')
'permissions', 'slug', 'position')
read_only_fields = ('id', 'author', 'last_message', 'pubdate', 'permissions')
# TODO je pense qu'avec cette config on peut deplacer un sujet en tant qu'user
# TODO le text deconne
@@ -58,7 +59,7 @@ def create(self, validated_data):
False)
"""

class TopicUpdateSerializer(ModelSerializer):
class TopicUpdateSerializer(ModelSerializer, TitleValidator, TextValidator):
"""
Serializer to update a topic.
"""
@@ -70,8 +71,8 @@ class TopicUpdateSerializer(ModelSerializer):

class Meta:
model = Topic
fields = ('id', 'title', 'subtitle', 'permissions',)
read_only_fields = ('id', 'permissions',)
fields = ('id', 'title', 'subtitle', 'permissions', 'forum')
read_only_fields = ('id', 'permissions', 'forum')

def update(self, instance, validated_data):
for attr, value in validated_data.items():
@@ -87,7 +88,7 @@ class Meta:
permissions_classes = DRYPermissions

# TODO renommer
class PostActionSerializer(ModelSerializer):
class PostActionSerializer(ModelSerializer, TextValidator):
"""
Serializer to send a post in a topic
"""
@@ -110,7 +111,7 @@ def create(self, validated_data):
#def throw_error(self, key=None, message=None):
#raise serializers.ValidationError(message)

class PostUpdateSerializer(ModelSerializer):
class PostUpdateSerializer(ModelSerializer, TextValidator):
"""
Serializer to update a post.
"""
67 changes: 41 additions & 26 deletions zds/forum/api/tests.py
Original file line number Diff line number Diff line change
@@ -278,7 +278,7 @@ def test_list_of_forums(self):

def test_list_of_forums_private(self):
"""
Gets list of forums not empty in the database.
Gets list of private forums not empty in the database (only for staff).
"""
category, forum = create_category(self.group_staff)

@@ -833,7 +833,6 @@ def test_new_post_unknown_topic(self):
# Edite un sujet sans changement
# Édite un sujet qvec user en ls
# Édite un sujet avec user banni
# Édite un sujet en vidant le titre
# Édite un sujet en le passant en resolu
# Editer dans un forum privé ? Verifier les auths
# TODO
@@ -846,9 +845,22 @@ def test_update_topic_details_title(self):
'title': 'Mon nouveau titre'
}
topic = self.create_multiple_forums_with_topics(1, 1, self.profile)
response = self.client.put(reverse('api:forum:detail-topic', args=[topic.id]), data)
response = self.client_authenticated.put(reverse('api:forum:detail-topic', args=[topic.id]), data)
print('test_update_topic_details_title')
print(response)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data.get('title'), data.get('title'))

def test_update_topic_details_title_empty(self):
"""
Updates title of a topic, tries to put an empty sting
"""
data = {
'title': ''
}
topic = self.create_multiple_forums_with_topics(1, 1, self.profile)
response = self.client_authenticated.put(reverse('api:forum:detail-topic', args=[topic.id]), data)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

def test_update_topic_details_subtitle(self):
"""
@@ -915,7 +927,8 @@ def test_update_topic_forum_user(self):
data = {
'forum': 5
}
self.create_multiple_forums_with_topics(5, 1, self.profile)
profile = ProfileFactory()
self.create_multiple_forums_with_topics(5, 1, profile)
topic = Topic.objects.filter(forum=1).first()
response = self.client_authenticated.put(reverse('api:forum:detail-topic', args=[topic.id]), data)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
@@ -944,11 +957,12 @@ def test_list_of_posts(self):
"""
Gets list of posts in a topic.
"""
topic, posts = self.create_topic_with_post()
# A post is already included with the topic
topic, posts = self.create_topic_with_post(REST_PAGE_SIZE - 1)

response = self.client.get(reverse('api:forum:list-post', args=[topic.id]))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data.get('count'), REST_PAGE_SIZE + 1)
self.assertEqual(response.data.get('count'), REST_PAGE_SIZE)
self.assertEqual(len(response.data.get('results')), REST_PAGE_SIZE)
self.assertIsNone(response.data.get('next'))
self.assertIsNone(response.data.get('previous'))
@@ -1034,7 +1048,7 @@ def test_list_of_posts_with_a_custom_page_size(self):
Gets list of forums with a custom page size. DRF allows to specify a custom
size for the pagination.
"""
topic, posts = self.create_topic_with_post(REST_PAGE_SIZE * 2)
topic, posts = self.create_topic_with_post((REST_PAGE_SIZE * 2) - 1)
print (topic)

page_size = 'page_size'
@@ -1067,9 +1081,8 @@ def test_list_of_posts_in_unknown_topic(self):
"""
Tries to list the posts of an non existing Topic.
"""
topic, posts = self.create_topic_with_post()

response = self.client.get(reverse('api:forum:list-post', args=[topic.id]))
response = self.client.get(reverse('api:forum:list-post', args=[666]))
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

def test_list_of_user_topics_empty(self):
@@ -1254,7 +1267,7 @@ def test_failure_post_in_a_forum_we_cannot_read(self):
data = {
'text': 'Welcome to this post!'
}
response = self.client.post(reverse('api:forum:list-post', args=[topic.pk,]), data)
response = self.client_authenticated.post(reverse('api:forum:list-post', args=[topic.pk,]), data)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

def test_post_in_a_private_forum(self):
@@ -1292,7 +1305,9 @@ def test_detail_post(self):
self.assertIsNotNone(response.data.get('text_html'))
self.assertIsNotNone(response.data.get('pubdate'))
self.assertIsNone(response.data.get('update'))
self.assertEqual(post.position_in_topic, response.data.get('position_in_topic'))
print('test_detail_post')
print(response.data)
self.assertEqual(post.position, response.data.get('position_in_topic'))
self.assertEqual(topic.author, response.data.get('author'))

def test_detail_of_a_private_post_not_present(self):
@@ -1371,7 +1386,8 @@ def test_list_of_member_posts_with_several_pages(self):
"""
Gets list of a member topics with several pages in the database.
"""
self.create_multiple_forums_with_topics(REST_PAGE_SIZE + 1, 1, self.profile)
# When we create a Topic a post is also added.
self.create_multiple_forums_with_topics(REST_PAGE_SIZE, 1, self.profile)

response = self.client_authenticated.get(reverse('api:forum:list-memberpost', args=[self.profile.id]))
self.assertEqual(response.status_code, status.HTTP_200_OK)
@@ -1380,7 +1396,7 @@ def test_list_of_member_posts_with_several_pages(self):
self.assertIsNone(response.data.get('previous'))
self.assertEqual(len(response.data.get('results')), REST_PAGE_SIZE)

response = self.client_authenticated.get(reverse('api:forum:list-memberpost', args=[self.profile.id]))
response = self.client_authenticated.get(reverse('api:forum:list-memberpost', args=[self.profile.id]) + '?page=2')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data.get('count'), REST_PAGE_SIZE + 1)
self.assertIsNone(response.data.get('next'))
@@ -1409,13 +1425,13 @@ def test_list_of_member_post_for_a_wrong_page_given(self):

def test_list_of_member_posts_with_a_custom_page_size(self):
"""
Gets list of user's topics with a custom page size. DRF allows to specify a custom
Gets list of user's posts with a custom page size. DRF allows to specify a custom
size for the pagination.
"""
self.create_topic_with_post(REST_PAGE_SIZE * 2, 1, self.profile)
self.create_topic_with_post(REST_PAGE_SIZE * 2, self.profile)

page_size = 'page_size'
response = self.client.get(reverse('api:forum:list-memberpost') + '?{}=20'.format(page_size), args=[self.profile.id])
response = self.client.get(reverse('api:forum:list-memberpost', args=[self.profile.id]) + '?{}=20'.format(page_size))
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data.get('count'), 20)
self.assertEqual(len(response.data.get('results')), 20)
@@ -1455,7 +1471,7 @@ def test_alert_post(self):
another_profile = ProfileFactory()
post = PostFactory(topic=topic, author=another_profile.user, position=1)
data = {
'text': 'There is a guy flooding about Flask, con you do something about it ?',
'text': 'There is a guy flooding about Flask, con you do something about it ?'
}

self.client = APIClient()
@@ -1480,7 +1496,7 @@ def test_alert_post_in_private_forum(self):
topic = add_topic_in_a_forum(forum, profile)
post = PostFactory(topic=topic, author=profile.user, position=1)
data = {
'text': 'There is a guy flooding about Flask, con you do something about it ?',
'text': 'There is a guy flooding about Flask, con you do something about it ?'
}

self.client = APIClient()
@@ -1507,7 +1523,7 @@ def test_alert_post_not_found(self):
topic = add_topic_in_a_forum(forum, profile)
post = PostFactory(topic=topic, author=profile.user, position=1)
data = {
'text': 'There is a guy flooding about Flask, con you do something about it ?',
'text': 'There is a guy flooding about Flask, con you do something about it ?'
}

response = self.client_authenticated.post(reverse('api:forum:alert-post', args=[666, post.id]), data)
@@ -1550,17 +1566,16 @@ def test_update_post_other_user(self):
}
topic, posts = self.create_topic_with_post(REST_PAGE_SIZE, self.profile)
response = self.client_authenticated.put(reverse('api:forum:detail-post', args=[topic.id, posts[0].id]), data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(data.get('text'), response.data.get('text'))

self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

def test_update_post(self):
"""
Updates a post with user.
"""
data = {
'text': 'I made an error I want to edit.'
}
topic, posts = self.create_topic_with_post()
topic, posts = self.create_topic_with_post(1, self.profile)
response = self.client_authenticated.put(reverse('api:forum:detail-post', args=[topic.id, posts[0].id]), data)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

@@ -1574,7 +1589,7 @@ def test_update_post_staff(self):
topic, posts = self.create_topic_with_post()
response = self.client_authenticated_staff.put(reverse('api:forum:detail-post', args=[topic.id, posts[0].id]), data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(reponse.data.get('text'), data.get('text'))
self.assertEqual(response.data.get('text'), data.get('text'))

def test_update_unknow_post(self):
"""
@@ -1596,9 +1611,9 @@ def test_update_post_in_private_topic_anonymous(self):
self.client = APIClient();
category, forum = create_category(self.group_staff)
topic = add_topic_in_a_forum(forum, self.staff)
posts = PostFactory(topic=topic, author=self.staff.user, position=1)
post = PostFactory(topic=topic, author=self.staff.user, position=1)

response = self.client.put(reverse('api:forum:detail-post', args=[topic.id, posts[0].id]), data)
response = self.client.put(reverse('api:forum:detail-post', args=[topic.id, post.id]), data)
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)


16 changes: 13 additions & 3 deletions zds/forum/api/views.py
Original file line number Diff line number Diff line change
@@ -82,6 +82,10 @@ def get(self, request, *args, **kwargs):
message: Not Found
"""
return self.list(request, *args, **kwargs)

def get_permissions(self):
permission_classes = [AllowAny, CanReadForum]
return [permission() for permission in permission_classes]


class ForumDetailAPI(RetrieveAPIView):
@@ -200,6 +204,7 @@ def get_permissions(self):
permission_classes.append(IsAuthenticated)
permission_classes.append(CanReadAndWriteNowOrReadOnly)
permission_classes.append(CanReadTopic)
permission_classes.append(CanReadForum)
return [permission() for permission in permission_classes]


@@ -377,6 +382,8 @@ def get_serializer_class(self):
def get_queryset(self):
if self.request.method == 'GET':
posts = Post.objects.filter(topic=self.kwargs.get('pk'))
#if posts is None:
# raise Http404("Topic with pk {} was not found".format(self.kwargs.get('pk')))
return posts

def get_current_user(self):
@@ -388,6 +395,7 @@ def get_permissions(self):
permission_classes.append(DRYPermissions)
permission_classes.append(IsAuthenticated)
permission_classes.append(CanReadAndWriteNowOrReadOnly)
permission_classes.append(CanReadPost)
return [permission() for permission in permission_classes]


@@ -528,8 +536,6 @@ class PostAlertAPI(CreateAPIView):
Alert a topic post to the staff.
"""

serializer_class = AlertSerializer

def post(self, request, *args, **kwargs):
"""
Alert a topic post to the staff.
@@ -556,13 +562,17 @@ def post(self, request, *args, **kwargs):

serializer = self.get_serializer_class()(data=request.data, context={'request': self.request})
serializer.is_valid(raise_exception=True)
serializer.save(position=0, author=author, comment=post)
serializer.save(comment=post)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

def get_permissions(self):
permission_classes = [AllowAny, IsAuthenticated]
return [permission() for permission in permission_classes]

def get_serializer_class(self):
return AlertSerializer



# TODO global identier quand masquer les messages
3 changes: 2 additions & 1 deletion zds/forum/forms.py
Original file line number Diff line number Diff line change
@@ -8,7 +8,8 @@
from crispy_forms.layout import Layout, Field, Hidden
from crispy_forms.bootstrap import StrictButton
from zds.forum.models import Forum, Topic
from zds.utils.forms import CommonLayoutEditor, TagValidator
from zds.utils.forms import CommonLayoutEditor
from zds.utils.validators import TagValidator
from django.utils.translation import ugettext_lazy as _


5 changes: 2 additions & 3 deletions zds/forum/models.py
Original file line number Diff line number Diff line change
@@ -388,14 +388,14 @@ def has_read_permission(request):
return True

def has_object_read_permission(self, request):
return Topic.has_read_permission(request) # TODO gerer fofo prives
return Topic.has_read_permission(request)

@staticmethod
def has_write_permission(request):
return request.user.is_authenticated()

def has_object_write_permission(self, request):
return Topic.has_write_permission(request) # TODO gerer les fofo prives
return Topic.has_write_permission(request)

def has_object_update_permission(self, request):
return Topic.has_write_permission(request) and (Topic.author == request.user)
@@ -451,7 +451,6 @@ def has_write_permission(request):

def has_object_write_permission(self, request):
return Topic.has_write_permission(request)
# TODO verifier que ce n'est pas un forum prive

def has_object_update_permission(self, request):
return self.is_author(request.user)
2 changes: 1 addition & 1 deletion zds/tutorialv2/forms.py
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
from django.utils.translation import ugettext_lazy as _
from zds.member.models import Profile
from zds.tutorialv2.utils import slugify_raise_on_invalid, InvalidSlugError
from zds.utils.forms import TagValidator
from zds.utils.validators import TagValidator


class FormWithTitle(forms.Form):
67 changes: 0 additions & 67 deletions zds/utils/forms.py
Original file line number Diff line number Diff line change
@@ -66,70 +66,3 @@ def __init__(self, *args, **kwargs):
Field('text'),
*args, **kwargs
)


class TagValidator(object):
"""
validate tags
"""
def __init__(self):
self.__errors = []
self.logger = logging.getLogger("zds.utils.forms")
self.__clean = []

def validate_raw_string(self, raw_string):
"""
validate a string composed as ``tag1,tag2``.
:param raw_string: the string to be validate. If ``None`` this is considered as a empty str
:type raw_string: basestring
:return: ``True`` if ``raw_string`` is fully valid, ``False`` if at least one error appears. See ``self.errors``
to get all internationalized error.
"""
if raw_string is None or not isinstance(raw_string, basestring):
return self.validate_string_list([])
return self.validate_string_list(raw_string.split(","))

def validate_length(self, tag):
"""
Check the length is in correct range. See ``Tag.label`` max length to have the true upper bound.
:param tag: the tag lavel to validate
:return: ``True`` if length is valid
"""
if len(tag) > Tag._meta.get_field("title").max_length:
self.errors.append(_(u"Le tag {} est trop long (maximum {} caractères)".format(
tag, Tag._meta.get_field("title").max_length)))
self.logger.debug("%s est trop long expected=%d got=%d", tag,
Tag._meta.get_field("title").max_length, len(tag))
return False
return True

def validate_string_list(self, string_list):
"""
Same as ``validate_raw_string`` but with a list of tag labels.
:param string_list:
:return: ``True`` if ``v`` is fully valid, ``False`` if at least one error appears. See ``self.errors``
to get all internationalized error.
"""
self.__clean = list(filter(self.validate_length, string_list))
self.__clean = list(filter(self.validate_utf8mb4, self.__clean))
return len(string_list) == len(self.__clean)

def validate_utf8mb4(self, tag):
"""
Checks the tag does not contain utf8mb4 chars.
:param tag:
:return: ``True`` if no utf8mb4 string is found
"""
if contains_utf8mb4(tag):
self.errors.append(_(u"Le tag {} contient des caractères utf8mb4").format(tag))
self.logger.warn("%s contains utf8mb4 char", tag)
return False
return True

@property
def errors(self):
return self.__errors
2 changes: 1 addition & 1 deletion zds/utils/tests/tests_models.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
from django.test import TestCase
from django.db import IntegrityError, transaction

from zds.utils.forms import TagValidator
from zds.utils.validators import TagValidator
from zds.utils.models import Tag