Adding questions support

remotes/origin/enhancement/email-actions
Alejandro Alonso 2013-04-26 10:49:18 +02:00
parent 7df355d92e
commit bce92c42f0
11 changed files with 554 additions and 408 deletions

View File

@ -44,7 +44,6 @@ class ApiRoot(APIView):
'priorities': reverse('priority-list', request=request, format=format), 'priorities': reverse('priority-list', request=request, format=format),
'documents': reverse('document-list', request=request, format=format), 'documents': reverse('document-list', request=request, format=format),
'questions': reverse('question-list', request=request, format=format), 'questions': reverse('question-list', request=request, format=format),
'question_responses': reverse('question-response-list', request=request, format=format),
'wiki/pages': reverse('wiki-page-list', request=request, format=format), 'wiki/pages': reverse('wiki-page-list', request=request, format=format),
'users': reverse('user-list', request=request, format=format), 'users': reverse('user-list', request=request, format=format),
'roles': reverse('user-roles', request=request, format=format), 'roles': reverse('user-roles', request=request, format=format),

View File

@ -1,561 +1,601 @@
[ [
{ {
"pk": 1, "pk": 1,
"model": "base.role", "model": "base.role",
"fields": { "fields": {
"permissions": [ "permissions": [
[ [
"add_logentry", "add_logentry",
"admin", "admin",
"logentry" "logentry"
], ],
[ [
"change_logentry", "change_logentry",
"admin", "admin",
"logentry" "logentry"
], ],
[ [
"delete_logentry", "delete_logentry",
"admin", "admin",
"logentry" "logentry"
], ],
[ [
"add_group", "add_group",
"auth", "auth",
"group" "group"
], ],
[ [
"change_group", "change_group",
"auth", "auth",
"group" "group"
], ],
[ [
"delete_group", "delete_group",
"auth", "auth",
"group" "group"
], ],
[ [
"add_permission", "add_permission",
"auth", "auth",
"permission" "permission"
], ],
[ [
"change_permission", "change_permission",
"auth", "auth",
"permission" "permission"
], ],
[ [
"delete_permission", "delete_permission",
"auth", "auth",
"permission" "permission"
], ],
[ [
"add_role", "add_role",
"base", "base",
"role" "role"
], ],
[ [
"change_role", "change_role",
"base", "base",
"role" "role"
], ],
[ [
"delete_role", "delete_role",
"base", "base",
"role" "role"
], ],
[ [
"add_user", "add_user",
"base", "base",
"user" "user"
], ],
[ [
"change_user", "change_user",
"base", "base",
"user" "user"
], ],
[ [
"delete_user", "delete_user",
"base", "base",
"user" "user"
], ],
[ [
"add_contenttype", "add_contenttype",
"contenttypes", "contenttypes",
"contenttype" "contenttype"
], ],
[ [
"change_contenttype", "change_contenttype",
"contenttypes", "contenttypes",
"contenttype" "contenttype"
], ],
[ [
"delete_contenttype", "delete_contenttype",
"contenttypes", "contenttypes",
"contenttype" "contenttype"
], ],
[ [
"add_document", "add_document",
"documents", "documents",
"document" "document"
], ],
[ [
"can_change_owned_documents", "can_change_owned_documents",
"documents", "documents",
"document" "document"
], ],
[ [
"can_download_from_my_projects", "can_download_from_my_projects",
"documents", "documents",
"document" "document"
], ],
[ [
"can_download_from_other_projects", "can_download_from_other_projects",
"documents", "documents",
"document" "document"
], ],
[ [
"can_view_documents", "can_view_documents",
"documents", "documents",
"document" "document"
], ],
[ [
"change_document", "change_document",
"documents", "documents",
"document" "document"
], ],
[ [
"delete_document", "delete_document",
"documents", "documents",
"document" "document"
], ],
[ [
"add_question", "add_question",
"questions", "questions",
"question" "question"
], ],
[ [
"can_change_owned_question", "can_assign_question_to_myself",
"questions", "questions",
"question" "question"
], ],
[ [
"can_reply_question", "can_assign_question_to_other",
"questions", "questions",
"question" "question"
], ],
[ [
"change_question", "can_change_assigned_question",
"questions", "questions",
"question" "question"
], ],
[ [
"delete_question", "can_change_owned_question",
"questions", "questions",
"question" "question"
], ],
[ [
"add_questionresponse", "can_change_question_state",
"questions", "questions",
"questionresponse" "question"
], ],
[ [
"change_questionresponse", "can_reply_question",
"questions", "questions",
"questionresponse" "question"
], ],
[ [
"delete_questionresponse", "can_view_question",
"questions", "questions",
"questionresponse" "question"
], ],
[ [
"add_issue", "change_question",
"scrum", "questions",
"question"
],
[
"delete_question",
"questions",
"question"
],
[
"add_questionstatus",
"questions",
"questionstatus"
],
[
"change_questionstatus",
"questions",
"questionstatus"
],
[
"delete_questionstatus",
"questions",
"questionstatus"
],
[
"add_attachment",
"scrum",
"attachment"
],
[
"change_attachment",
"scrum",
"attachment"
],
[
"delete_attachment",
"scrum",
"attachment"
],
[
"add_issue",
"scrum",
"issue" "issue"
], ],
[ [
"can_assign_issue_to_myself", "can_assign_issue_to_myself",
"scrum", "scrum",
"issue" "issue"
], ],
[ [
"can_assign_issue_to_other", "can_assign_issue_to_other",
"scrum", "scrum",
"issue" "issue"
], ],
[ [
"can_change_assigned_issue", "can_change_assigned_issue",
"scrum", "scrum",
"issue" "issue"
], ],
[ [
"can_change_issue_state", "can_change_issue_state",
"scrum", "scrum",
"issue" "issue"
], ],
[ [
"can_change_owned_issue", "can_change_owned_issue",
"scrum", "scrum",
"issue" "issue"
], ],
[ [
"can_comment_issue", "can_comment_issue",
"scrum", "scrum",
"issue" "issue"
], ],
[ [
"can_view_issue", "can_view_issue",
"scrum", "scrum",
"issue" "issue"
], ],
[ [
"change_issue", "change_issue",
"scrum", "scrum",
"issue" "issue"
], ],
[ [
"delete_issue", "delete_issue",
"scrum", "scrum",
"issue" "issue"
], ],
[ [
"add_issuestatus", "add_issuestatus",
"scrum", "scrum",
"issuestatus" "issuestatus"
], ],
[ [
"change_issuestatus", "change_issuestatus",
"scrum", "scrum",
"issuestatus" "issuestatus"
], ],
[ [
"delete_issuestatus", "delete_issuestatus",
"scrum", "scrum",
"issuestatus" "issuestatus"
], ],
[ [
"add_issuetype", "add_issuetype",
"scrum", "scrum",
"issuetype" "issuetype"
], ],
[ [
"change_issuetype", "change_issuetype",
"scrum", "scrum",
"issuetype" "issuetype"
], ],
[ [
"delete_issuetype", "delete_issuetype",
"scrum", "scrum",
"issuetype" "issuetype"
], ],
[ [
"add_membership", "add_membership",
"scrum", "scrum",
"membership" "membership"
], ],
[ [
"change_membership", "change_membership",
"scrum", "scrum",
"membership" "membership"
], ],
[ [
"delete_membership", "delete_membership",
"scrum", "scrum",
"membership" "membership"
], ],
[ [
"add_milestone", "add_milestone",
"scrum", "scrum",
"milestone" "milestone"
], ],
[ [
"can_view_milestone", "can_view_milestone",
"scrum", "scrum",
"milestone" "milestone"
], ],
[ [
"change_milestone", "change_milestone",
"scrum", "scrum",
"milestone" "milestone"
], ],
[ [
"delete_milestone", "delete_milestone",
"scrum", "scrum",
"milestone" "milestone"
], ],
[ [
"add_points", "add_points",
"scrum", "scrum",
"points" "points"
], ],
[ [
"change_points", "change_points",
"scrum", "scrum",
"points" "points"
], ],
[ [
"delete_points", "delete_points",
"scrum", "scrum",
"points" "points"
], ],
[ [
"add_priority", "add_priority",
"scrum", "scrum",
"priority" "priority"
], ],
[ [
"change_priority", "change_priority",
"scrum", "scrum",
"priority" "priority"
], ],
[ [
"delete_priority", "delete_priority",
"scrum", "scrum",
"priority" "priority"
], ],
[ [
"add_project", "add_project",
"scrum", "scrum",
"project" "project"
], ],
[ [
"can_list_projects", "can_list_projects",
"scrum", "scrum",
"project" "project"
], ],
[ [
"can_manage_users", "can_manage_users",
"scrum", "scrum",
"project" "project"
], ],
[ [
"can_view_project", "can_view_project",
"scrum", "scrum",
"project" "project"
], ],
[ [
"change_project", "change_project",
"scrum", "scrum",
"project" "project"
], ],
[ [
"delete_project", "delete_project",
"scrum", "scrum",
"project" "project"
], ],
[ [
"add_severity", "add_severity",
"scrum", "scrum",
"severity" "severity"
], ],
[ [
"change_severity", "change_severity",
"scrum", "scrum",
"severity" "severity"
], ],
[ [
"delete_severity", "delete_severity",
"scrum", "scrum",
"severity" "severity"
], ],
[ [
"add_task", "add_task",
"scrum", "scrum",
"task" "task"
], ],
[ [
"can_add_task_to_us", "can_add_task_to_us",
"scrum", "scrum",
"task" "task"
], ],
[ [
"can_assign_task_to_myself", "can_assign_task_to_myself",
"scrum", "scrum",
"task" "task"
], ],
[ [
"can_assign_task_to_other", "can_assign_task_to_other",
"scrum", "scrum",
"task" "task"
], ],
[ [
"can_change_assigned_task", "can_change_assigned_task",
"scrum", "scrum",
"task" "task"
], ],
[ [
"can_change_owned_task", "can_change_owned_task",
"scrum", "scrum",
"task" "task"
], ],
[ [
"can_change_task_state", "can_change_task_state",
"scrum", "scrum",
"task" "task"
], ],
[ [
"can_comment_task", "can_comment_task",
"scrum", "scrum",
"task" "task"
], ],
[ [
"can_view_task", "can_view_task",
"scrum", "scrum",
"task" "task"
], ],
[ [
"change_task", "change_task",
"scrum", "scrum",
"task" "task"
], ],
[ [
"delete_task", "delete_task",
"scrum", "scrum",
"task" "task"
], ],
[ [
"add_taskstatus", "add_taskstatus",
"scrum", "scrum",
"taskstatus" "taskstatus"
], ],
[ [
"change_taskstatus", "change_taskstatus",
"scrum", "scrum",
"taskstatus" "taskstatus"
], ],
[ [
"delete_taskstatus", "delete_taskstatus",
"scrum", "scrum",
"taskstatus" "taskstatus"
], ],
[ [
"add_userstory", "add_userstory",
"scrum", "scrum",
"userstory" "userstory"
], ],
[ [
"can_add_userstory_to_milestones", "can_add_userstory_to_milestones",
"scrum", "scrum",
"userstory" "userstory"
], ],
[ [
"can_change_owned_userstory", "can_change_owned_userstory",
"scrum", "scrum",
"userstory" "userstory"
], ],
[ [
"can_comment_userstory", "can_comment_userstory",
"scrum", "scrum",
"userstory" "userstory"
], ],
[ [
"can_delete_userstory", "can_delete_userstory",
"scrum", "scrum",
"userstory" "userstory"
], ],
[ [
"can_view_userstory", "can_view_userstory",
"scrum", "scrum",
"userstory" "userstory"
], ],
[ [
"change_userstory", "change_userstory",
"scrum", "scrum",
"userstory" "userstory"
], ],
[ [
"delete_userstory", "delete_userstory",
"scrum", "scrum",
"userstory" "userstory"
], ],
[ [
"add_userstorystatus", "add_userstorystatus",
"scrum", "scrum",
"userstorystatus" "userstorystatus"
], ],
[ [
"change_userstorystatus", "change_userstorystatus",
"scrum", "scrum",
"userstorystatus" "userstorystatus"
], ],
[ [
"delete_userstorystatus", "delete_userstorystatus",
"scrum", "scrum",
"userstorystatus" "userstorystatus"
], ],
[ [
"add_session", "add_session",
"sessions", "sessions",
"session" "session"
], ],
[ [
"change_session", "change_session",
"sessions", "sessions",
"session" "session"
], ],
[ [
"delete_session", "delete_session",
"sessions", "sessions",
"session" "session"
], ],
[ [
"add_migrationhistory", "add_migrationhistory",
"south", "south",
"migrationhistory" "migrationhistory"
], ],
[ [
"change_migrationhistory", "change_migrationhistory",
"south", "south",
"migrationhistory" "migrationhistory"
], ],
[ [
"delete_migrationhistory", "delete_migrationhistory",
"south", "south",
"migrationhistory" "migrationhistory"
], ],
[ [
"add_wikipage", "add_wikipage",
"wiki", "wiki",
"wikipage" "wikipage"
], ],
[ [
"can_change_owned_wikipage", "can_change_owned_wikipage",
"wiki", "wiki",
"wikipage" "wikipage"
], ],
[ [
"can_view_wikipage", "can_view_wikipage",
"wiki", "wiki",
"wikipage" "wikipage"
], ],
[ [
"change_wikipage", "change_wikipage",
"wiki", "wiki",
"wikipage" "wikipage"
], ],
[ [
"delete_wikipage", "delete_wikipage",
"wiki", "wiki",
"wikipage" "wikipage"
], ],
[ [
"add_wikipageattachment", "add_wikipageattachment",
"wiki", "wiki",
"wikipageattachment" "wikipageattachment"
], ],
[ [
"change_wikipageattachment", "change_wikipageattachment",
"wiki", "wiki",
"wikipageattachment" "wikipageattachment"
], ],
[ [
"delete_wikipageattachment", "delete_wikipageattachment",
"wiki", "wiki",
"wikipageattachment" "wikipageattachment"
] ]
], ],
"name": "Developer", "name": "Developer",
"slug": "" "slug": ""
} }
} }

View File

@ -1,16 +1,18 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from django.contrib import admin from django.contrib import admin
from greenmine.questions.models import Question, QuestionResponse from greenmine.questions.models import Question, QuestionStatus
import reversion
class QuestionAdmin(admin.ModelAdmin): class QuestionAdmin(reversion.VersionAdmin):
list_display = ["subject", "project", "owner"] list_display = ["subject", "project", "owner"]
admin.site.register(Question, QuestionAdmin) admin.site.register(Question, QuestionAdmin)
class QuestionResponseAdmin(admin.ModelAdmin): class QuestionStatusAdmin(admin.ModelAdmin):
list_display = ["id", "question", "owner"] list_display = ["name", "order", "is_closed", "project"]
admin.site.register(QuestionResponse, QuestionResponseAdmin) admin.site.register(QuestionStatus, QuestionStatusAdmin)

View File

@ -1,32 +1,34 @@
# -*- coding: utf-8 -*-
from rest_framework import generics from rest_framework import generics
from rest_framework.permissions import IsAuthenticated
from greenmine.questions.serializers import QuestionSerializer, QuestionResponseSerializer from greenmine.questions.serializers import QuestionSerializer
from greenmine.questions.models import Question, QuestionResponse from greenmine.questions.models import Question
from greenmine.questions.permissions import QuestionDetailPermission, QuestionResponseDetailPermission from greenmine.questions.permissions import QuestionDetailPermission
import reversion
class QuestionList(generics.ListCreateAPIView): class QuestionList(generics.ListCreateAPIView):
model = Question model = Question
serializer_class = QuestionSerializer serializer_class = QuestionSerializer
filter_fields = ('project',)
permission_classes = (IsAuthenticated,)
def get_queryset(self): def get_queryset(self):
return self.model.objects.filter(project__members=self.request.user) return self.model.objects.filter(project__members=self.request.user)
def pre_save(self, obj):
obj.owner = self.request.user
class QuestionDetail(generics.RetrieveUpdateDestroyAPIView): class QuestionDetail(generics.RetrieveUpdateDestroyAPIView):
model = Question model = Question
serializer_class = QuestionSerializer serializer_class = QuestionSerializer
permission_classes = (QuestionDetailPermission,) permission_classes = (IsAuthenticated, QuestionDetailPermission,)
def post_save(self, obj, created=False):
class QuestionResponseList(generics.ListCreateAPIView): with reversion.create_revision():
model = QuestionResponse if "comment" in self.request.DATA:
serializer_class = QuestionResponseSerializer # Update the comment in the last version
reversion.set_comment(self.request.DATA['comment'])
def get_queryset(self):
return self.model.objects.filter(question__project__members=self.request.user)
class QuestionResponseDetail(generics.RetrieveUpdateDestroyAPIView):
model = QuestionResponse
serializer_class = QuestionResponseSerializer
permission_classes = (QuestionResponseDetailPermission,)

View File

@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
from django.utils.translation import ugettext_lazy as _
QUESTION_STATUS = (
(1, _(u"New"), False),
(2, _(u"Pending"), False),
(3, _(u"Answered"), True),
)

View File

@ -1,15 +1,51 @@
# -*- coding: utf-8 -*-
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.dispatch import receiver
from greenmine.base.utils.slug import slugify_uniquely from greenmine.base.utils.slug import slugify_uniquely, ref_uniquely
from greenmine.base.fields import DictField from greenmine.base.fields import DictField
from greenmine.scrum.models import Project
from picklefield.fields import PickledObjectField
from greenmine.questions.choices import QUESTION_STATUS
class QuestionStatus(models.Model):
name = models.CharField(max_length=255, null=False, blank=False,
verbose_name=_('name'))
order = models.IntegerField(default=10, null=False, blank=False,
verbose_name=_('order'))
is_closed = models.BooleanField(default=False, null=False, blank=True,
verbose_name=_('is closed'))
project = models.ForeignKey(Project, null=False, blank=False,
related_name='question_status',
verbose_name=_('project'))
class Meta:
verbose_name = u'question status'
verbose_name_plural = u'question status'
ordering = ['project', 'name']
unique_together = ('project', 'name')
def __unicode__(self):
return u'project {0} - {1}'.format(self.project_id, self.name)
class Question(models.Model): class Question(models.Model):
subject = models.CharField(max_length=150, null=False, blank=False,
ref = models.BigIntegerField(db_index=True, null=True, blank=True, default=None,
verbose_name=_('ref'))
owner = models.ForeignKey('base.User', null=True, blank=True, default=None,
related_name='owned_questions',
verbose_name=_('owner'))
status = models.ForeignKey('QuestionStatus', null=False, blank=False,
related_name='questions',
verbose_name=_('status'))
subject = models.CharField(max_length=250, null=False, blank=False,
verbose_name=_('subject')) verbose_name=_('subject'))
slug = models.SlugField(unique=True, max_length=250, null=False, blank=True,
verbose_name=_('slug'))
content = models.TextField(null=False, blank=True, content = models.TextField(null=False, blank=True,
verbose_name=_('content')) verbose_name=_('content'))
closed = models.BooleanField(default=False, null=False, blank=True, closed = models.BooleanField(default=False, null=False, blank=True,
@ -18,66 +54,68 @@ class Question(models.Model):
upload_to='messages', upload_to='messages',
verbose_name=_('attached_file')) verbose_name=_('attached_file'))
project = models.ForeignKey('scrum.Project', null=False, blank=False, project = models.ForeignKey('scrum.Project', null=False, blank=False,
related_name='questions') related_name='questions',
verbose_name=_('project'))
milestone = models.ForeignKey('scrum.Milestone', null=True, blank=True, default=None, milestone = models.ForeignKey('scrum.Milestone', null=True, blank=True, default=None,
related_name='questions', related_name='questions',
verbose_name=_('milestone')) verbose_name=_('milestone'))
assigned_to = models.ForeignKey('base.User', null=False, blank=False, finished_date = models.DateTimeField(null=True, blank=True,
verbose_name=_('finished date'))
assigned_to = models.ForeignKey('base.User', null=True, blank=True, default=None,
related_name='questions_assigned_to_me', related_name='questions_assigned_to_me',
verbose_name=_('assigned_to')) verbose_name=_('assigned_to'))
created_date = models.DateTimeField(auto_now_add=True, null=False, blank=False, created_date = models.DateTimeField(auto_now_add=True, null=False, blank=False,
verbose_name=_('created date')) verbose_name=_('created date'))
modified_date = models.DateTimeField(auto_now_add=True, null=False, blank=False, modified_date = models.DateTimeField(auto_now_add=True, null=False, blank=False,
verbose_name=_('modified date')) verbose_name=_('modified date'))
owner = models.ForeignKey('base.User', null=False, blank=False,
related_name='owned_questions')
watchers = models.ManyToManyField('base.User', null=True, blank=True, watchers = models.ManyToManyField('base.User', null=True, blank=True,
related_name='watched_questions', related_name='watched_questions',
verbose_name=_('watchers')) verbose_name=_('watchers'))
tags = DictField(null=False, blank=True, tags = PickledObjectField(null=False, blank=True,
verbose_name=_('tags')) verbose_name=_('tags'))
class Meta: class Meta:
verbose_name = u'question' verbose_name = u'question'
verbose_name_plural = u'questions' verbose_name_plural = u'questions'
ordering = ['project', 'subject', 'id'] ordering = ['project', 'subject', 'id']
#TODO: permissions
permissions = ( permissions = (
('can_reply_question', 'Can reply questions'), ('can_reply_question', 'Can reply questions'),
('can_change_owned_question', 'Can modify owned questions'), ('can_change_owned_question', 'Can modify owned questions'),
('can_change_assigned_question', 'Can modify assigned questions'),
('can_assign_question_to_other', 'Can assign questions to others'),
('can_assign_question_to_myself', 'Can assign questions to myself'),
('can_change_question_state', 'Can change the question state'),
('can_view_question', 'Can view the question'),
) )
def __unicode__(self): def __unicode__(self):
return self.subject return self.subject
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if not self.slug: if self.id:
self.slug = slugify_uniquely(self.subject, self.__class__) self.modified_date = timezone.now()
if not self.ref:
self.ref = ref_uniquely(self.project, 'last_issue_ref', self.__class__)
super(Question, self).save(*args, **kwargs) super(Question, self).save(*args, **kwargs)
class QuestionResponse(models.Model):
content = models.TextField(null=False, blank=False,
verbose_name=_('content'))
created_date = models.DateTimeField(auto_now_add=True, null=False, blank=False,
verbose_name=_('created date'))
modified_date = models.DateTimeField(auto_now=True, null=False, blank=False,
verbose_name=_('modified date'))
attached_file = models.FileField(max_length=500, null=True, blank=True,
upload_to='messages',
verbose_name=_('attached file'))
question = models.ForeignKey('Question', null=False, blank=False,
related_name='responses',
verbose_name=_('question'))
owner = models.ForeignKey('base.User', null=False, blank=False,
related_name='question_responses')
tags = DictField(null=False, blank=True,
verbose_name=_('tags'))
class Meta: # Model related signals handlers
verbose_name = u'question response'
verbose_name_plural = u'question responses'
ordering = ['question', 'created_date']
def __unicode__(self): @receiver(models.signals.post_save, sender=Project, dispatch_uid='project_post_save_add_question_states')
return u'{0} - response {1}'.format(unicode(self.question), self.id) def project_post_save_add_question_states(sender, instance, created, **kwargs):
"""
Create all project model depences on project is
created.
"""
if not created:
return
# Populate new project dependen default data
for order, name, is_closed in QUESTION_STATUS:
QuestionStatus.objects.create(name=name, order=order,
is_closed=is_closed, project=instance)

View File

@ -1,15 +1,11 @@
from greenmine.base.permissions import BaseDetailPermission from greenmine.base.permissions import BaseDetailPermission
class QuestionDetailPermission(BaseDetailPermission): class QuestionDetailPermission(BaseDetailPermission):
get_permission = "can_view_question" get_permission = "can_view_question"
put_permission = "can_change_question" put_permission = "change_question"
delete_permission = "can_delete_question" patch_permission = "change_question"
delete_permission = "delete_question"
safe_methods = ['HEAD', 'OPTIONS'] safe_methods = ['HEAD', 'OPTIONS']
path_to_document = [] path_to_project = []
class QuestionResponseDetailPermission(BaseDetailPermission):
get_permission = "can_view_questionresponse"
put_permission = "can_change_questionresponse"
delete_permission = "can_delete_questionresponse"
safe_methods = ['HEAD', 'OPTIONS']
path_to_document = []

View File

@ -1,15 +1,58 @@
# -*- coding: utf-8 -*-
from rest_framework import serializers from rest_framework import serializers
from greenmine.questions.models import Question, QuestionResponse from greenmine.questions.models import Question
from greenmine.scrum.serializers import PickleField
import reversion
class QuestionSerializer(serializers.ModelSerializer): class QuestionSerializer(serializers.ModelSerializer):
tags = PickleField()
comment = serializers.SerializerMethodField('get_comment')
history = serializers.SerializerMethodField('get_history')
class Meta: class Meta:
model = Question model = Question
fields = () fields = ()
def get_comment(self, obj):
return ''
class QuestionResponseSerializer(serializers.ModelSerializer): def get_questions_diff(self, old_question_version, new_question_version):
class Meta: old_obj = old_question_version.field_dict
model = QuestionResponse new_obj = new_question_version.field_dict
fields = ()
diff_dict = {
'modified_date': new_obj['modified_date'],
'by': old_question_version.revision.user,
'comment': old_question_version.revision.comment,
}
for key in old_obj.keys():
if key == 'modified_date':
continue
if old_obj[key] == new_obj[key]:
continue
diff_dict[key] = {
'old': old_obj[key],
'new': new_obj[key],
}
return diff_dict
def get_history(self, obj):
diff_list = []
current = None
for version in reversed(list(reversion.get_for_object(obj))):
if current:
questions_diff = self.get_questions_diff(version, current)
diff_list.append(questions_diff)
current = version
return diff_list

View File

@ -6,7 +6,5 @@ from greenmine.questions import api
urlpatterns = format_suffix_patterns(patterns('', urlpatterns = format_suffix_patterns(patterns('',
url(r'^questions/$', api.QuestionList.as_view(), name='question-list'), url(r'^questions/$', api.QuestionList.as_view(), name='question-list'),
url(r'^questions/(?P<pk>[0-9]+)/$', api.QuestionDetail.as_view(), name='question-detail'), url(r'^questions/(?P<pk>[0-9]+)/$', api.QuestionDetail.as_view(), name='question-detail'),
url(r'^question_responses/$', api.QuestionResponseList.as_view(), name='question-response-list'),
url(r'^question_responses/(?P<pk>[0-9]+)/$', api.QuestionResponseDetail.as_view(), name='question-response-detail'),
)) ))

View File

@ -11,6 +11,7 @@ from django.contrib.webdesign import lorem_ipsum
from greenmine.base.models import User, Role from greenmine.base.models import User, Role
from greenmine.scrum.models import * from greenmine.scrum.models import *
from greenmine.questions.models import *
subjects = [ subjects = [
"Fixing templates for Django 1.2.", "Fixing templates for Django 1.2.",
@ -146,3 +147,19 @@ class Command(BaseCommand):
bug.tags.append(tag) bug.tags.append(tag)
bug.save() bug.save()
# create questions.
for y in xrange(20):
question = Question.objects.create(
project=project,
subject=lorem_ipsum.words(random.randint(1, 5), common=False),
content=lorem_ipsum.words(random.randint(1, 15), common=False),
owner=project.owner,
status=QuestionStatus.objects.get(project=project, order=1),
tags=[],
)
for tag in lorem_ipsum.words(random.randint(1, 5), common=True).split(" "):
question.tags.append(tag)
question.save()

View File

@ -1,3 +1,5 @@
# -*- coding: utf-8 -*-
from rest_framework import serializers from rest_framework import serializers
from greenmine.scrum.models import * from greenmine.scrum.models import *