diff --git a/greenmine/base/api.py b/greenmine/base/api.py index 0972a726..e831dcd8 100644 --- a/greenmine/base/api.py +++ b/greenmine/base/api.py @@ -44,7 +44,6 @@ class ApiRoot(APIView): 'priorities': reverse('priority-list', request=request, format=format), 'documents': reverse('document-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), 'users': reverse('user-list', request=request, format=format), 'roles': reverse('user-roles', request=request, format=format), diff --git a/greenmine/base/fixtures/initial_data.json b/greenmine/base/fixtures/initial_data.json index 9cfc6c01..7b82e8e2 100644 --- a/greenmine/base/fixtures/initial_data.json +++ b/greenmine/base/fixtures/initial_data.json @@ -1,561 +1,601 @@ [ { - "pk": 1, - "model": "base.role", + "pk": 1, + "model": "base.role", "fields": { "permissions": [ [ - "add_logentry", - "admin", + "add_logentry", + "admin", "logentry" - ], + ], [ - "change_logentry", - "admin", + "change_logentry", + "admin", "logentry" - ], + ], [ - "delete_logentry", - "admin", + "delete_logentry", + "admin", "logentry" - ], + ], [ - "add_group", - "auth", + "add_group", + "auth", "group" - ], + ], [ - "change_group", - "auth", + "change_group", + "auth", "group" - ], + ], [ - "delete_group", - "auth", + "delete_group", + "auth", "group" - ], + ], [ - "add_permission", - "auth", + "add_permission", + "auth", "permission" - ], + ], [ - "change_permission", - "auth", + "change_permission", + "auth", "permission" - ], + ], [ - "delete_permission", - "auth", + "delete_permission", + "auth", "permission" - ], + ], [ - "add_role", - "base", + "add_role", + "base", "role" - ], + ], [ - "change_role", - "base", + "change_role", + "base", "role" - ], + ], [ - "delete_role", - "base", + "delete_role", + "base", "role" - ], + ], [ - "add_user", - "base", + "add_user", + "base", "user" - ], + ], [ - "change_user", - "base", + "change_user", + "base", "user" - ], + ], [ - "delete_user", - "base", + "delete_user", + "base", "user" - ], + ], [ - "add_contenttype", - "contenttypes", + "add_contenttype", + "contenttypes", "contenttype" - ], + ], [ - "change_contenttype", - "contenttypes", + "change_contenttype", + "contenttypes", "contenttype" - ], + ], [ - "delete_contenttype", - "contenttypes", + "delete_contenttype", + "contenttypes", "contenttype" - ], + ], [ - "add_document", - "documents", + "add_document", + "documents", "document" - ], + ], [ - "can_change_owned_documents", - "documents", + "can_change_owned_documents", + "documents", "document" - ], + ], [ - "can_download_from_my_projects", - "documents", + "can_download_from_my_projects", + "documents", "document" - ], + ], [ - "can_download_from_other_projects", - "documents", + "can_download_from_other_projects", + "documents", "document" - ], + ], [ - "can_view_documents", - "documents", + "can_view_documents", + "documents", "document" - ], + ], [ - "change_document", - "documents", + "change_document", + "documents", "document" - ], + ], [ - "delete_document", - "documents", + "delete_document", + "documents", "document" - ], + ], [ - "add_question", - "questions", + "add_question", + "questions", "question" - ], + ], [ - "can_change_owned_question", - "questions", + "can_assign_question_to_myself", + "questions", "question" - ], + ], [ - "can_reply_question", - "questions", + "can_assign_question_to_other", + "questions", "question" - ], + ], [ - "change_question", - "questions", + "can_change_assigned_question", + "questions", "question" - ], + ], [ - "delete_question", - "questions", + "can_change_owned_question", + "questions", "question" - ], + ], [ - "add_questionresponse", - "questions", - "questionresponse" - ], + "can_change_question_state", + "questions", + "question" + ], [ - "change_questionresponse", - "questions", - "questionresponse" - ], + "can_reply_question", + "questions", + "question" + ], [ - "delete_questionresponse", - "questions", - "questionresponse" - ], + "can_view_question", + "questions", + "question" + ], [ - "add_issue", - "scrum", + "change_question", + "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" - ], + ], [ - "can_assign_issue_to_myself", - "scrum", + "can_assign_issue_to_myself", + "scrum", "issue" - ], + ], [ - "can_assign_issue_to_other", - "scrum", + "can_assign_issue_to_other", + "scrum", "issue" - ], + ], [ - "can_change_assigned_issue", - "scrum", + "can_change_assigned_issue", + "scrum", "issue" - ], + ], [ - "can_change_issue_state", - "scrum", + "can_change_issue_state", + "scrum", "issue" - ], + ], [ - "can_change_owned_issue", - "scrum", + "can_change_owned_issue", + "scrum", "issue" - ], + ], [ - "can_comment_issue", - "scrum", + "can_comment_issue", + "scrum", "issue" - ], + ], [ - "can_view_issue", - "scrum", + "can_view_issue", + "scrum", "issue" - ], + ], [ - "change_issue", - "scrum", + "change_issue", + "scrum", "issue" - ], + ], [ - "delete_issue", - "scrum", + "delete_issue", + "scrum", "issue" - ], + ], [ - "add_issuestatus", - "scrum", + "add_issuestatus", + "scrum", "issuestatus" - ], + ], [ - "change_issuestatus", - "scrum", + "change_issuestatus", + "scrum", "issuestatus" - ], + ], [ - "delete_issuestatus", - "scrum", + "delete_issuestatus", + "scrum", "issuestatus" - ], + ], [ - "add_issuetype", - "scrum", + "add_issuetype", + "scrum", "issuetype" - ], + ], [ - "change_issuetype", - "scrum", + "change_issuetype", + "scrum", "issuetype" - ], + ], [ - "delete_issuetype", - "scrum", + "delete_issuetype", + "scrum", "issuetype" - ], + ], [ - "add_membership", - "scrum", + "add_membership", + "scrum", "membership" - ], + ], [ - "change_membership", - "scrum", + "change_membership", + "scrum", "membership" - ], + ], [ - "delete_membership", - "scrum", + "delete_membership", + "scrum", "membership" - ], + ], [ - "add_milestone", - "scrum", + "add_milestone", + "scrum", "milestone" - ], + ], [ - "can_view_milestone", - "scrum", + "can_view_milestone", + "scrum", "milestone" - ], + ], [ - "change_milestone", - "scrum", + "change_milestone", + "scrum", "milestone" - ], + ], [ - "delete_milestone", - "scrum", + "delete_milestone", + "scrum", "milestone" - ], + ], [ - "add_points", - "scrum", + "add_points", + "scrum", "points" - ], + ], [ - "change_points", - "scrum", + "change_points", + "scrum", "points" - ], + ], [ - "delete_points", - "scrum", + "delete_points", + "scrum", "points" - ], + ], [ - "add_priority", - "scrum", + "add_priority", + "scrum", "priority" - ], + ], [ - "change_priority", - "scrum", + "change_priority", + "scrum", "priority" - ], + ], [ - "delete_priority", - "scrum", + "delete_priority", + "scrum", "priority" - ], + ], [ - "add_project", - "scrum", + "add_project", + "scrum", "project" - ], + ], [ - "can_list_projects", - "scrum", + "can_list_projects", + "scrum", "project" - ], + ], [ - "can_manage_users", - "scrum", + "can_manage_users", + "scrum", "project" - ], + ], [ - "can_view_project", - "scrum", + "can_view_project", + "scrum", "project" - ], + ], [ - "change_project", - "scrum", + "change_project", + "scrum", "project" - ], + ], [ - "delete_project", - "scrum", + "delete_project", + "scrum", "project" - ], + ], [ - "add_severity", - "scrum", + "add_severity", + "scrum", "severity" - ], + ], [ - "change_severity", - "scrum", + "change_severity", + "scrum", "severity" - ], + ], [ - "delete_severity", - "scrum", + "delete_severity", + "scrum", "severity" - ], + ], [ - "add_task", - "scrum", + "add_task", + "scrum", "task" - ], + ], [ - "can_add_task_to_us", - "scrum", + "can_add_task_to_us", + "scrum", "task" - ], + ], [ - "can_assign_task_to_myself", - "scrum", + "can_assign_task_to_myself", + "scrum", "task" - ], + ], [ - "can_assign_task_to_other", - "scrum", + "can_assign_task_to_other", + "scrum", "task" - ], + ], [ - "can_change_assigned_task", - "scrum", + "can_change_assigned_task", + "scrum", "task" - ], + ], [ - "can_change_owned_task", - "scrum", + "can_change_owned_task", + "scrum", "task" - ], + ], [ - "can_change_task_state", - "scrum", + "can_change_task_state", + "scrum", "task" - ], + ], [ - "can_comment_task", - "scrum", + "can_comment_task", + "scrum", "task" - ], + ], [ - "can_view_task", - "scrum", + "can_view_task", + "scrum", "task" - ], + ], [ - "change_task", - "scrum", + "change_task", + "scrum", "task" - ], + ], [ - "delete_task", - "scrum", + "delete_task", + "scrum", "task" - ], + ], [ - "add_taskstatus", - "scrum", + "add_taskstatus", + "scrum", "taskstatus" - ], + ], [ - "change_taskstatus", - "scrum", + "change_taskstatus", + "scrum", "taskstatus" - ], + ], [ - "delete_taskstatus", - "scrum", + "delete_taskstatus", + "scrum", "taskstatus" - ], + ], [ - "add_userstory", - "scrum", + "add_userstory", + "scrum", "userstory" - ], + ], [ - "can_add_userstory_to_milestones", - "scrum", + "can_add_userstory_to_milestones", + "scrum", "userstory" - ], + ], [ - "can_change_owned_userstory", - "scrum", + "can_change_owned_userstory", + "scrum", "userstory" - ], + ], [ - "can_comment_userstory", - "scrum", + "can_comment_userstory", + "scrum", "userstory" - ], + ], [ - "can_delete_userstory", - "scrum", + "can_delete_userstory", + "scrum", "userstory" - ], + ], [ - "can_view_userstory", - "scrum", + "can_view_userstory", + "scrum", "userstory" - ], + ], [ - "change_userstory", - "scrum", + "change_userstory", + "scrum", "userstory" - ], + ], [ - "delete_userstory", - "scrum", + "delete_userstory", + "scrum", "userstory" - ], + ], [ - "add_userstorystatus", - "scrum", + "add_userstorystatus", + "scrum", "userstorystatus" - ], + ], [ - "change_userstorystatus", - "scrum", + "change_userstorystatus", + "scrum", "userstorystatus" - ], + ], [ - "delete_userstorystatus", - "scrum", + "delete_userstorystatus", + "scrum", "userstorystatus" - ], + ], [ - "add_session", - "sessions", + "add_session", + "sessions", "session" - ], + ], [ - "change_session", - "sessions", + "change_session", + "sessions", "session" - ], + ], [ - "delete_session", - "sessions", + "delete_session", + "sessions", "session" - ], + ], [ - "add_migrationhistory", - "south", + "add_migrationhistory", + "south", "migrationhistory" - ], + ], [ - "change_migrationhistory", - "south", + "change_migrationhistory", + "south", "migrationhistory" - ], + ], [ - "delete_migrationhistory", - "south", + "delete_migrationhistory", + "south", "migrationhistory" - ], + ], [ - "add_wikipage", - "wiki", + "add_wikipage", + "wiki", "wikipage" - ], + ], [ - "can_change_owned_wikipage", - "wiki", + "can_change_owned_wikipage", + "wiki", "wikipage" - ], + ], [ - "can_view_wikipage", - "wiki", + "can_view_wikipage", + "wiki", "wikipage" - ], + ], [ - "change_wikipage", - "wiki", + "change_wikipage", + "wiki", "wikipage" - ], + ], [ - "delete_wikipage", - "wiki", + "delete_wikipage", + "wiki", "wikipage" - ], + ], [ - "add_wikipageattachment", - "wiki", + "add_wikipageattachment", + "wiki", "wikipageattachment" - ], + ], [ - "change_wikipageattachment", - "wiki", + "change_wikipageattachment", + "wiki", "wikipageattachment" - ], + ], [ - "delete_wikipageattachment", - "wiki", + "delete_wikipageattachment", + "wiki", "wikipageattachment" ] - ], - "name": "Developer", + ], + "name": "Developer", "slug": "" } } diff --git a/greenmine/questions/admin.py b/greenmine/questions/admin.py index b93e733a..2d807148 100644 --- a/greenmine/questions/admin.py +++ b/greenmine/questions/admin.py @@ -1,16 +1,18 @@ # -*- coding: utf-8 -*- 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"] admin.site.register(Question, QuestionAdmin) -class QuestionResponseAdmin(admin.ModelAdmin): - list_display = ["id", "question", "owner"] +class QuestionStatusAdmin(admin.ModelAdmin): + list_display = ["name", "order", "is_closed", "project"] -admin.site.register(QuestionResponse, QuestionResponseAdmin) +admin.site.register(QuestionStatus, QuestionStatusAdmin) diff --git a/greenmine/questions/api.py b/greenmine/questions/api.py index e74c6cf2..83c8d728 100644 --- a/greenmine/questions/api.py +++ b/greenmine/questions/api.py @@ -1,32 +1,34 @@ +# -*- coding: utf-8 -*- from rest_framework import generics +from rest_framework.permissions import IsAuthenticated -from greenmine.questions.serializers import QuestionSerializer, QuestionResponseSerializer -from greenmine.questions.models import Question, QuestionResponse -from greenmine.questions.permissions import QuestionDetailPermission, QuestionResponseDetailPermission +from greenmine.questions.serializers import QuestionSerializer +from greenmine.questions.models import Question +from greenmine.questions.permissions import QuestionDetailPermission +import reversion class QuestionList(generics.ListCreateAPIView): model = Question serializer_class = QuestionSerializer + filter_fields = ('project',) + permission_classes = (IsAuthenticated,) def get_queryset(self): return self.model.objects.filter(project__members=self.request.user) + def pre_save(self, obj): + obj.owner = self.request.user + + class QuestionDetail(generics.RetrieveUpdateDestroyAPIView): model = Question serializer_class = QuestionSerializer - permission_classes = (QuestionDetailPermission,) + permission_classes = (IsAuthenticated, QuestionDetailPermission,) - -class QuestionResponseList(generics.ListCreateAPIView): - model = QuestionResponse - serializer_class = QuestionResponseSerializer - - 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,) + def post_save(self, obj, created=False): + with reversion.create_revision(): + if "comment" in self.request.DATA: + # Update the comment in the last version + reversion.set_comment(self.request.DATA['comment']) diff --git a/greenmine/questions/choices.py b/greenmine/questions/choices.py new file mode 100644 index 00000000..e52b1e78 --- /dev/null +++ b/greenmine/questions/choices.py @@ -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), +) diff --git a/greenmine/questions/models.py b/greenmine/questions/models.py index dd1d8c25..b2d0988e 100644 --- a/greenmine/questions/models.py +++ b/greenmine/questions/models.py @@ -1,15 +1,51 @@ +# -*- coding: utf-8 -*- + from django.db import models 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.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): - 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')) - slug = models.SlugField(unique=True, max_length=250, null=False, blank=True, - verbose_name=_('slug')) content = models.TextField(null=False, blank=True, verbose_name=_('content')) closed = models.BooleanField(default=False, null=False, blank=True, @@ -18,66 +54,68 @@ class Question(models.Model): upload_to='messages', verbose_name=_('attached_file')) 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, related_name='questions', 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', verbose_name=_('assigned_to')) created_date = models.DateTimeField(auto_now_add=True, null=False, blank=False, verbose_name=_('created date')) modified_date = models.DateTimeField(auto_now_add=True, null=False, blank=False, 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, related_name='watched_questions', verbose_name=_('watchers')) - tags = DictField(null=False, blank=True, + tags = PickledObjectField(null=False, blank=True, verbose_name=_('tags')) class Meta: verbose_name = u'question' verbose_name_plural = u'questions' ordering = ['project', 'subject', 'id'] + #TODO: permissions permissions = ( ('can_reply_question', 'Can reply 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): return self.subject def save(self, *args, **kwargs): - if not self.slug: - self.slug = slugify_uniquely(self.subject, self.__class__) + if self.id: + 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) -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: - verbose_name = u'question response' - verbose_name_plural = u'question responses' - ordering = ['question', 'created_date'] +# Model related signals handlers - def __unicode__(self): - return u'{0} - response {1}'.format(unicode(self.question), self.id) +@receiver(models.signals.post_save, sender=Project, dispatch_uid='project_post_save_add_question_states') +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) diff --git a/greenmine/questions/permissions.py b/greenmine/questions/permissions.py index fedf72fe..b276fd41 100644 --- a/greenmine/questions/permissions.py +++ b/greenmine/questions/permissions.py @@ -1,15 +1,11 @@ from greenmine.base.permissions import BaseDetailPermission + class QuestionDetailPermission(BaseDetailPermission): get_permission = "can_view_question" - put_permission = "can_change_question" - delete_permission = "can_delete_question" + put_permission = "change_question" + patch_permission = "change_question" + delete_permission = "delete_question" 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 = [] diff --git a/greenmine/questions/serializers.py b/greenmine/questions/serializers.py index 83d59b41..412c1652 100644 --- a/greenmine/questions/serializers.py +++ b/greenmine/questions/serializers.py @@ -1,15 +1,58 @@ +# -*- coding: utf-8 -*- + 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): + tags = PickleField() + comment = serializers.SerializerMethodField('get_comment') + history = serializers.SerializerMethodField('get_history') + class Meta: model = Question fields = () + def get_comment(self, obj): + return '' -class QuestionResponseSerializer(serializers.ModelSerializer): - class Meta: - model = QuestionResponse - fields = () + def get_questions_diff(self, old_question_version, new_question_version): + old_obj = old_question_version.field_dict + new_obj = new_question_version.field_dict + + 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 diff --git a/greenmine/questions/urls.py b/greenmine/questions/urls.py index 80085fa7..9eef951c 100644 --- a/greenmine/questions/urls.py +++ b/greenmine/questions/urls.py @@ -6,7 +6,5 @@ from greenmine.questions import api urlpatterns = format_suffix_patterns(patterns('', url(r'^questions/$', api.QuestionList.as_view(), name='question-list'), url(r'^questions/(?P[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[0-9]+)/$', api.QuestionResponseDetail.as_view(), name='question-response-detail'), )) diff --git a/greenmine/scrum/management/commands/sample_data.py b/greenmine/scrum/management/commands/sample_data.py index 3e82877b..290499da 100644 --- a/greenmine/scrum/management/commands/sample_data.py +++ b/greenmine/scrum/management/commands/sample_data.py @@ -11,6 +11,7 @@ from django.contrib.webdesign import lorem_ipsum from greenmine.base.models import User, Role from greenmine.scrum.models import * +from greenmine.questions.models import * subjects = [ "Fixing templates for Django 1.2.", @@ -146,3 +147,19 @@ class Command(BaseCommand): bug.tags.append(tag) 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() diff --git a/greenmine/scrum/serializers.py b/greenmine/scrum/serializers.py index 964b1a15..c25f3989 100644 --- a/greenmine/scrum/serializers.py +++ b/greenmine/scrum/serializers.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + from rest_framework import serializers from greenmine.scrum.models import *