class PolyvVideoAdminView(AdminView): MODEL = PolyvVideo ORDER_BY = ['-id'] USE_PAGINATION = True QUERYSET_SELECT_RELATED = [ 'owner', 'thumbnail', 'thumbnail__owner', ] SEARCH_FORM = Form([ panels.TextPanel('title', search_op='icontains'), panels.TextPanel('vid'), ], model=MODEL, form_mode='search') EDIT_FORM = Form([ panels.TextPanel('title'), panels.TextPanel('vid'), panels.TextPanel('duration'), panels.SwitchPanel('login_required'), panels.ImageUploaderPanel('thumbnail', bucket='thumbnails'), ], model=MODEL, form_mode='edit') def get_extra_create_kwargs(self, request): return dict(owner=request.user)
def get_edit_panels(cls): return super().get_edit_panels() + [ panels.TextPanel('title'), panels.TextPanel('author_name'), panels.ImageUploaderPanel('cover_picture', bucket='project'), panels.DateTimePickerPanel('publish_time'), ProjectPageAttachmentPanel('attachments', bucket='project-attachments'), panels.RichTextPanel('excerpt'), panels.RichTextPanel('content'), ]
class ProjectCarouselItemAdminView(AdminView): MODEL = ProjectCarouselItem QUERYSET_PREFETCH_RELATED = [ 'image', ] SEARCH_FORM = Form([ panels.SelectPanel('project_homepage', label='', help_text=''), ], model=MODEL, form_mode='search') EDIT_FORM = Form([ panels.ImageUploaderPanel('image', bucket='carousel'), panels.TextPanel('title'), panels.TextPanel('link_url'), ], model=MODEL, form_mode='edit')
class PresentationLessonAdminView(AdminView): MODEL = PresentationLesson ORDER_BY = ['-id'] USE_PAGINATION = True QUERYSET_SELECT_RELATED = [ 'course', 'course__owner', 'course__thumbnail', 'course__thumbnail__owner', 'teacher_picture', 'teacher_picture__owner', 'presentation', 'presentation__owner', 'presentation__thumbnail', 'presentation__thumbnail__owner', ] QUERYSET_PREFETCH_RELATED = [ 'attachments', 'presentation__slides', ] SEARCH_FORM = Form([ panels.TextPanel('title', search_op='icontains'), panels.SelectPanel('status'), ], model=MODEL, form_mode='search') EDIT_FORM = Form([ panels.DividerPanel('基本信息'), panels.SelectPanel('course', choices=choices.ApiChoices('api-course-courses', label_field='title')), panels.TextPanel('title', validators=[validators.TextLengthValidator(max=30)]), panels.RichTextPanel('summary'), panels.SelectPanel('status'), panels.SelectPanel('presentation', choices=choices.ApiChoices('api-media-presentations', label_field='title')), # TODO implement attachments (ManyToManyField Chooser) panels.DividerPanel('讲者信息'), panels.TextPanel('teacher_name', required=False), panels.TextPanel('teacher_organization', required=False), panels.ImageUploaderPanel('teacher_picture', bucket='thumbnails', required=False), panels.RichTextPanel('teacher_introduction', required=False), ], model=MODEL, form_mode='edit')
class CourseAdminView(AdminView): MODEL = Course ORDER_BY = ['-id'] USE_PAGINATION = True QUERYSET_SELECT_RELATED = [ 'owner', 'thumbnail', 'thumbnail__owner', ] SEARCH_FORM = Form([ panels.TextPanel('title', search_op='icontains'), ], model=MODEL, form_mode='search') EDIT_FORM = Form([ panels.TextPanel('title'), panels.RichTextPanel('introduction'), panels.ImageUploaderPanel('thumbnail', bucket='thumbnails'), ], model=MODEL, form_mode='edit') def get_extra_create_kwargs(self, request): return dict(owner=request.user)
class NewsAdminView(AdminView): MODEL = ZhixiangNews ORDER_BY = ['-id'] USE_PAGINATION = True QUERYSET_SELECT_RELATED = ['thumbnail'] SEARCH_FORM = Form([ panels.TextPanel('title', search_op='icontains'), panels.TextPanel('author_name', search_op='icontains'), panels.DateRangePanel('publish_time', form_field_name='publish_range'), ], model=MODEL, form_mode='search') EDIT_FORM = Form([ panels.TextPanel('title'), panels.TextPanel('author_name'), panels.ImageUploaderPanel('thumbnail', bucket='thumbnails'), panels.DateTimePickerPanel('publish_time'), panels.RichTextPanel('content'), ], model=MODEL, form_mode='edit')
class ProjectAdminView(AdminView): MODEL = Project QUERYSET_SELECT_RELATED = [ 'banner', 'menu', 'menu__link_page', ] QUERYSET_PREFETCH_RELATED = [ 'menu__children', 'menu__children__link_page', ] SEARCH_FORM = Form([ panels.TextPanel('title'), ], model=MODEL, form_mode='search') EDIT_FORM = Form([ panels.TextPanel('title'), panels.TextPanel('slug'), panels.RichTextPanel('introduction'), panels.ImageUploaderPanel('banner', bucket='banner'), panels.ImageUploaderPanel('banner_background', bucket='banner'), ProjectThemeColorPickerPanel('theme_colors'), ], model=MODEL, form_mode='edit') @transaction.atomic def create_model(self, request): create_args = super().create_model(request, no_save=True) # 创建菜单 create_args['menu'] = ProjectNavMenu.objects.create() project = self.MODEL.objects.create(**create_args) # 创建首页 ProjectHomepage.objects.create( project=project, status=ProjectHomepage.STATUSES.published) return api.ok(data=project) @transaction.atomic 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(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) @classmethod def urls(cls, base, app): return super().urls(base, app) + [ path(f'{base}/<int:pk>/menu', cls.as_view(), name=f'{app}-{base}-menu', kwargs=dict(menu=True)), ]
class PresentationAdminView(AdminView): MODEL = Presentation ORDER_BY = ['-id'] USE_PAGINATION = True QUERYSET_SELECT_RELATED = [ 'owner', 'thumbnail', 'thumbnail__owner', ] QUERYSET_PREFETCH_RELATED = ['slides'] SEARCH_FORM = Form([panels.TextPanel('title', search_op='icontains')], model=MODEL, form_mode='search') EDIT_FORM = Form([ panels.TextPanel('title'), TimeSliderPanel('min_watch_seconds'), panels.ImageUploaderPanel('thumbnail', bucket='thumbnails'), SlidesUploaderPanel('slides'), ], model=MODEL, form_mode='edit') def get_extra_create_kwargs(self, request): return dict(owner=request.user) def set_slides(self, presentation, slide_ids): # 对于PPT的图片,我们做如下处理: # * 获取当前所有的图片(对于 create 来说,应该是空的) # * 将所有图片的 presentation 置为空,sort_order 置为 null # * 获取用户提交的所有图片列表 # * 将用户提交的所有图片设置正确的 presentation 以及 sort_order # * 保存所有涉及到的图片的修改 # 我们维护一个 slides_to_update 字典,key 为 slide 的 id,方便记录 slides_to_update = list(presentation.slides.all()) slides_to_update = {slide.id: slide for slide in slides_to_update} slides = list(Slide.objects.filter(id__in=slide_ids)) for slide in slides: slides_to_update[slide.id] = slide for slide in slides_to_update.values(): slide.presentation = None slide.sort_order = None sort_order = 1 for slide_id in slide_ids: # TODO if slide_id does not exist, it means the frontend passed in a non-exist slide id slide = slides_to_update[slide_id] slide.presentation = presentation slide.sort_order = sort_order sort_order += 1 Slide.objects.bulk_update(slides_to_update.values(), ['presentation', 'sort_order']) def create_model(self, request): create_args = super().create_model(request, no_save=True) model = self.MODEL.objects.create(**create_args) self.set_slides(model, request.json.get('slides', [])) return api.ok(data=model) def patch_model(self, request, pk): model = super().patch_model(request, pk, no_save=True) model.save() self.set_slides(model, request.json.get('slides', [])) return api.ok(data=model)