一.项目需求

  批量上传图片,然后批量导入(使用excel)每个图片对应的属性(属性共十个,即对应十个字段,其中外键三个)。

二.问题

  一次可能上传成百上千张图片和对应字段,原来数据库的设计我将图片和对应属性放在一张表中,图片不可能和对应字段一起批量导入,如果先导入图片,其他字段必须允许为空,且在导入对应属性时,会遍历刚上传已经存在数据库中的图片,然后更新数据库,增加对应属性,这样会给服务器造成很大的压力,且很有可能出现错误(如图片对应不上,因此很多字段为空或只有图片,会使很多错误很难捕捉。)

三.实践中的解决方法

  1.分成两张表:

    我首先想到将图片和对应字段分开成两张表,先上传图片,然后在导入对应属性,然而仔细一想,问题似乎解决得不完善,导入使如何对应图片id,还是直接对应图片名,还有是否有可能图片已经保存到数据库,但是excel中没有该图片的信息,这也会浪费很多的空间,因此此方法还有待提高。

  2.使用缓存:

    然后我最后想到了缓存,也决定使用该方法批量上传与导入,思路大概是:上传图片先暂时存入缓存(我这里时图片名为键,图片临时文件对象为值),设置一定的时效,然后在上传excel判断excel的格式及列标题等,这些都对应时,然后将外键数据从数据库取出,一行一行判断excel中的数据的外键是否满足,以及图片是否在缓存中,如果条件都满足,然后这一行数据构成数据库中的一个Queryset对象存入列表,这样就将数据验证完毕,最后验证完所有的数据后,使用bulk_create()方法批量写入,或者可以使用get_or_create()方法批量导入(可以去重,但更耗时)。

     2.1图片和excel文件上传序列化如下:

 1 class RockImageSerializer(serializers.Serializer):
 2     imgs = serializers.ListField(child=serializers.FileField(max_length=100,
 3                                                              ), label="地质薄片图片",
 4                                  help_text="地质薄片图片列表", write_only=True)
 5 
 6     def create(self, validated_data):
 7         try:
 8             imgs = validated_data.get('imgs')
 9             notimg_file = []
10             for img in imgs:
11                 img_name = str(img)
12                 if not img_name.endswith(('.jpg', '.png', '.bmp', '.JPG', '.PNG', '.BMP')):
13                     notimg_file.append(img_name)
14                 else:
15                     # 将图片加入缓存
16                     cache.set(img_name, img, 60 * 60 * 24)
17             if notimg_file:
18                 return {'code': -2, 'msg': '部分未上传成功,请检查是否为图片,失败文件部分如下:{0}'.format(','.join(notimg_file[:10]))}
19             return {'code': 1}
20         except Exception as e:
21             return {'code': -1}
22 
23     def validate_imgs(self, imgs):
24         if imgs:
25             return imgs
26         else:
27             raise serializers.ValidationError('缺失必要的字段或为空')
28 
29 
30 class SourceSerializer(serializers.Serializer):
31     """
32     批量上传序列化(excel)
33     """
34     source = serializers.FileField(required=True, allow_empty_file=False,
35                                    error_messages={'empty': '未选择文件', 'required': '未选择文件'}, help_text="excel文件批量导入",
36                                    label="excel文件")
View Code

相关文章:

  • 2022-02-21
  • 2022-12-23
  • 2021-12-09
  • 2021-11-20
  • 2021-11-20
  • 2021-11-20
  • 2021-11-20
  • 2021-11-20
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-08-11
  • 2021-11-20
  • 2022-12-23
  • 2021-07-24
相关资源
相似解决方案