You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django REST Framework自定义图片URL验证器返回格式不符问题

Django REST Framework自定义验证器错误返回格式不符问题

我正在开发一个Django REST Framework项目,其中ProjectModel包含image_file(本地上传图片)和image_url(外部托管图片)字段,同时为image_url实现了ImageURLValidator自定义验证器,用于校验URL是否以http:///https://开头、格式合法且指向图片。但运行单元测试时发现,验证返回的错误信息格式与预期不符:实际返回包含ErrorDetail的结构,而预期为纯字符串列表。


相关代码文件

models.py

from django.db import models


class ProjectModel(models.Model):
    image_file = models.ImageField(
        null=True,
        blank=True,
        upload_to='project/%Y/%m/%d'
    )

    image_url = models.URLField(
        null=True,
        blank=True
    )

serializers.py

from rest_framework import serializers
from .validators import ImageURLValidator
from .models import ProjectModel

class ProjectSerializer(serializers.ModelSerializer):
    image_url = serializers.URLField(
        required=False,
        allow_null=True,
        allow_blank=True,
        validators=[ImageURLValidator()]
    )

    class Meta:
        model = ProjectModel
        fields = ['id', 'image_file', 'image_url']

validators.py

import requests
from rest_framework import serializers
from django.core import validators
from django.utils.translation import gettext_lazy as _

class ImageURLValidator:

    def __call__(self, value):
        if not value.startswith(('http://', 'https://')):
            raise serializers.ValidationError(
                _("URL must start with 'http://' or 'https://'")
            )

        try:
            validators.URLValidator()(value)
        except serializers.ValidationError:
            raise serializers.ValidationError(
                _("Invalid URL format")
            )

        # 获取URL内容并检查图片格式
        response = None
        try:
            response = requests.get(value)
            response.raise_for_status()  # 检查请求状态码
        except requests.exceptions.RequestException as e:
            raise serializers.ValidationError(
                _("Error fetching content from URL: %(error)s") % {'error': str(e)}
            )

        content_type = response.headers['content-type']
        if not content_type.startswith(('image/')):
            raise serializers.ValidationError(
                _("URL must point to an image")
            )

错误返回对比

实际返回结果

{'image_url': [ErrorDetail(string="URL must start with 'http://' or 'https://'", code='invalid')]}

预期返回结果

{'image_url': ["URL must start with 'http://' or 'https://'"]}

单元测试代码

class TestFail(TestBase):

    def test_file_url_starts_with_http_or_https(self):
        # 移除http://或https://前缀
        image_url = self.faker.image_url(width=640, height=480)
        pattern = re.compile(r'https?://')
        image_url = pattern.sub('', image_url)

        post_data = {
            'image_url': image_url,
        }

        url_name = "create-project"
        url = f"{APP_LABEL}:{url_name}"
        end_point = reverse(url)
        response = self.client.post(
            end_point,
            post_data,
            # format="multipart"
        )

        expected = status.HTTP_400_BAD_REQUEST
        actual = response.status_code
        self.assertEqual(expected, actual)

        msg = _("URL must start with 'http://' or 'https://'")
        expected = {'image_url': [msg]}
        actual = response.data
        self.assertDictEqual(expected, actual)

内容的提问来源于stack exchange,提问作者erhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 00:22:41