DRF序列化器将提供的字段设置为“无”

时间:2019-01-27 16:54:20

标签: django validation date serialization django-rest-framework

我目前在一个项目中,我想测试我的序列化程序的验证。我遇到的问题是,在验证过程中,序列化程序将提供的字段设置为None,这对我来说似乎并不合理。

更多详情(为简化起见,简称:)

models.py:

class Contract(models.Model):
    start_date = models.DateField()
    end_date = models.DateField()

serializers.py:

class ContractSerializer(serializers.ModelSerializer):

    class Meta:
        model = Contract
        fields = "__all__"

    def validate(self, attrs):
        """
        Object-level validation.
        Here we validate : start_date is, timewise, prior to end_date
        :param attrs:
        :return:
        """

        if not attrs["start_date"] < attrs["end_date"]:
            raise serializers.ValidationError("Sample Error Message.")

        return attrs

我使用pytest进行测试和pytest-django。

我的conftest.py:

from pytz import datetime


@pytest.fixture
def valid_contract_json():
    start_date = datetime.date(2019, 1, 1)
    end_date = datetime.date(2019, 1, 31)

    data = {
        "start_date": start_date,
        "end_date": end_date,
    }

    return data

我的测试看起来像:

test_serializers.py:

from app.serializers import ContractSerializer

class TestContractSerializer:
    def test_validation(self, valid_contract_json):
        ContractSerializer(data=valid_contract_json).is_valid(raise_exception=True)

运行此测试时,它失败并显示以下消息:

  

TypeError:“ datetime.date”和“ NoneType”的实例之间不支持“ <”

我对此进行了调查:

  1. 注释掉validate方法。
  2. 将测试修改为:

    def test_validation(self, valid_contract_json):
    
        pprint.pprint(valid_contract_json)        
    
        seri = ContractSerializer(data=valid_contract_json).is_valid(raise_exception=True)
        # Serialization won't throw exception now
        pprint.pprint(seri.data)
    

这样,我将数据的实际输出传递给序列化器和由序列化器准备的数据。

输出为:

{
 'start_date': datetime.date(2019, 1, 1),
 'end_date': datetime.date(2019, 1, 31),
}

{
 'start_date': '2019-01-01',
 'end_date': None,
}

我还检查了调用validate()时end_date是否已经为None。 答案是肯定的。

所以我的问题是:为什么此处的序列化程序在start_date下能按预期执行,而在end_date下却无法执行?

这可能是pytest的隐藏缓存问题吗? 编辑:

我尝试过pytest --cache-clear并没有解决问题,所以我怀疑这不是一个小问题。

谢谢。

1 个答案:

答案 0 :(得分:0)

我发现了发生错误的原因。

问题既不是pytest的问题,也不是所提供的Fixture或数据聚合过程的问题。

问题是我进行了以下字段级验证:

def validate_end_date(self, end_date):

    if end_date.day not in (14, monthrange(end_date.year, end_date.month)[1]):
        raise serializers.ValidationError()

如您所见,这对我来说执行不佳,因为如果验证通过,我忘记了返回字段值。这样,字段值变为None

经验教训:实施字段级验证时,请不要忘记返回初始值。

->之后的方法:

def validate_end_date(self, end_date):

    if end_date.day not in (14, monthrange(end_date.year, end_date.month)[1]):
        raise serializers.ValidationError()
    return start_date