Explorar o código

amelioration du systeme de commentaire

omassot %!s(int64=7) %!d(string=hai) anos
pai
achega
2571967862

+ 9 - 3
main/forms.py

@@ -57,18 +57,24 @@ class StoryForm(forms.ModelForm):
         self.fields['sprints'].required = False
         self.fields['weight'].required = False
     
-    def save(self):
+    def save(self, *args, **kwargs):
         if self.cleaned_data['weight'] == '':
             self.cleaned_data['weight'] = None
-        return super(StoryForm, self).save()
+        return super(StoryForm, self).save(*args, **kwargs)
         
         
 class CommentForm(forms.ModelForm):
     class Meta:
         model = Comment
-        fields = ('content',)
+        widgets = {'content_type': forms.HiddenInput(), 'object_id': forms.HiddenInput()}
+        fields = ('content','content_type', 'object_id')
     content = MartorFormField(label="Commentaire")
 
+    def __init__(self, *args, **kwargs):
+        super(CommentForm, self).__init__(*args, **kwargs)
+        if not self.prefix:
+            self.prefix = str(self.instance.id) if self.instance and self.instance.id else "new"
+ 
 class SprintForm(forms.ModelForm):
     class Meta:
         model = Sprint

+ 29 - 17
main/models.py

@@ -3,6 +3,9 @@ import datetime
 import uuid
 
 from django.contrib.auth.models import User
+from django.contrib.contenttypes.fields import GenericForeignKey, \
+    GenericRelation
+from django.contrib.contenttypes.models import ContentType
 from django.core import serializers
 from django.db import models, connection
 from django.db.models.aggregates import Sum
@@ -26,18 +29,38 @@ class BaseModel(models.Model):
     class Meta:
         abstract = True
 
+    def get_content_type(self):
+        return ContentType.objects.get_for_model(self)
+
     def model_name(self):
         try:
             return self._meta.verbose_name
         except AttributeError:
             return ""
 
-    def comments(self):
-        return Comment.objects.filter(obj_uuid = self.uuid)
-
     def to_json(self):
         return serializers.serialize('json', [ self, ])
 
+
+class Comment(BaseModel):
+    class Meta:
+        verbose_name = "commentaire"
+        verbose_name_plural = "commentaires"
+        ordering = ('-created', )
+        
+    def __str__(self):
+        return "De {}, le {:%Y-%m-%d}: {}".format(self.author.username, self.created, self.content[:30])
+                
+    content_type = models.ForeignKey(ContentType,on_delete=models.CASCADE)
+    object_id = models.PositiveIntegerField()
+    content_object = GenericForeignKey('content_type', 'object_id')
+    
+    content = MartorField(blank=False, default="", verbose_name="Commentaire")
+    author = models.ForeignKey(User, 
+                               on_delete=models.PROTECT, 
+                               verbose_name="Auteur")
+    created = models.DateTimeField(auto_now_add=True)
+    
 class Project(BaseModel):
     class Meta:
         verbose_name = "projet"
@@ -70,6 +93,7 @@ class Epic(BaseModel):
     description = MartorField(blank=True, default="", verbose_name="Description")
     project = models.ForeignKey(Project, on_delete=models.PROTECT, null=True, verbose_name="Projet")
     closed = models.BooleanField(default=False, verbose_name="Clôturée")
+    comments = GenericRelation(Comment)
     
     def __str__(self):
         return self.name
@@ -193,6 +217,7 @@ class Story(BaseModel):
                                        related_name="stories",
                                        related_query_name="story", 
                                        verbose_name="Sprints")
+    comments = GenericRelation(Comment)
     
     def __str__(self):
         return self.name
@@ -217,17 +242,4 @@ class Story(BaseModel):
         self.closed = False
         self.save()
 
-class Comment(BaseModel):
-    class Meta:
-        verbose_name = "commentaire"
-        verbose_name_plural = "commentaires"
-        ordering = ('-created', )
-        
-    def __str__(self):
-        return "De {}, le {:%Y-%m-%d}: {}".format(self.author.username, self.created, self.content[:30])
-                
-    obj_uuid = models.UUIDField(default="")
-    content = MartorField(blank=False, default="", verbose_name="Commentaire")
-    author = models.ForeignKey(User, 
-                               on_delete=models.PROTECT, 
-                               verbose_name="Auteur")
+

+ 12 - 5
main/templates/_comment_div.html

@@ -2,16 +2,19 @@
 {# l'objet en parametre doit avoir une propriete 'comments' et une propriete 'uuid' #}
 
 {% load martortags %}
+{% load commenting %}
 
 <a class="anchor" id="a-comment-section"></a>
 <div id="comment-section">
 	<ul class="comment-list">
-	{% for comment, frm in com_pack.comments.items %}
+	{% for comment in obj.comments.all %}
+		
 		<li class="comment flex-col anchor" id="comment-{{ comment.id }}" data-id="{{ comment.id }}">
 			<a class="anchor" id="a-comment-{{ comment.id }}"></a>
 			<div class="flex-row">
 				<span class="comment-header"><i class="fa fa-comment"></i> {{ comment.author }}, le {{ comment.created }}</span>
-				{% if comment.author.id == request.user.id %}
+
+				{% if comment.author.id == user.id %}
 				    <a class="comment-edit-btn" href="" style="margin-left: 20px;"><i class="fa fa-pencil"></i></a>
 					<a class="comment-del-btn" href="{% url 'comment_del' comment_id=comment.id %}" style="margin-left: 10px;"><i class="fa fa-trash"></i></a>
 				{% endif %}
@@ -24,9 +27,12 @@
 				<form action="{% url 'comment_edit' comment_id=comment.id %}" method="post" accept-charset="utf-8" enctype="multipart/form-data">
 					{% csrf_token %}
 					
+					{% comment_edition_form comment as frm %}
+					{{ frm.content_type }}
+					{{ frm.object_id }}
 					{{ frm.content }}
 					
-			    	<div class="flex-row flex-end" style="margin-top: 10px;">
+			    	<div class="flex-row flex-end flex-align-center" style="margin-top: 10px;">
 			    		<a href="" class="comment-edition-cancel" style="margin-right: 20px;">Annuler</a>
 			    		<input type="submit">
 			    	</div>
@@ -36,10 +42,11 @@
 	{% endfor %}
 	</ul>
 	
-	<form action="{% url 'comment_post' obj_uuid=com_pack.obj.uuid %}" method="post" accept-charset="utf-8" enctype="multipart/form-data" style="margin-top:4em;">
+	<form action="{% url 'comment_post' %}" method="post" accept-charset="utf-8" enctype="multipart/form-data" style="margin-top:4em;">
 		{% csrf_token %}
 		
-		{{ com_pack.empty_form.as_p }}
+		{% comment_new_form obj as frm %}
+		{{ frm.as_p }}
 		
     	<div class="flex-row flex-end" style="margin-top: 10px;">
     		<input type="submit">

+ 2 - 1
main/templates/epic_details.html

@@ -1,4 +1,5 @@
 {% extends '_layout.html' %}
+{% load commenting %}
 
 {% block title %}
 	{{ epic.name }}
@@ -60,6 +61,6 @@
 
 	<hr>
 	
-	{% include '_comment_div.html' with com_pack=com_pack %}
+	{% comments_for epic %}
     
 {% endblock %}

+ 2 - 1
main/templates/story_details.html

@@ -1,4 +1,5 @@
 {% extends '_layout.html' %}
+{% load commenting %}
 
 {% block title %}
 	{{ story.name }}
@@ -84,6 +85,6 @@
 	
 	<hr>
 	
-	{% include '_comment_div.html' with obj=story %}
+	{% comments_for story %}
 	
 {% endblock %}

+ 0 - 0
main/templatetags/__init__.py


+ 25 - 0
main/templatetags/commenting.py

@@ -0,0 +1,25 @@
+'''
+
+@author: olivier.massot, 2018
+'''
+from django.template.library import Library
+
+from main.forms import CommentForm
+from main.models import Comment
+
+register = Library()
+
+@register.inclusion_tag('_comment_div.html', takes_context=True)
+def comments_for(context, obj):
+    return {'obj': obj, 'user': context.request.user}
+
+@register.simple_tag
+def comment_new_form(target_obj):
+    new_comment = Comment()
+    new_comment.content_type = target_obj.get_content_type()
+    new_comment.object_id = target_obj.id
+    return CommentForm(instance=new_comment)
+
+@register.simple_tag
+def comment_edition_form(comment):
+    return CommentForm(instance=comment)

+ 1 - 1
main/urls.py

@@ -37,7 +37,7 @@ urlpatterns = [
     path('reports/sprints/', views.report_sprints, name='report_sprints'),
     path('reports/projects/', views.report_projects, name='report_projects'),
     path('reports/activity/', views.report_activity, name='report_activity'),
-    path('comment-post/<obj_uuid>/', views.comment_post, name='comment_post'),
+    path('comment-post/', views.comment_post, name='comment_post'),
     path('comment-edit/<int:comment_id>/', views.comment_edit, name='comment_edit'),
     path('comment-del/<int:comment_id>/', views.comment_del, name='comment_del'),
     path('search/', views.search, name='search'),

+ 17 - 19
main/views.py

@@ -113,7 +113,7 @@ def story_index(request):
 @login_required
 def story_details(request, story_id):
     story = get_object_or_404(Story, id=story_id)
-    return render(request, 'story_details.html', {'story': story, 'com_pack': com_pack(story)})
+    return render(request, 'story_details.html', {'story': story})
 
 @login_required
 def story_create(request, epic_id=None):
@@ -186,7 +186,7 @@ def story_reopen(_, story_id):
 @login_required
 def epic_details(request, epic_id):
     epic = get_object_or_404(Epic, id=epic_id)
-    return render(request, 'epic_details.html', {'epic': epic, 'com_pack': com_pack(epic)})
+    return render(request, 'epic_details.html', {'epic': epic})
 
 @login_required
 def epic_create(request):
@@ -297,29 +297,27 @@ def report_activity(request):
     epics_activity_cleaned = {epic: act for epic, act in epics_activity.items() if act["sixmonths"] > 0 }
     
     return render(request, 'reports/report_activity.html', {'projects_activity': projects_activity, 'epics_activity': epics_activity_cleaned})
-        
-def com_pack(obj):
-    pack = {}
-    pack['obj'] = obj
-    pack['comments'] = {c: CommentForm(instance=c, prefix="{}".format(c.id)) for c in obj.comments()}
-    pack['empty_form'] = CommentForm(prefix="new")
-    return pack
 
 @login_required
-def comment_post(request, obj_uuid):
-    comment = Comment()
-    comment.obj_uuid = obj_uuid
-    comment.author = get_object_or_404(User, username=request.user)
-    comment.content = request.POST["new-content"]
-    comment.save()
-    return redirect(request.META['HTTP_REFERER'].split("#")[0] + "#a-comment-{}".format(comment.id))
+def comment_post(request):
+    form = CommentForm(request.POST)
+    if form.is_valid():
+        comment = form.save(commit=False)
+        comment.author = get_object_or_404(User, username=request.user)
+        comment.save()
+        return redirect(request.META['HTTP_REFERER'].split("#")[0] + "#a-comment-{}".format(comment.id))
+    else:
+        return redirect(request.META['HTTP_REFERER'])
 
 @login_required
 def comment_edit(request, comment_id):
     comment = get_object_or_404(Comment, id=comment_id)
-    comment.content = request.POST["{}-content".format(comment_id)]
-    comment.save()
-    return redirect(request.META['HTTP_REFERER'].split("#")[0] + "#a-comment-{}".format(comment.id))
+    form = CommentForm(request.POST, instance=comment)
+    if form.is_valid():
+        form.save()
+        return redirect(request.META['HTTP_REFERER'].split("#")[0] + "#a-comment-{}".format(comment_id))
+    else:
+        return redirect(request.META['HTTP_REFERER'])
     
 @login_required
 def comment_del(request, comment_id):