【问题标题】:How to handle files in Django Rest Framework?如何处理 Django Rest Framework 中的文件?
【发布时间】:2020-07-14 12:59:19
【问题描述】:

我正在构建一个 Angular + Django 项目,我需要向它添加一些文件,这个想法是这个模型 Ticket 应该接收一些文件,如 imgs 或 pdf... 我应该在模型中使用哪个字段?文件字段?

class Ticket (models.Model):
    titulo = models.CharField(max_length=100, blank=True)
    estagio = models.ForeignKey(
        Estagio, related_name='tickets', on_delete=models.CASCADE, null=True)
    cliente = models.ForeignKey(Cliente, on_delete=models.CASCADE, null=True)
    org = models.ForeignKey(Organizacao, on_delete=models.CASCADE, null=True)
    produto = models.ManyToManyField(Produto)
    valorestimado = models.IntegerField(null=True)
    termometro = models.CharField(max_length=100, null=True, blank=True)
    vendedor = models.ForeignKey(
        Vendedor,  on_delete=models.CASCADE, null=True)
    vendedorext = models.ManyToManyField(
        VendedorExt, related_name='leads', blank=True)
    obs = models.ManyToManyField(Obs, related_name='tickets')
    status = models.CharField(max_length=155, blank=True, default='Aberto')
    mtvperd = models.CharField(max_length=155, null=True, blank=True)
    cmtperd = models.CharField(max_length=155, null=True, blank=True)
    created = models.ForeignKey(Created, on_delete=models.CASCADE, null=True)
    updated = models.ManyToManyField(Updated)

    def __str__(self):
        return str(self.titulo)

我怎样才能在视图中处理这个img? :

class TicketViewSet(viewsets.ModelViewSet):

    queryset = Ticket.objects.all().order_by('-id')
    serializer_class = TicketSerializer
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]

    def create(self, request):
        data = request.data

        print(data['titulo'])
        print(request.user)
        print(request.headers)

        c = Created()
        c.user = request.user
        c.save()
        V = Vendedor.objects.get(id=int(data['vendedor']))
        print(V)

        T = Ticket()
        T.titulo = data['titulo']
        T.estagio = Estagio.objects.get(id=int(data['estagio']))
        T.cliente = Cliente.objects.get(id=int(data['cliente']))
        T.org = Organizacao.objects.get(id=int(data['org']))
        T.valorestimado = int(data['valorestimado'])
        T.termometro = data['termometro']
        T.vendedor = V
        T.status = 'Aberto'

        T.created = c
        T.save()
        try:
            if data['obs'].length >= 1:
                for i in data['obs']:
                    k = Obs()
                    k.texto = i
                    k.save()
                    T.obs.add(k)
                    T.save()
        except:
            k = Obs()
            k.texto = data['obs']
            k.save()
            T.obs.add(k)
            T.save()

        produtos = data['produto']
        for prod in produtos:
            T.produto.add(Produto.objects.get(id=prod))

        T.save()
        print(data)
        return JsonResponse({'message': 'Saved'})

另外,这是将文件发送到 API 的正确方法吗?

  <form>
    <label id="thumbnail">
      <input type="file" name="attachments[dummy][file]"  class="file_selector" multiple="multiple"/>
    </label>
    <button class="btn btn-success" (click)="formAnexo()" style="float: right;">Salvar Anexo</button>
  </form>

对不起,如果我错过了一些明显的东西,那是第一次使用 Django 处理文件

【问题讨论】:

    标签: django angular django-models django-rest-framework django-views


    【解决方案1】:

    如果您必须将多个文件附加到同一资源,我建议您创建一个单独的表。例如,如果您想将多张图片上传到票务资源,您可以这样做:

    class Photo(models.Model):
        file = models.ImageField(
            upload_to='photos',
            null=False,
            max_length=100
        )
        created_at = models.DateTimeField(
            auto_now_add=True,
            db_index=True
        )
    
        class Meta:
            ordering = ['-created_at']
    

    然后在您的票证模型上定义:

    class Ticket(models.Model):
        photos = models.ManyToManyField(
            'app_label.Photo',
            blank=True,
            related_name='ticket_photos'
        )
        ...
    

    为了存储照片,我会考虑使用 AWS S3 之类的解决方案,使用 Django storages 设置它真的很容易。

    要使用 Angular 在前端上传图片,您需要使用 FormData API 并将数据上传为 multipart/form-data

    这是一个代码示例:

    @Injectable({ providedIn: 'root' })
    export class MyService {
    
      constructor(
        private _http: HttpClient
      ) { }
    
      postFile(path: string, file: File, data?: any): Observable<any> {
        const uploadData = new FormData();
        uploadData.append('file', file, file.name);
    
        if (data) {
          Object.keys(data).forEach(key => {
            uploadData.append(key, data[key]);
          });
        }
        return this._http.post(
          path,
          uploadData
        );
      }
    }
    

    我希望这可以帮助您入门。

    【讨论】:

      【解决方案2】:

      您必须在视图中使用 FileUploadParser。 https://www.django-rest-framework.org/api-guide/parsers/#basic-usage-example

      parser_classes = (FileUploadParser,)
      

      模型的 FileField 就可以了

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-06
        • 1970-01-01
        • 2018-11-05
        • 2019-02-20
        • 2015-05-11
        • 2023-03-09
        • 2020-06-11
        • 2020-06-28
        相关资源
        最近更新 更多