rest框架-- serializer操作


Serializers把querysets和model instances這些復雜的數據結構轉化為native Python 以便於以json,xml或其它內容類型的形式render出去。

  • 類似於Django的 Form 和ModelForm
  • Serializer和ModelSerializer

序列化對象
from datetime import datetime classComment(object):def __init__(self, email, content, created=None):self.email = email self.content = content self.created = created or datetime.now()
from rest_framework import serializers classCommentSerializer(serializers.Serializer): email = serializers.EmailField() content = serializers.CharField(max_length=200) created = serializers.DateTimeField()
comment =Comment(email='leila@example.com', content='foo bar') serializer =CommentSerializer(comment) serializer.data # {'email': 'leila@example.com', 'content': 'foo bar', 'created': '2016-01-27T15:17:10.375877'}

把數據轉化為json格式

from rest_framework.renderers importJSONRenderer json =JSONRenderer().render(serializer.data) json # b'{"email":"leila@example.com","content":"foo bar","created":"2016-01-27T15:17:10.375877"}'

反序列化對象

把json數據轉化為本地數據類型,也就是Django rest framework可以使用的數據類型

from django.utils.six importBytesIOfrom rest_framework.parsers importJSONParser stream =BytesIO(json) data =JSONParser().parse(stream)

讓后進一步把這些數據綁定到serializers上面,serializer = CommentSerializer(data=data)之后使用serializer.is_valid()驗證傳進來的數據(上段代碼的data是否符合CommentSerializer的格式,這里可以寫一個try-exception.現在可以在serializer.validated_data找到傳進來的數據。
在訪問validated data或板寸validated data之前一定要檢查serializer.is_valid()是否為true。如果為false的話錯誤信息包含在serializer.errors里。

serializer =CommentSerializer(data=data)
serializer.is_valid()# True
serializer.validated_data
# {'content': 'foo bar', 'email': 'leila@example.com', 'created': datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)}

 


保存instances

我們應該實現基本的create和update方法,把數據寫入數據庫

def create(self, validated_data):

  returnComment.objects.create(**validated_data)

def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)
        instance.save()return instance

 

如果不需要寫入數據庫,可以直接放回數據就好了

classCommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()def create(self, validated_data):returnComment(**validated_data)

  def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)

     return instance

 

在命令行中的編寫如下:
創建一個新的對象

serializer =CommentSerializer(data=data)
serializer.is_valid()# True
serializer.validated_data
# {'content': 'foo bar', 'email': 'leila@example.com', 'created': datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)}
comment = serializer.save()

 

更新已經存在的comment實例

serializer =CommentSerializer(comment, data=data)
serializer.is_valid()# True
serializer.validated_data
# {'content': 'foo bar', 'email': 'leila@example.com', 'created': datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)}
comment = serializer.save()

 

在save的時候添加其它內容比如

serializer.save(owner=request.user)

owner數據被綁定在serializer.validated_data對象上,當create或update的時候就會被添加進數據庫。
直接重寫save()方法
有時候並不需要保存或則返回數據,這個時候save()方法就需要重寫。比如執行發送郵件的任務。

classContactForm(serializers.Serializer):
    email = serializers.EmailField()
    message = serializers.CharField()def save(self):
        email =self.validated_data['email']
        message =self.validated_data['message']
        send_email(from=email, message=message)

 

請注意,在上述情況下,我們現在必須直接訪問serializer_date屬性。


驗證
serializer =CommentSerializer(data={'email':'foobar','content':'baz'})
serializer.is_valid()# False
serializer.errors
# {'email': [u'Enter a valid e-mail address.'], 'created': [u'This field is required.']}

 

non_field_errors關鍵字有可能出現,可以在REST framework 框架的設置文件里面設置NON_FIELD_ERRORS_KEY。
is_valid()有默認的異常處理機制,raise_exception標志默認為true,框架自動幫你拋異常(serializers.ValidationError)。

# Return a 400 response if the data was invalid. serializer.is_valid(raise_exception=True)

自定義驗證
類似於Django表單的clean_<fieldname>方法,你可以添加validate<field_name>方法到你的Serializer子類里面。這個方法只接受要驗證的數據這一個對象。拋出的異常也是serializers.ValidationError。

from rest_framework import serializers

classBlogPostSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=100)
    content = serializers.CharField()

  def validate_title(self, value):"""
        Check that the blog post is about Django.
        """if'django'notin value.lower():raise serializers.ValidationError("Blog post is not about Django")return value

 

注意:如果你不希望這個驗證方法被使用,你可以在serializer上聲明required=False,那么如果這個field沒有包括進來這個驗證步驟就不會起作用。(這里有點不清晰)
對象級驗證
如果你的驗證需要訪問多個fileds,你可以添加serializer的子類validate().這個方法接收一個字典參數,你需要使用的多個fileds應該包含在這個字典參數里面。報錯類型為serializers.ValidationError

from rest_framework import serializers

classEventSerializer(serializers.Serializer):
    description = serializers.CharField(max_length=100)
    start = serializers.DateTimeField()
    finish = serializers.DateTimeField()

  def validate(self, data):"""
        Check that the start is before the stop.
        """if data['start']> data['finish']:raise serializers.ValidationError("finish must occur after start")return data

 

驗證器

  • 通過在字段實例上聲明使用驗證器
def multiple_of_ten(value):

   if value %10!=0:

   raise serializers.ValidationError('Not a multiple of ten')classGameRecord(serializers.Serializer):
score =IntegerField(validators=[multiple_of_ten])...

 

  • 作用於全部字段的驗證器
    下載Meta里面
classEventSerializer(serializers.Serializer):
    name = serializers.CharField()
    room_number = serializers.IntegerField(choices=[101,102,103,201])
    date = serializers.DateField()classMeta:# Each room only has one event per day.
        validators =UniqueTogetherValidator(
            queryset=Event.objects.all(),
            fields=['room_number','date'])

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM