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)))
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)
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)
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()
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()
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)
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}')
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())
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)
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()
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='文件修改成功')
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)
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)
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()