django-rest-framework-02

常见问题以及使用技巧


  • 问题:将字典类型数据传递给序列器,默认是需要传入所有非空字段的,如果只传入部分字段,将会出现错误

  • 解决办法:数据传入序列器时添加partial参数True

  • 例子:

    serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True)
    


  • 问题:ModelSerializer和Serializer的区别?

  • 答:前者可以使用django中的Model类在models.py中编写模型,也可以在序列器中添加或者覆盖models.py中的字段,后者在序列器中使用Serializer.编写模型

  • 例子:

    在序列器中编写数据模型

    class CommentSerializer(serializers.Serializer): user = UserSerializer(required=False) # May be an anonymous user. content = serializers.CharField(max_length=200) created = serializers.DateTimeField()

    在models.py中编写数据模型

    class AdjustOrderSerializer(ModelSerializer): goodsmanage = GoodsManageSerizlizer(many=True) warehouse = WareHouseSerizlizer(many=True) supplier = SupplierSerizlizer(many=True) userprofile = UserProfileSerializers(many=True) # 添加models.py中没有的字段 test = Serializers.CharField(max_length=30) class Meta: model = AdjustOrder fields = 'all'


  • 简单序列器的写法:不存在关联表的情况

    class PurchaseTypeSerializer(ModelSerializer): class Meta: model = PurchaseType fields = 'all'

  • 说明:重写Meta,model指定我们models.py中定义的模型类,fields指定序列器包含的模型类中的字段,这个值有几种写法:

  • 1.fields = ['字段1', '字段2', ...]或者('字段1', 。。。)
  • 2.fields = "--all--",表示所有字段,官网推荐这样写。
  • 3.exclude = ('users',),用这个来代替fields, 表示排除这个字段,也是一种推荐的写法。
  • 4.read_only_fields = (',,'...),指定只读字段。

  • 序列器存在外键关系时的写法:在序列器中调用外键关联表的序列器,这个做法在官网文档被称作序列器的嵌套

  • 如下所示:many=True表示序列器接收到的data是多个数据(字典),required=False表示序列器可以接收None

  • 例子:

    class CommentSerializer(serializers.Serializer): user = UserSerializer(required=False) edits = EditItemSerializer(many=True) # A nested list of 'edit' items. content = serializers.CharField(max_length=200) created = serializers.DateTimeField()


  • 嵌套序列器中的create方法编写,关键参数“valited_data”,注释部分说明了内层和外层模型的增加方法

  • 例子:

    class UserSerializer(serializers.ModelSerializer): # 嵌套profile的序列器 profile = ProfileSerializer() class Meta: model = User fields = ('username', 'email', 'profile') def create(self, validated_data): # validtaed_data包含了user所有的字段以及关联表 profile_data = validated_data.pop('profile') # 外层序列器对应的表模型使用validated_data增加记录 user = User.objects.create(validated_data) # 内层序列器对应的表模型使用刚才从valited_data中取出的profile的数据字典增加记录 Profile.objects.create(user=user, profile_data) return user


  • 嵌套序列器的update方法编写

方法一,普通写法

def update(self, instance, validated_data):
    profile_data = validated_data.pop('profile')
    # Unless the application properly enforces that this field is
    # always set, the follow could raise a DoesNotExist, which
    # would need to be handled.
    profile = instance.profile

instance.username = validated_data.get('username', instance.username)
instance.email = validated_data.get('email', instance.email)
instance.save()

profile.is_premium_member = profile_data.get(
    'is_premium_member',
    profile.is_premium_member
)
profile.has_support_contract = profile_data.get(
    'has_support_contract',
    profile.has_support_contract
 )
profile.save()
return instance

方法二,增加一个管理类(更推荐)

class UserManager(models.Manager):
    ...

    def create(self, username, email, is_premium_member=False, has_support_contract=False):
        user = User(username=username, email=email)
        user.save()
        profile = Profile(
            user=user,
            is_premium_member=is_premium_member,
            has_support_contract=has_support_contract
        )
        profile.save()
        return user


# ---------------接下来在序列类写-------------
def create(self, validated_data):
    return User.objects.create(
        username=validated_data['username'],
        email=validated_data['email']
        is_premium_member=validated_data['profile']['is_premium_member']
        has_support_contract=validated_data['profile']['has_support_contract']
    )


  • HyperLinkedSerializer类使用:

  • 这个序列类作用是使用超链接来表示api,通常需要传入context={'request': request}这个参数来确保url绝对路径。

  • 例子:

    serializer = AccountSerializer(queryset, context={'request': request})


评论 2