Exemplo n.º 1
0
    def patch_model(self, request, pk, no_save=False):
        """
        PATCH /adpi/admin/.../{model}/<pk>
        """
        try:
            model = self.get_queryset(request).get(pk=pk)
        except self.MODEL.DoesNotExist:
            return api.not_found()

        update_fields = []
        for panel in self.get_edit_panels(request):
            kwargs = panel.get_edit_kwargs(request)
            if kwargs:
                for key, value in kwargs.items():
                    setattr(model, key, value)
                    update_fields.append(key)

        if not update_fields:
            return api.bad_request(message='No field to update')

        if hasattr(model, 'updated_at'):
            update_fields.append('updated_at')

        if no_save:
            return model
        else:
            model.save()
            return api.ok(data=model.serialize(
                **self.get_serialize_kwargs(request)))
Exemplo n.º 2
0
 def get(self,
         request,
         menu=None,
         pagetypes=None,
         form_name=None,
         panel=None,
         **kwargs):
     if pagetypes:
         project = request.GET.get('project', None)
         return api.ok(data=ProjectPage.serialize_pagetypes(project))
     if form_name == 'edit':
         pagetype = request.GET.get('pagetype')
         Page = ProjectPage.PAGE_TYPES.get(pagetype)
         if not Page:
             return api.ok(data=Form().serialize())
         form = Form(Page.get_edit_panels(), model=Page, form_mode='edit')
         return api.ok(data=form.serialize())
     if form_name == 'empty':
         return api.ok(data=Form().serialize())
     if panel:
         if panel == 'project':
             return api.ok(data=self.PROJECT_SELECT_PANEL.serialize())
         elif panel == 'pagetype':
             return api.ok(data=self.PAGETYPE_SELECT_PANEL.serialize())
         else:
             return api.not_found()
     return super().get(request, form_name=form_name, **kwargs)
Exemplo n.º 3
0
 def get(self, request, pk=None, menu=None, *args, **kwargs):
     if pk and menu:
         try:
             project = self.get_queryset(request).get(pk=pk)
             return api.ok(data=project.menu)
         except self.MODEL.DoesNotExist:
             return api.not_found()
     return super().get(request, pk=pk, **kwargs)
Exemplo n.º 4
0
 def delete_model(self, request, pk):
     try:
         model = self.get_queryset(request).get(pk=pk)
         data = model.serialize()
         model.delete()
         # 删除关联的菜单
         model.menu.delete()
         return api.ok(data=data)
     except self.MODEL.DoesNotExist:
         return api.not_found()
Exemplo n.º 5
0
 def get_model(self, request, pk):
     """
     GET /api/admin/.../{model}/<pk>
     """
     try:
         model = self.get_queryset(request).get(pk=pk)
         return api.ok(data=model.serialize(
             **self.get_serialize_kwargs(request)))
     except self.MODEL.DoesNotExist:
         return api.not_found()
Exemplo n.º 6
0
 def get(self, request, pk=None, form_name=None):
     if form_name is not None:
         if form_name in self.forms:
             return api.ok(data=self.forms[form_name].serialize())
         else:
             return api.not_found()
     if pk is not None:
         return self._get_method(request, pk)
     else:
         return self._list_method(request)
Exemplo n.º 7
0
def delete_file(request, Model, id):
    try:
        file = Model.objects.filter(deleted_at__isnull=True).get(id=id)
        file.delete()
        return api.ok(data=file)
    except Model.DoesNotExist:
        return api.not_found()
    except Exception as e:
        # NOTE 可能是由于其他资源依赖该文件,而相应资源上设置了 on_delete=models.PROTECT
        # 由于该请求仅在管理后台使用,所以可以直接把 exception 输出
        return api.bad_request(message=f'删除失败:{e}')
Exemplo n.º 8
0
    def patch_model(self, request, pk):
        children = request.json.get('children', [])
        try:
            root = self.get_queryset(request).get(pk=pk)
        except self.MODEL.DoesNotExist:
            return api.not_found()

        old_children = list(root.children.all())
        old_ids = {child.id for child in old_children}
        new_ids = {child['id'] for child in children if child['id']}

        children_to_delete = [
            child for child in old_children if child.id not in new_ids
        ]
        children_to_update = [
            child for child in old_children if child.id in new_ids
        ]
        children_to_create = [
            ProjectNavMenu(
                id=None,
                parent_id=child['parent'],
                link_type=child['link_type'],
                link_page_id=child['link_page']
                if child['link_type'] == 'page' else None,
                link_url=child['link_url']
                if child['link_type'] == 'external' else '',
                text=child['text'],
                sort_order=child['sort_order'],
            ) for child in children if not child['id']
        ]
        children_to_update_data = {
            child['id']: child
            for child in children if child['id']
        }
        for child in children_to_update:
            data = children_to_update_data[child.id]
            child.link_type = data['link_type']
            child.link_page_id = data['link_page'] if data[
                'link_type'] == 'page' else None
            child.link_url = data['link_url'] if data[
                'link_url'] == 'external' else ''
            child.text = data['text']
            child.sort_order = data['sort_order']

        for child in children_to_delete:
            child.delete()
        for child in children_to_update:
            child.save()
        for child in children_to_create:
            child.save()

        root.refresh_from_db()
        return api.ok(data=root.serialize())
Exemplo n.º 9
0
def page(request, project_slug, page_id=None):
    try:
        if page_id is None:
            page = ProjectHomepage.objects \
                    .select_related('project', 'project__banner', 'project__menu') \
                    .get(project__slug=project_slug)
        else:
            page = ProjectPage.objects \
                    .select_related('project', 'project__banner', 'project__menu') \
                    .get_subclass(project__slug=project_slug, id=page_id)
    except ProjectPage.DoesNotExist:
        return api.not_found()

    preview = get_boolean_query(request, 'preview', False)
    if page.status != page.STATUSES.published and not preview:
        return api.not_found()

    context = page.get_context(request)
    template = page.get_template(request)

    return render_for_ua(request, template, context=context)
Exemplo n.º 10
0
 def delete_model(self, request, pk):
     """
     DELETE /api/admin/.../{model}/<pk>
     """
     try:
         model = self.get_queryset(request).get(pk=pk)
         # 在删除前序列化。在 multitable-inheritance 的场景中,
         # 删除资源后会导致无法序列化(父类关联的子类已经被删除)。
         data = model.serialize(**self.get_serialize_kwargs(request))
         model.delete()
         return api.ok(data=data)
     except self.MODEL.DoesNotExist:
         return api.not_found()
Exemplo n.º 11
0
def patch_file(request, Model, id):
    try:
        file = Model.objects.filter(deleted_at__isnull=True).get(id=id)
    except Model.DoesNotExist:
        return api.not_found()

    update_fields = []

    for field in ['filename', 'title']:
        if field in request.json:
            value = request.json[field]
            if not value:
                return api.bad_request(message=f'无效的 {field}: {value}')
            update_fields.append(field)
            setattr(file, field, value)

    file.save(update_fields=update_fields)

    return api.ok(data=file, message='文件修改成功')
Exemplo n.º 12
0
def download_file(request, key, model):
    if model == 'image':
        Model = Image
    elif model == 'document':
        Model = Document
    elif model == 'slide':
        Model = Slide
    else:
        raise Exception(f'unknown model: {model}')

    try:
        file = Model.objects.filter(deleted_at__isnull=True).get(key=key)
    except Model.DoesNotExist:
        # TODO should return 404 webpage instead of json
        return api.not_found()

    # as django document claimed, we don't need to open the file with a context manager,
    # FileResponse will close it automatically.
    # see: https://docs.djangoproject.com/en/2.2/ref/request-response/#fileresponse-objects
    return FileResponse(open(file.local_abs_path, 'rb'),
                        as_attachment=True,
                        filename=file.filename)
Exemplo n.º 13
0
def lesson(request, id):
    """
    知享课程培训中的单节课页面

    可以使用 POST 请求发送观看计时以及标记已看到最后一页

    POST /zhixiang/lesson/<int:id>/
    {
        add_watch_time: 10,  // 添加10秒
        watch_end: true, // 可选参数,已观看到最后一页
    }

    回复:
    {
        // 是否标记为已学习,只有当请求中含有 watch_end,且最终状态为 watched,才为 true
        mark_watched: true/false,
        // 数据库中是否为已学习状态
        watched: true/false,
        // 用户累计学习的时长
        watched_seconds: 120,
    }
    """
    if request.method == 'POST':
        seconds = request.json.get('add_watch_time', 0)
        watch_end = request.json.get('watch_end', False)
        try:
            lesson = PresentationLesson.objects.select_related('presentation') \
                     .get(id=id, status=PresentationLesson.STATUSES.published)
        except PresentationLesson.DoesNotExist:
            return api.not_found()

        record = lesson.presentation.add_watch_time(request.user, seconds)
        mark_watched = False

        if watch_end:
            if record.watched_seconds > lesson.presentation.min_watch_seconds:
                record = lesson.presentation.mark_watched(request.user)
                mark_watched = True

        return api.ok(data=dict(
            mark_watched=mark_watched,
            watched=record.watched,
            watched_seconds=record.watched_seconds,
        ))

    try:
        lesson = PresentationLesson.objects \
                .filter(status=PresentationLesson.STATUSES.published) \
                .select_related('course', 'presentation') \
                .prefetch_related('presentation__slides') \
                .get(id=id)
    except PresentationLesson.DoesNotExist:
        return render_for_ua(request, 'cardpc/404.html', status=404)

    lesson.course.fetch_presentationlesson_details(request.user)
    lesson.record = lesson.presentation.get_watch_record(request.user)

    context = dict(
        lesson=lesson,
        course=lesson.course,
        course_lessons=lesson.course.presentationlessons,
    )
    return render_for_ua(request,
                         'cardpc/zhixiang/lesson.html',
                         context=context)
Exemplo n.º 14
0
def get_file(request, Model, id):
    try:
        file = Model.objects.filter(deleted_at__isnull=True).get(id=id)
        return api.ok(data=file.serialize(request=request))
    except Model.DoesNotExist:
        return api.not_found()