如何用django rest框架反序列化foreignkey?

时间:2014-09-15 05:00:45

标签: django django-rest-framework

例如

class People(models.Model):
    name = models.CharField(max_length=20)

class Blog(models.Model):
    author = models.ForeignKeyField(People)
    content = models.TextField()

然后,

class CreateBlogSerializer(serializers.Serializer):
    #author id
    author = serializers.IntegerField()
    content = serializers.TextField()

在视图中,我需要获取author_id,检查id是否存在并获取作者实例,这样做很麻烦。

serializer = CreateBlogSerializer(data=request.DATA)
if serializer.is_valid():
    try:
        author = Author.objects.get(pk=serializer.data["author"])
    except Author.DoesNotExist:
        return Response(data={"author does not exist"})
    blog = Blog.objects.create(author=author, content=serializer.data["content"])

是否有一个ForeignKeyField来反序列化和验证primarykey数据,然后返回一个实例。

class CreateBlogSerializer(serializers.Serializer):
    author = serializers.ForeignKeyField(Author)
    content = serializers.TextField()

serializer = CreateBlogSerializer(data=request.DATA)
if serializer.is_valid():
    #after deserialization , the author id becomes author model instance
    blog = Blog.objects.create(author=serializer.data["author"], content=serializer.data["content"])
else:
    #the author id does not exist will cause serializer.is_valid=Flase

PS

我在ModelSerializer中知道PrimaryKeyRelatedField,但我不能在这里使用ModelSerializer,模型结构很复杂,上面只是示例。

我的第一个想法是写一个客户领域。

2 个答案:

答案 0 :(得分:1)

class ForeignKeyField(WritableField):

    def __init__(self, model_name, *args, **kwargs):
        super(ForeignKeyField, self).__init__(*args, **kwargs)
        self.model_name = model_name
        self.model_instance = None

    def from_native(self, pk):
        if not isinstance(pk, int):
            raise ValidationError("pk must be int")
        try:
            self.model_instance = self.model_name.objects.get(pk=pk)
            return self.model_instance
        except self.model_name.DoesNotExist:
            raise ValidationError('object does not exist')

    def to_native(self, obj):
        return self.model_instance

我入侵了它,但我不知道它为什么会起作用。

<强>用法: 有一点差异

class t_serializer(serializers.Serializer):
    author = ForeignKeyField(Author)

@api_view(["POST"])
def func(request):
    serializer = t_serializer(data=request.DATA)
    if serializer.is_valid():
        print isinstance(serializer.data["author"], Author)
        #print True
    else:
        print serializer.errors

答案 1 :(得分:0)

看来你想要的是自定义验证码。

对于此特定实例,您可以编写以下内容。

class CreateBlogSerializer(serializers.Serializer):
    author = serializers.ForeignKeyField(Author)
    content = serializers.TextField()

    def validate_author(self, attrs, source):
        """
        Verify that the author exists.
        """
        author = attrs[source]
        if Author.objects.filter(pk=author).exists():
            return attrs
        raise serializers.ValidationError("Specified Author does not exist!")

现在,当您致电serializer.is_valid()时,将会进行此项检查。

因此,您可以在代码中的其他位置执行此操作,

if serializer.is_valid():
     blog = Blog.objects.create(author=serializer.data["author"], content=serializer.data["content"])

请确保如果创建了给定的blog,则数据库中已存在相应的Author

详细说明

因此,Django Rest Framework提供了一种向序列化程序添加自定义验证的方法。这可以通过在序列化程序类validate_<field name>中提供以下格式的方法来完成。这些方法会将source值设置为给定字段的名称,在我们的示例author中,然后可以与attrs变量一起使用以获取字段的当前值({ {1}}包含传递给序列化程序的所有值。

调用这些验证方法,然后调用attrs方法。如果给定的测试通过,他们应该返回serializer.is_valid(),否则提出attrs

它们可能会有些复杂,所以如果你在这里阅读完整的文档可能是最好的,http://www.django-rest-framework.org/api-guide/serializers#validation