我有以下用例。我希望能够拥有一个包含许多文件的项目,因此我创建了一个模型来存储文件和另一个模型来存储项目,例如,您还可以将图像上传到Item
:
models.py
class File(models.Model):
"""Class to represent a file."""
name = models.TextField()
file = models.FileField(upload_to='item_attachments/%Y/%m/%d/')
item = models.ForeignKey("Item", on_delete=models.CASCADE, related_name='attachments', null=True)
added_on = models.DateTimeField(auto_now_add=True)
class Item(models.Model):
"""Class to represent an item..."""
label = models.TextField(null=True)
photo = models.ImageField(null=True, upload_to='item_images/%Y/%m/%d/')
name = models.TextField()
然后我创建我的序列化程序:
serializers.py
class FileSerializer(serializers.ModelSerializer):
"""Serializer for File."""
class Meta: # pylint: disable=too-few-public-methods
"""Class to represent metadata of the object."""
model = File
fields = [ 'id', 'name', 'file', 'added_on', 'item' ]
class ItemSerializer(serializers.ModelSerializer):
"""Serializer for Item."""
attachments = FileSerializer(
many=True,
allow_null=True,
required = False
)
class Meta: # pylint: disable=too-few-public-methods
"""Class to represent metadata of the object."""
model = Item
fields = [ 'id', 'label', 'photo', 'name', 'attachments']
read_only_fields = ['id']
def create(self, validated_data):
obj = Item.objects.create(**validated_data)
print(self)
print(validated_data)
return obj
最后我创建了 REST 端点:
views.py
class FileViewset(viewsets.ModelViewSet): # pylint: disable=too-many-ancestors
"""API Endpoint to return the list of categories"""
queryset = File.objects.all()
serializer_class = FileSerializer
pagination_class = None
class ItemViewset(viewsets.ModelViewSet): # pylint: disable=too-many-ancestors
"""API Endpoint to return the list of items"""
queryset = Item.objects.all()
serializer_class = ItemSerializer
我可以做一个 POST
,FileViewset
它工作得很好:
如果我尝试POST
使用附件执行该项目,它不起作用,它会为附件留下一个空数组:
所以经过一些研究,我认为我必须覆盖该create
方法。但是当我尝试执行该步骤时,我的问题就来了。print(validated_data)
如果我像以前那样打印。我看不到attachments
我在查询中发送的内容。
如果我打印print(self)
变量,我会看到附件以与图像类似的方式进入服务器,但不知何故它在数据验证中丢失了。
我该怎么做才能通过验证?
要添加更多信息,这是 self 打印的内容:
ItemSerializer(context={'request': <rest_framework.request.Request: POST '/api/v1/item/'>, 'format': None, 'view': <inventory.views.ItemViewset object>}, data=<QueryDict: {'label': ['00000003'], 'name': ['HDMI Cable Delete me'], 'photo': [<InMemoryUploadedFile: example.png (image/png)>], 'attachments': [<InMemoryUploadedFile: example.png (image/png)>]}>):
...
...
attachments = FileSerializer(allow_null=True, many=True, required=False):
id = IntegerField(label='ID', read_only=True)
name = CharField(style={'base_template': 'textarea.html'})
file = FileField(max_length=100)
added_on = DateTimeField(read_only=True)
item = PrimaryKeyRelatedField(allow_null=True, queryset=Item.objects.all(), required=False)