使用drf的时候, 保存图片, 可以使用models.ImageField
, 然后使用表单提交. 但是有的时候一个model对应多张图片. 比方说创建一个作品, 这个作品有7页图片需要保存.
那首先应该建立两张表, 一张works作品表, 一张works_file作品文件表.并在works_file中设置外键关联到作品表. 并且works_file中要有字段保存页码信息,防止混乱.
class Works(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.DO_NOTHING, db_constraint=False)
title = models.CharField(max_length=200, verbose_name="标题")
update_time = models.DateTimeField(verbose_name="更新时间", default=datetime.now)
class Meta:
verbose_name = "作品"
verbose_name_plural = verbose_name
ordering = ("update_time",)
def upload_to(instance, filename):
return "/".join(["work_file", f'{datetime.now().strftime("%Y%m%d_%H%M%S")}__{filename}'])
class WorksFile(models.Model):
id = models.AutoField(primary_key=True)
work_file = models.FileField(verbose_name="文件", upload_to=upload_to)
rank_num = models.PositiveIntegerField(verbose_name='序号')
works = models.ForeignKey(Works, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name="所属作品")
update_time = models.DateTimeField(verbose_name="更新时间", default=datetime.now)
class Meta:
verbose_name = "作品文件"
ordering = ("rank_num",)
然后创建作品的时候,同时多张保存作品图片,可以复写serializers.py
中的create
方法
class WorksMeSerializer(serializers.ModelSerializer):
id = serializers.ReadOnlyField()
user = serializers.HiddenField(default=serializers.CurrentUserDefault())
update_time = serializers.ReadOnlyField()
works_files = WorksFileSerializer(source='worksfile_set', many=True, read_only=True, label="作品文件")
class Meta:
model = Works
fields = ("id", "user", "title", 'update_time', "works_files")
def create(self, validated_data):
work_files = self.context.get("view").request.FILES
works = Works.objects.create(**validated_data)
for i, work_file in enumerate(work_files.getlist("work_files"), start=1):
WorksFile.objects.create(works=works, work_file=work_file, rank_num=i)
return works
里面通过context取出request来, 再取出所有图片, 并保存.
还有一个问题, ArrayField在前端展示和接受请求的时候会有问题. 所以针对ArrayField可以指定serializer的Field为自定义的Field
utils.myfield.py
# -*- coding: utf-8 -*-
__author__ = '陈章'
__date__ = '2019/8/29 12:58'
from rest_framework.fields import Field
class StringArrayField(Field):
"""
String representation of an array field.
"""
def to_representation(self, obj):
# convert list to string
return ",".join([str(element) for element in obj])
def to_internal_value(self, data):
data = data.split(",") # convert string to list
return data
serializer.py
class WorksMeSerializer(serializers.ModelSerializer):
id = serializers.ReadOnlyField()
user = serializers.HiddenField(default=serializers.CurrentUserDefault())
styles = StringArrayField()
instruments = StringArrayField()