最近的主要就是在写rest api,不少地方是多表关联的外键,而后api传递给你的就只是另外一张表里面记录的id,而后你再去查询,判断记录是否存在,而后处理,这样以为很麻烦。代码大体是这样的python
#models.py class People(models.Model): name = models.CharField(max_length=20) sex = models.CharField(max_length=3) class Blog(models.Model): author = models.ForeignKeyField(People) content = models.TextField()
在建立Blog的时候,咱们post的数据大体是这样的数据库
{ "author": 1, "content": "Hello world" }
而后个人serializer是这样的api
class CreateBlogSerializer(serializers.Serializer): #author id author = serializers.IntegerField() content = serializers.TextField()
这样的话,进入views,post
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"])
由于这样的状况不少,每次在views里面这样查询是很麻烦的,我就想把这个验证的工做放到serializer里面完成,而后返回给我一个ValidationError或者这个model的instance。这样就能省略不少的代码了。rest
看了看rest framework的文档,例子都是很简单的逻辑构成的,没有什么外键或者多对多的关系,这个固然好写。code
最后发现本身能够去继承WritableField
自定义一个serializer,可是里面有两个方法to_native
和from_native
这个到如今没搞懂是怎么个执行顺序,连rest framework源代码都看了一点,也没有搞懂,算了,反正能工做就行。blog
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
而后咱们的views就这样干净利索了继承
class CreateBlogSerializer(serializers.Serializer): author = ForeignKeyField(Author) content = serializer.TextField() @api_view(["POST"]) def func(request): serializer = CreateBlogSerializer(data=request.DATA) if serializer.is_valid(): #print isinstance(serializer.data["author"], Author) #print True Blog.objects.create(author=serializer["author"], content=serializer["content"]) else: print serializer.errors
PS
其实在上面写的这种简单状况的时候,咱们可使用ModelSerializer
的PrimaryKeyRelatedField
,可是数据库结构一复杂就会致使ModelSerializer
无法用了,只能本身去写serializer。文档