无文章ID时如何为编辑器中的文章上传文档?
解决方案:文章未创建时的文件上传问题
方案1:允许文件先独立上传,后续关联文章
修改DocumentModel的外键字段,允许文件暂时不绑定文章,待文章创建后自动关联。
模型修改
# documentmodels.py class DocumentModel(models.Model): id=models.AutoField(primary_key=True, auto_created=True, verbose_name="DOCUMENT_ID") user_fk_doc=models.ForeignKey(User, on_delete=models.CASCADE, related_name="users_fk_doc") # 新增null=True, blank=True,允许外键为空 article_fk_doc=models.ForeignKey(Article, on_delete=models.CASCADE, related_name="articles_fk_doc", null=True, blank=True) document=models.FileField(max_length=350, validators=[FileExtensionValidator(extensions)], upload_to=uploaded_files) filename=models.CharField(max_length=100, blank=True) filesize=models.IntegerField(default=0, blank=True) mimetype=models.CharField(max_length=100, blank=True) created_at=models.DateField(auto_now_add=True)
文章创建时自动绑定未关联文件
在ArticleViewSet中重写创建逻辑,新文章生成后,批量将当前用户未绑定的文件关联到该文章:
# Article views.py from rest_framework import status class ArticleViewSet(viewsets.ModelViewSet): queryset=Article.objects.all() serializer_class=ArticleSerializer permission_classes=[permissions.IsAuthenticated] authentication_classes = [authentication.TokenAuthentication] def create(self, request, *args, **kwargs): # 先完成文章创建 response = super().create(request, *args, **kwargs) # 批量更新当前用户未关联文章的文件 DocumentModel.objects.filter( user_fk_doc=request.user, article_fk_doc__isnull=True ).update(article_fk_doc=response.data['id']) return response
补充:建议添加定时任务(如Celery),清理超过7天未关联文章的冗余文件,避免存储浪费。
方案2:先创建草稿文章,再上传文件
利用现有Article模型的isDraft字段,用户进入编辑器时自动生成草稿文章,拿到文章ID后再上传文件,编辑完成后更新草稿状态。
新增草稿创建接口
在ArticleViewSet中添加生成草稿的action:
# Article views.py from rest_framework.decorators import action class ArticleViewSet(viewsets.ModelViewSet): # ... 原有代码 ... @action(detail=False, methods=['post'], url_path='create-draft') def create_draft(self, request): # 生成默认草稿数据 draft_data = { 'headline': '临时草稿', 'isDraft': True, 'created_by': request.user.id } serializer = self.get_serializer(data=draft_data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) return Response(serializer.data, status=status.HTTP_201_CREATED)
前端流程
- 用户进入编辑器时,先调用
/articles/create-draft/接口获取草稿ID - 上传文件时,将该ID作为
article_fk_doc参数传入 - 编辑完成后,调用文章更新接口,修改标题、内容等字段,并将
isDraft设为False
方案3:临时存储文件,创建文章后再迁移
新增临时文件模型存储未绑定的文件,待文章创建后,将文件迁移到正式目录并关联文章。
新增临时文件模型
# documentmodels.py class TemporaryDocument(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) document = models.FileField(upload_to='temp_files/') filename = models.CharField(max_length=100, blank=True) filesize = models.IntegerField(default=0, blank=True) mimetype = models.CharField(max_length=100, blank=True) created_at = models.DateTimeField(auto_now_add=True)
临时上传与迁移逻辑
- 新增临时文件上传视图,处理用户上传请求
# document views.py from rest_framework.views import APIView class TemporaryDocumentUploadView(APIView): permission_classes=[permissions.IsAuthenticated] authentication_classes= [authentication.TokenAuthentication] parser_classes=[FormParser, MultiPartParser] def post(self, request): serializer = TemporaryDocumentSerializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save(user=request.user) return Response(serializer.data, status=status.HTTP_201_CREATED)
- 文章创建时迁移临时文件到正式目录
# Article views.py import os from django.core.files.storage import default_storage class ArticleViewSet(viewsets.ModelViewSet): # ... 原有代码 ... def create(self, request, *args, **kwargs): response = super().create(request, *args, **kwargs) article_id = response.data['id'] # 处理当前用户的临时文件 temp_docs = TemporaryDocument.objects.filter(user=request.user) for temp_doc in temp_docs: # 复制文件到正式存储目录 new_file_path = default_storage.save( f'uploaded_files/{temp_doc.filename}', temp_doc.document ) # 创建正式文件记录并关联文章 DocumentModel.objects.create( user_fk_doc=request.user, article_fk_doc_id=article_id, document=new_file_path, filename=temp_doc.filename, filesize=temp_doc.filesize, mimetype=temp_doc.mimetype ) # 删除临时文件及记录 temp_doc.document.delete() temp_doc.delete() return response
内容的提问来源于stack exchange,提问作者Abdullah Roshan
相关产品推荐
相关产品推荐

