【问题标题】:Issues in validating Image file passed through post request in django验证通过 django 中的 post 请求传递的图像文件的问题
【发布时间】:2022-01-20 06:51:47
【问题描述】:

我想在我的 django 项目中验证两件事:

  1. 传递的图像是否有效(具有适当的扩展名、非空等)

  2. 我有一个函数isCovering70p 返回布尔值,这取决于图像中的对象是否覆盖了 70% 的区域。 现在我还必须在将数据保存到数据库之前检查这一点。如果用户发布的图片不符合这两个条件,则应发送400 响应代码。

这是我的models.py:

def user_image_dir_path(instance, filename):
    return f"uploads/users/{instance.email}/{filename}"


class UserDetail(models.Model):

    email = models.EmailField(max_length=80)
    registration_time = models.DateTimeField(auto_now_add=True)
    image_path = models.ImageField(upload_to=user_image_dir_path)
    image_meta = models.CharField(max_length=100)

    @property
    def filename(self):
        return os.path.basename(self.file.name)

这是我的 serializers.py:

class UserDetailsSerializer(serializers.ModelSerializer):

    class Meta:
        model = UserDetail
        fields = ['full_name', 'email', 'org_id', 'image_path']

通过DRF docs,我了解到我的#1 验证条件将由 DRF/django 处理。

但是,我应该如何以及在哪里照顾 #2 条件?

另外,我想根据isCovering70p 更新我的image_meta 字段。我应该如何以及在哪里放置该更新的逻辑?

【问题讨论】:

    标签: python django django-models django-rest-framework


    【解决方案1】:

    您可以解决此问题的一种方法是使用序列化程序上的验证方法

    class UserDetailsSerializer(serializers.ModelSerializer):
        
        class Meta:
            model = UserDetail
            fields = ['full_name', 'email', 'org_id', 'image_path']  
        
        def validate(self, data):
            if not isCovering70p(data['image_path']):
                raise serializers.ValidationError({'image_path': 'image is not covering 70% of area')
            return data
    

    您可以在序列化程序中添加一个验证函数,如果接收到的数据无效,则引发 ValidationError。

    【讨论】:

    • 感谢您的回复。我遇到的这种方法的问题是,data['image_path'] 的类型是 class 'django.core.files.uploadedfile.InMemoryUploadedFile',而 isCovering70p 需要一个文件路径或 numpy 数组。根据 django 文档,保存该模型对象时会保存该文件。因此,在保存之前无法访问它。
    • 在修改了您的解决方案一段时间后,我意识到根据 django 和 DRF 文档,似乎没有任何方法可以使用我的 isCovering70p 方法,序列化发生在保存之前,因此文件上传只保留在内存中。所以我不得不修改我的isCovering70p 以使用 InMemory 字节而不是文件路径/np 数组。虽然这对许多人来说是理想的方式,但它不适合我,因为我无法访问 'isCovering70p' 方法,并且不得不围绕它编写一个包装器,增加开销。
    • 我赞成,因为这会带来一些结果,如果没有更好的想法出现,我会接受。谢谢。
    猜你喜欢
    • 2021-11-01
    • 2018-12-13
    • 2020-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 2010-11-05
    相关资源
    最近更新 更多