DRF学习笔记(1)——准备一个DRF项目、序列化、关联对象

准备一个DRF项目

环境搭建
  • IDE推荐使用Pycharm专业版本,专业版相较于免费版本,可以直接连接数据库。学生可以直接申请专业版的使用。
    Pycharm官网下载
  • 开发环境我是用的Anaconda,需要注意的是安装Django的2.2版本,最新的3.x还属于测试版,与之前的版本使用有着区别,也不稳定。另外需要安装djangoresrframework和mysqlclient等包。
    在这里插入图片描述
项目配置
  • pycharm创建Django项目,使用先前创建的conda环境。
  • 在setting.py中如下修改
    • ALLOWED_HOSTS = ['*']
    • 在INSTALLED_APP中添加
INSTALLED_APPS = [
    ......
    'rest_framework'
]
    • 根据需要修改数据库
	DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'xxx',
        'HOST': '127.0.0.1',
        'USER': 'xxx',
        'PASSWORD': 'xxx',
        'PORT': 3306,
    }
}
    • 修改语言选项和时区
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False
  • 如果设置了数据库,对数据库进行连接,连接数据库的前提是体现创建好了数据库。填写数据库的名称,用户名,密码。填写完毕可以点击测试连接,如果提示TimeZone问题,可以点击立即修复。
    在这里插入图片描述
    在这里插入图片描述
测试

pycharm窗口的Terminal命令行下输入python manage.py runserver,启动测试。出现下面界面表示配置成功。
在这里插入图片描述

数据迁移

- 从数据库到models.py
`python manage.py inspectdb > App/models.py`

Serializer序列化

正向序列化
serializer.py
class BookSerializer(serializers.Serializer):
	btitle = serializers.CharField(max_length=100, required=False)
	bpub_date = serializers.DateField(allow_null=True, required=False)
	bread = serializers.IntegerField(min_value=0)
	bcomment = serializers.IntegerField(min_value=0)
	bimage = serializers.CharField(max_length=300)
 views.py
 def get(self, request):
	  # 正向序列化
	  books = Bookinfo.objects.all()
	  bs = BookSerializer(instance=books, many=True)
	  return Response(data=bs.data)
反向序列化
  • 使用serializers.Serializer反向序列化,需要重写 create update
  • create 是创建新的对象
    serializer.py
    def create(self, validated_data):
    # book = Bookinfo(btitle=validated_data.get('btitle'))
    # book.bpub_date = validated_data.get('bpub_date')
    # book.bread = validated_data.get('bread', 0)
    # book.bcomment = validated_data.get('bcomment', 0)
    # book.bimage = validated_data.get('bimage', '')
    # book.save()
    # return book
    
    # 也可由下面这么写
    return Bookinfo.objects.create(**validated_data)
    
    • update 是对对象的更新
    def update(self, instance, validated_data):
      """
      :param instance: 要更新的对象
      :param validated_data: y要更新的属性字典
      :return: 对象
      """
      print("update")
      instance.btitle =  validated_data.get('btitle') if validated_data.get('btitle') else instance.btitle
      if validated_data.get('bpub_date'):
          instance.bpub_date = validated_data.get('bpub_date')
      else:
          instance.bpub_date =  instance.bpub_date
      instance.bread = validated_data.get('bread') if  validated_data.get('bread') else instance.bread
      instance.bcomment = validated_data.get('bcomment') if  validated_data.get('bcomment') else instance.comment
      instance.bread = validated_data.get('bimage') if  validated_data.get('bimage') else instance.bimage
      instance.save()
      return instance
    
    • 在视图函数views.py中实现操作,如果使用序列化器进行验证更新操作,需要讲所有的不允许为空的值指定,然后更新,否则会报错。
      # 新增操作
      book = {'btitle':'庆余年2','bpub_date':'2020-3-10',
              'bread':10,'bcomment':30,'bimage':'static/1.jpg'}
      bs = BookSerializer(data=book)
      # 验证
      if bs.is_valid():
    
          # 保存到数据库
          bs.save()
          print(bs.data)
          return Response({'code': 0, 'msg': '保存成功'})
      else:
          print(bs.errors)
          return Response({'code': 1,'msg': bs.errors})
    
      # 更新操作
      data = {'bimage': 'static/0.jpg'}
      book = Bookinfo.objects.get(pk=3)
      # 把对象赋值给instance,更新属性字典赋值给data
      bs = BookSerializer(instance=book, data=data)
      # 验证
      if bs.is_valid():
          # 保存到数据库
          bs.save()
          print(bs.data)
          return Response({'code': 0, 'msg': '保存成功'})
      else:
          print(bs.errors)
          return Response({'code': 1,'msg': bs.errors})
    
    • 进行序列化验证更新会有些麻烦,可以写成部分更新。
    views.py
      # 部分更新
      data = {'bimage': 'static/111.jpg'}
      book = Bookinfo.objects.get(pk=3)
      for key, value in data.items():
          if hasattr(book, key):
              setattr(book, key, value)
      book.save()
      return Response({'code': 2, 'msg': 'update success'})
    
自定义验证器
  • 单独的函数
def check_data(value):
	if value < datetime(2010,1,1).date():
       raise serializers.ValidationError("日期不能小于2010-1-1")
bpub_date = serializers.DateField(allow_null=True, required=False, validators=[check_data])
  • 使用定义单字段验证,validate_xxx, 验证哪个字段就写对应的名字到xxx,此时的attrs为字符串,不是字典。
def validate_bread(self, attrs):
   if attrs > 1000:
      raise serializers.ValidationError("阅读数不能大于1000")
  • 涉及到多字段验证
def validate(self, attrs):
    pass

(推荐使用)使用ModelSerializer进行序列化,自动生成create和update方法

class BookSerializer(serializers.ModelSerializer):
   	bread = serializers.IntegerField(min_value=0)  # 重写验证
   	class Meta:
   		 model = Bookinfo
   		 fields = ['btitle', 'bpub_date', 'bread', 'bcomment', 'bimage']
   		 # fields = '__all__'

关联对象

1.查询到的字典中只包含关联表的主键

related_name 在表中定义外键时,增加related_name字段指定这个字表在主表中对应的外键属性,

models.py
class Bookinfo(models.Model):
    btitle = models.CharField(max_length=200)
    bpub_date = models.DateField(blank=True, null=True)
    bread = models.IntegerField()
    bcomment = models.IntegerField()
    bimage = models.CharField(max_length=200, blank=True, null=True)
    class Meta:
        managed = False
        db_table = 'bookinfo'
        
class Heroinfo(models.Model):
    hid = models.AutoField(primary_key=True)
    hname = models.CharField(max_length=50)
    bid = models.ForeignKey(Bookinfo, models.DO_NOTHING, db_column='bid', blank=True, null=True, related_name='heros')
    class Meta:
        managed = False
        db_table = 'heroinfo'

在models.py里定义了外键,使用了related_name='heros,在序列化器里设置关联对象。

serializer.py
class HeroSerializer(serializers.ModelSerializer):
    class Meta:
        model = Heroinfo
        fields = '__all__'

class BookSerializer(serializers.ModelSerializer):
    # 关联对象
    heros = PrimaryKeyRelatedField(many=True, read_only=True)
    bread = serializers.IntegerField(min_value=0)  # 重写验证
    class Meta:
        model = Bookinfo
        fields = '__all__'

最后返回字典为,其中heros下为对应字段的主键
在这里插入图片描述

2.使用方法__str__(self),直接返回名字

在models.py里定义模型的同时,重写方法__str__(),序列化器中使用StringRelatedField()方法可以直接返回名字。

models.py
class Heroinfo(models.Model):
    hid = models.AutoField(primary_key=True)
    hname = models.CharField(max_length=50)
    bid = models.ForeignKey(Bookinfo, models.DO_NOTHING, db_column='bid', blank=True, null=True, related_name='heros')
    class Meta:
        managed = False
        db_table = 'heroinfo'
    def __str__(self):
        return self.hname
        
serializer.py
class BookSerializer(serializers.ModelSerializer):
    # 关联对象
    heros = StringRelatedField(many=True, read_only=True)
    bread = serializers.IntegerField(min_value=0)  # 重写验证
    class Meta:
        model = Bookinfo
        fields = '__all__'
3.获取关联字段的所有信息

HeroSerializer为Heroinfo的序列化器,BookSerializer为Bookinfo的序列化器,直接使用heros = HeroSerializer(many=True, read_only=True)

serializer.py
class HeroSerializer(serializers.ModelSerializer):
    class Meta:
        model = Heroinfo
        fields = '__all__'
        
class BookSerializer(serializers.ModelSerializer):
    # 关联对象
    heros = HeroSerializer(many=True, read_only=True)
    bread = serializers.IntegerField(min_value=0)  # 重写验证
    class Meta:
        model = Bookinfo
        fields = '__all__'

在这里插入图片描述

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值