串行器容許諸如查詢集和模型實例複雜的數據轉換爲可隨後被容易地呈現到機Python數據類型JSON
,XML
或其餘內容類型。序列化程序還提供反序列化,容許在首次驗證傳入數據後將解析後的數據轉換回複雜類型。html
REST框架中的序列化程序與Django Form
和ModelForm
類的工做方式很是類似。咱們提供了一個Serializer
類,它爲您提供了一種強大的通用方法來控制響應的輸出,以及一個ModelSerializer
類,它提供了一個有用的快捷方式來建立處理模型實例和查詢集的序列化程序。數據庫
每一個序列化器字段類構造函數至少採用這些參數。某些Field類採用其餘特定於字段的參數,但應始終接受如下內容:django
read_only
只讀字段包含在API輸出中,但在建立或更新操做期間不該包含在輸入中。任何錯誤包含在序列化程序輸入中的「read_only」字段都將被忽略。api
將其設置爲True
以確保在序列化表示時使用該字段,但在反序列化期間建立或更新實例時不使用該字段。框架
默認爲 False
ide
write_only
將其設置True
爲確保在更新或建立實例時可使用該字段,但在序列化表示時不包括該字段。函數
默認爲 False
ui
required
一般,若是在反序列化期間未提供字段,則會引起錯誤。若是在反序列化期間不須要此字段,則設置爲false。加密
將此設置爲False
還容許在序列化實例時從輸出中省略對象屬性或字典鍵。若是密鑰不存在,它將不會包含在輸出表示中。url
默認爲True
。
default
若是設置,則給出默認值,若是未提供輸入值,將使用該字段。若是未設置,則默認行爲是根本不填充該屬性。
該default
過程當中部分更新操做不適用。在部分更新的狀況下,只有傳入數據中提供的字段將返回一個驗證值。
能夠設置爲函數或其餘可調用函數,在這種狀況下,將在每次使用時評估該值。調用時,它不會收到任何參數。若是callable有一個set_context
方法,那麼在每次獲取值以前都會調用該方法,並將字段實例做爲惟一參數。這與驗證器的工做方式相同。
序列化實例時,若是實例中不存在對象屬性或字典鍵,則將使用默認值。
請注意,設置default
值意味着不須要該字段。包含default
和required
關鍵字參數都是無效的,而且會引起錯誤。
allow_null
一般,若是None
傳遞給序列化程序字段,則會引起錯誤。將此關鍵字參數設置爲True
if None
應被視爲有效值。
請注意,若是沒有顯式default
,將此參數設置爲True
將暗示序列化輸出的default
值null
,但不暗示輸入反序列化的默認值。
默認爲 False
source
將用於填充字段的屬性的名稱。多是一個只接受self
參數的方法,例如URLField(source='get_absolute_url')
,或者可使用點分表示來遍歷屬性,例如EmailField(source='user.email')
。使用點分表示法序列化字段時,default
若是任何對象不存在或在屬性遍歷期間爲空,則可能須要提供值。
該值source='*'
具備特殊含義,用於指示整個對象應該傳遞到該字段。這對於建立嵌套表示或者須要訪問整個對象以肯定輸出表示的字段很是有用。
默認爲字段名稱。
validators
應該應用於傳入字段輸入的驗證程序函數列表,它會引起驗證錯誤或只是返回。驗證器函數一般應該提升serializers.ValidationError
,可是Django的內置函數ValidationError
也支持與Django代碼庫或第三方Django軟件包中定義的驗證器兼容。
error_messages
錯誤消息的錯誤代碼字典。
label
一個簡短的文本字符串,可用做HTML表單字段或其餘描述性元素中字段的名稱。
help_text
一個文本字符串,可用做HTML表單字段或其餘描述性元素中字段的描述。
initial
應該用於預填充HTML表單字段值的值。你能夠將一個callable傳遞給它,就像你對任何常規Django同樣Field
:
import datetime from rest_framework import serializers class ExampleSerializer(serializers.Serializer): day = serializers.DateField(initial=datetime.date.today)
style
鍵值對的字典,可用於控制渲染器應如何渲染字段。
這裏的兩個例子是'input_type'
和'base_template'
:
# Use <input type="password"> for the input. password = serializers.CharField( style={'input_type': 'password'} ) # Use a radio input instead of a select input. color_channel = serializers.ChoiceField( choices=['red', 'green', 'blue'], style={'base_template': 'radio.html'} )
class SmsSerializer(serializers.Serializer): ''' 註冊手機號和驗證碼序列化 ''' mobile = serializers.CharField(max_length=11,min_length=11) def validate_mobile(self, mobile): ''' 驗證手機號碼 ''' # 驗證手機是否合法 if not re.match(REGEX_MOBILE, mobile): raise serializers.ValidationError('手機號非法') # 手機是否註冊 if User.objects.filter(mobile=mobile).count(): raise serializers.ValidationError('用戶已經存在') on_minute_ago = datetime.now() - timedelta(hours=0, minutes=1, seconds=0) if VerifyCode.objects.filter(add_time__gt=on_minute_ago, mobile=mobile): raise serializers.ValidationError('距離上一次發送未超過60秒') return mobile
class UserRegSerializer(serializers.ModelSerializer): ''' 用戶註冊序列化 ''' # write_only=True,不會拿該字段來序列化,labe標籤名,help_text:docs文檔中description code = serializers.CharField(required=True, write_only=True, max_length=4, min_length=4, label='驗證碼', error_messages={ "blank": "請輸入驗證碼", "required": "驗證碼不能爲空", "max_length": "驗證碼格式錯誤", "min_length": "驗證碼格式錯誤" },help_text='驗證碼') username = serializers.CharField(required=True, allow_blank=False, validators=[UniqueValidator(queryset=User.objects.all(), message='用戶已經存在')]) #style密文,write_only=True不返回,保存爲明文 password = serializers.CharField(style={"input_type":"password"},write_only=True) #重載create函數,保存爲密文,該方法能夠實現加密密碼,還能夠信號(分離性好) # def create(self, validated_data): # user=super(UserRegSerializer,self).create(validated_data=validated_data) # user.set_password(validated_data['password']) # user.save() # return user def validate_code(self, code): # 不用get,若是返回兩條數據以上,會拋異常 # try: # verify_codes=VerifyCode.objects.get(mobile=self.initial_data['username']) # except VerifyCode.DoesNotExist as e: # pass # except VerifyCode.MultipleObjectsReturned as e: # pass verify_codes = VerifyCode.objects.filter(mobile=self.initial_data['username']).order_by('-add_time') if verify_codes: last_verfycode = verify_codes[0] five_minute_ago = datetime.now() - timedelta(hours=0, minutes=5, seconds=0) if five_minute_ago > last_verfycode.add_time: raise serializers.ValidationError('驗證碼過時') if code != last_verfycode.code: raise serializers.ValidationError('驗證碼錯誤') else: raise serializers.ValidationError('驗證碼錯誤') # 做用於全部字段,將驗證碼刪除,不是插入數據庫的字段 def validate(self, attrs): attrs["mobile"] = attrs["username"] del attrs["code"] return attrs class Meta: model = User fields = ('username', 'code', 'mobile', 'password')
class UserViewset(mixins.CreateModelMixin,mixins.UpdateModelMixin,mixins.RetrieveModelMixin,viewsets.GenericViewSet): ''' 用戶 ''' serializer_class = UserRegSerializer queryset = User.objects.all() authentication_classes = (JSONWebTokenAuthentication,authentication.SessionAuthentication) #更新,添加用戶信息放在一塊兒,是否登陸應該動態,註冊不用登陸IsAuthenticated,該方法不行 # permission_classes = (permissions.IsAuthenticated) def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) user=self.perform_create(serializer) re_dict=serializer.data payload=jwt_payload_handler(user) re_dict['token']=jwt_encode_handler(payload) re_dict['name']=user.name if user.name else user.username headers = self.get_success_headers(serializer.data) return Response(re_dict, status=status.HTTP_201_CREATED, headers=headers) def get_serializer_class(self): ''' 重載GenericAPIView中的get_serializer_class函數,調用不一樣的序列化類,若是是create, 就調用UserRegSerializer序列化,不然UserDetailSerializer序列化 :return: ''' if self.action == 'retrieve': return UserDetailSerializer elif self.action == 'create': return UserRegSerializer return UserDetailSerializer def get_permissions(self): ''' 重載APIview中的get_perimissions函數,若是是新增用戶則不用登陸,不然必須登陸 :return: ''' if self.action == 'retrieve': return [permissions.IsAuthenticated()] elif self.action == 'create': return [] return [] def get_object(self): ''' 返回當前用戶 :return: ''' return self.request.user def perform_create(self, serializer): return serializer.save()