Source code for classroom.serializers.assignments

from collections import OrderedDict

from django.apps import apps
from django.conf import settings
from django.db import transaction
from django.utils import timezone
from django.utils.translation import ugettext as _
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework.settings import api_settings
from social_core.utils import setting_name

from . import mixins
from .courses import CourseRoleSerializer
from .. import models


[문서]class AssignmentUserSerializer(serializers.ModelSerializer): id = serializers.PrimaryKeyRelatedField( read_only=True, ) name = serializers.CharField( source="user.full_name", read_only=True, label=_("username"), help_text=_("사용자 이름"), ) email = serializers.EmailField( source="user.email", read_only=True, label=_("email address"), help_text=_("사용자 메일주소"), ) idNumber = serializers.SerializerMethodField()
[문서] class Meta: model = models.AssignmentUser fields = [ "id", "name", "email", "locked", "idNumber", ]
# extra_kwargs = { # "type": { # "required": True # } # }
[문서] def get_idNumber(self, instance): return None
[문서]class AssignmentRepositoryUpdateSerializer(mixins.RemoveNullFieldsMixin, serializers.Serializer): commitId = serializers.CharField( source="commit_id", label=models.AssignmentRepository._meta.get_field("commit_id").verbose_name, help_text=models.AssignmentRepository._meta.get_field("commit_id").help_text, )
[문서] def update(self, instance, validated_data): pass
[문서] def create(self, validated_data): pass
[문서]class AssignmentRepositorySerializer(mixins.RemoveNullFieldsMixin, serializers.ModelSerializer): repoWebUrl = serializers.URLField( source="web_url", read_only=True, ) repoHttpUrl = serializers.URLField( source="http_url_to_repo", read_only=True, ) repoSshUrl = serializers.URLField( source="ssh_url_to_repo", read_only=True, ) commitId = serializers.CharField( source="commit_id", required=False, label=models.AssignmentRepository._meta.get_field("commit_id").verbose_name, help_text=models.AssignmentRepository._meta.get_field("commit_id").help_text, )
[문서] class Meta: model = models.AssignmentRepository fields = [ api_settings.URL_FIELD_NAME, "origin", "repoWebUrl", "repoHttpUrl", "repoSshUrl", "branch", "commitId" ] extra_kwargs = { api_settings.URL_FIELD_NAME: { "view_name": "assignments-repo", "lookup_field": "assignment_id", "lookup_url_kwarg": "pk", "read_only": True, }, "branch": { "read_only": True }, "origin": { "required": False, "write_only": True }, }
[문서]class AssignmentSerializer(mixins.RemoveNullFieldsMixin, serializers.ModelSerializer): parent_lookup_kwargs = { 'course_pk': 'course__pk', } nameWithNamespace = serializers.SerializerMethodField( label=_("name with namespace"), help_text=_("클래스의 이름을 포함한 이름 '{{class name}} / {{assignment name}}' 입니다.") ) description = serializers.CharField( source="short_description", # read_only=True, required=False, allow_null=True, label=models.Assignment._meta.get_field("short_description").verbose_name, help_text=models.Assignment._meta.get_field("short_description").help_text, ) path = serializers.CharField( source="slug", # read_only=True, required=True, label=models.Assignment._meta.get_field("slug").verbose_name, help_text=models.Assignment._meta.get_field("slug").help_text, ) pathWithNamespace = serializers.SerializerMethodField( label=_("name with namespace"), help_text=_("클래스의 path를 포함한 경로 '{{class path}} / {{assignment path}}' 입니다.") ) webUrl = serializers.SerializerMethodField( help_text=_("이 수업에 대한 Web URL 주소입니다."), ) readmeFormat = serializers.CharField( source="readme_format", required=False, label=models.Assignment._meta.get_field("readme_format").verbose_name, help_text=models.Assignment._meta.get_field("readme_format").help_text, ) startDate = serializers.DateTimeField( source="start_date", # read_only=True, required=False, allow_null=True, label=models.Assignment._meta.get_field("start_date").verbose_name, help_text=models.Assignment._meta.get_field("start_date").help_text, ) endDate = serializers.DateTimeField( source="end_date", # read_only=True, required=False, allow_null=True, label=models.Assignment._meta.get_field("end_date").verbose_name, help_text=models.Assignment._meta.get_field("end_date").help_text, ) # Fixme 작성자 모델도 수정필요함. author = CourseRoleSerializer( read_only=True, label=_("작성자"), help_text=_("과제를 작성한 자"), ) successBuilds = serializers.IntegerField( source="metadata.builds", read_only=True, label=_("number of success results"), help_text=_("통과한 빌드의 수. 각 학생들이 제출한 최종 결과중에서 통과한 빌드의 집계"), ) submits = serializers.IntegerField( source="metadata.submits", read_only=True, label=_("number of submits"), help_text=_("제출된 과제의 수. 제출 마감일에 과제를 포크한 저장소중 변경사항이 있는 저장소의 수 집계"), ) modifiedAt = serializers.DateTimeField( source="metadata.modified_at", read_only=True, label=models.AssignmentMeta._meta.get_field("modified_at").verbose_name, help_text=models.AssignmentMeta._meta.get_field("modified_at").help_text, ) status = serializers.ChoiceField( read_only=True, choices=models.Assignment.STATUS_CHOICES, label=_("status of assignments"), help_text=_("과제의 상태. hidden: 숨김(Owner만 보임), dormant: 예정, progress: 진행, closed: 종료"), ) repository = AssignmentRepositorySerializer()
[문서] class Meta: model = models.Assignment fields = [ api_settings.URL_FIELD_NAME, "id", "name", "nameWithNamespace", "path", "pathWithNamespace", "description", "webUrl", "readme", "readmeFormat", "startDate", "endDate", "author", "successBuilds", "submits", "modifiedAt", "status", "repository", ] extra_kwargs = { api_settings.URL_FIELD_NAME: { "view_name": "assignments-detail", "lookup_field": "id", "lookup_url_kwarg": "pk", "read_only": True, }, "name": { "required": True }, "readme": { "required": False } }
[문서] @transaction.atomic def update(self, instance: models.Assignment, validated_data): validated_data.pop("metadata", {}) validated_repository = validated_data.pop("repository", {}) super(AssignmentSerializer, self).update(instance, validated_data) gl = apps.get_app_config("classroom").gitlab_admin_api try: git_ref = instance.metadata.git_ref git_ref.refresh(gl) except models.AssignmentGitlabReference.DoesNotExist: models.AssignmentGitlabReference.create_sync(instance.metadata, gl) return instance
[문서] @transaction.atomic def create(self, validated_data): errors = OrderedDict() if "course" in self.context and self.context["course"]: validated_data["course"] = self.context["course"] else: errors.update({ "course": [_("course instance is not found")] }) validated_data.pop("metadata", {}) validated_repository = validated_data.pop("repository", {}) if errors: raise ValidationError(errors) instance = super(AssignmentSerializer, self).create(validated_data) metadata = models.AssignmentMeta.objects.create( assignment=instance, display_order=-1, modified_at=timezone.now(), ) gl = apps.get_app_config("classroom").gitlab_admin_api try: git_ref = metadata.git_ref git_ref.refresh(gl) except models.AssignmentGitlabReference.DoesNotExist: models.AssignmentGitlabReference.create_sync(metadata, gl) repository_url = validated_repository.get("origin") if validated_repository else None if repository_url: if repository_url.startswith( getattr(settings, setting_name("GITLAB_API_URL"))): path = repository_url.split("/")[-1] for project in gl.projects.list(search=path): if project.web_url.startswith(repository_url) or project.http_url_to_repo.startswith( repository_url): fork = project.forks.create({ "namespace": metadata.git_ref.id }) fork = gl.projects.get(id=fork.id, lazy=True) fork.name = _("{name} 템플릿").format(name=instance.name) fork.path = "template" fork.description = instance.short_description fork.jobs_enabled = False fork.wiki_enabled = False fork.snippets_enabled = False fork.issues_enabled = False fork.resolve_outdated_diff_discussions = False fork.shared_runners_enabled = False fork.save() break else: fork = None else: fork = gl.projects.create({ "name": _("{name} 템플릿").format(name=instance.name), "path": "template", "namespace_id": metadata.git_ref.id, "description": instance.short_description, "jobs_enabled": False, "wiki_enabled": True, "snippets_enabled": True, "issues_enabled": False, "resolve_outdated_diff_discussions": False, "shared_runners_enabled": False, "import_url": repository_url, }) else: fork = gl.projects.create({ "name": _("{name} 템플릿").format(name=instance.name), "path": "template", "namespace_id": metadata.git_ref.id, "description": instance.short_description, "jobs_enabled": False, "wiki_enabled": True, "snippets_enabled": True, "issues_enabled": False, "resolve_outdated_diff_discussions": False, "shared_runners_enabled": False, }) if fork is not None: models.AssignmentRepository.objects.create( assignment=instance, origin=validated_repository, # TODO 업로드 처리는 추후 지원 url=fork.web_url, branch=validated_repository["branch"] if "branch" in validated_repository and validated_repository[ "branch"] else "master", data=fork.attributes ) return instance
[문서] def get_nameWithNamespace(self, instance: models.Assignment): try: name = "{} / {}".format(instance.course.info.name, instance.name) except models.CourseInfo.DoesNotExist: return None return name
[문서] def get_pathWithNamespace(self, instance: models.Assignment): try: path = "{} / {}".format(instance.course.info.slug, instance.slug) except models.CourseInfo.DoesNotExist: return None return path
[문서] def get_webUrl(self, instance): try: url_path = "/class/{}/assignment/{}/".format(instance.course.info.slug, instance.slug) except models.CourseInfo.DoesNotExist: return None request = self.context.get("request") if request: return request.build_absolute_uri(url_path) return url_path
# def save(self, **kwargs): # parent_pk = self.context['view'].kwargs['course_pk'] # # v = self.validated_data # # a = models.Assignment( # course=models.Course.objects.get(pk=parent_pk), # name=v['name'], # slug=v['slug'], # short_description=v['short_description'], # readme=v['readme'], # readme_format=v['readme_format'], # start_date=v['start_date'], # end_date=v['end_date']) # self.instance = a # a.clean_fields() # a.save() # # # super(AssignmentSerializer, self).save(**kwargs)
[문서]class AssignmentUserRepositorySerializer(mixins.RemoveNullFieldsMixin, serializers.ModelSerializer): user = AssignmentUserSerializer( source="assignment_map", label=_("student"), help_text=_("이 과제를 포크한 사용자(학생)"), ) repoWebUrl = serializers.URLField( source="web_url", read_only=True, label=_("repository web url"), help_text=_("web url of repository"), ) repoHttpUrl = serializers.URLField( source="http_url_to_repo", read_only=True, label=_("repository http Url"), help_text=_("http url for repository clone using http protocol"), ) repoSshUrl = serializers.URLField( source="ssh_url_to_repo", read_only=True, label=_("repository ssh Url"), help_text=_("ssh url for repository clone using ssh protocol"), ) commitId = serializers.CharField( source="commit_id", label=models.AssignmentRepository._meta.get_field("commit_id").verbose_name, help_text=models.AssignmentRepository._meta.get_field("commit_id").help_text, ) lastSubmittedAt = serializers.DateTimeField( source="last_submitted_at", label=models.AssignmentSubmission._meta.get_field("submitted_at").verbose_name, help_text=models.AssignmentSubmission._meta.get_field("submitted_at").help_text, ) lastBuildStatus = serializers.CharField( source="last_build_status", label=models.AssignmentBuild._meta.get_field("status").verbose_name, help_text=models.AssignmentBuild._meta.get_field("status").help_text, )
[문서] class Meta: model = models.AssignmentUserRepository fields = [ api_settings.URL_FIELD_NAME, "id", "user", "repoWebUrl", "repoHttpUrl", "repoSshUrl", "commitId", "lastSubmittedAt", "lastBuildStatus", "memo", ] extra_kwargs = { api_settings.URL_FIELD_NAME: { "view_name": "assignment_forks-detail", "lookup_field": "id", "lookup_url_kwarg": "pk", "read_only": True, }, }