环境准备:创建app
(python36env) [vagrant@CentOS7 apps]$ cd apps/
(python36env) [vagrant@CentOS7 apps]$ django-admin startapp cabinet
(1)激活注册settings.py:
'cabinet.apps.CabinetConfig'
(2)模型cabinet/models.py
from django.db import models
from apps.idcs.models import Idc
class Cabinet(models.Model):
#关联哪个机房且(一个机房有多个机柜)且foreignkey所在的模型是多,即指向的模型是一(Idc)
idc = models.ForeignKey(Idc, verbose_name="所在机房",on_delete=models.CASCADE)
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Meta:
db_table = "resources_cabinet"
ordering = ["id"]
(python36env) [vagrant@CentOS7 devops]$ python manage.py makemigrations cabinet
(python36env) [vagrant@CentOS7 devops]$ python manage.py migrate
(3)写序列化cabinet/serializers.py:
from rest_framework import serializers from idcs.serializers import IdcSerializer from .models import Cabinet class CabinetSerializer(serializers.Serializer): #idc是关联字段关联Idc---序列化本身也是一字段类型,这里指定序列化为它的关键字段 idc = IdcSerializer(many=False) name = serializers.CharField(required=True)
(4)写视图cabinet/views.py:
from rest_framework import viewsets from .models import Cabinet from .serializers import CabinetSerializer class CabinetViewset(viewsets.ModelViewSet): """ retrieve:返回指定机柜信息 list:返回指定机柜列表 update:更新机柜信息 destroy:删除机柜记录 create:创建机柜记录 partial_update:更新部分字段 """ queryset = Cabinet.objects.all() serializer_class = CabinetSerializer
(5)写路由urls.py:
from cabinet.views import CabinetViewset route.register("cabinet", CabinetViewset, basename="cabinet")
为测试给它创建条数据:
(python36env) [vagrant@CentOS7 devops]$ python manage.py shell
In [1]: from idcs.models import Idc
In [2]: idc = Idc.objects.get(pk=4)
In [3]: from cabinet.models import Cabinet
In [4]: c = Cabinet()
In [5]: c.idc = idc
In [6]: c.name = "test"
In [7]: c.save()
二.序列化高级用法
上述效果中可知,问题一:它把序列化类的所有字段拿过来了,其实我想要的就只是id和name,问题二:在创建数据时它要求所有的字段数据提交且是必须提交
(1)cabinet/serializers.py中:
from rest_framework import serializers from idcs.serializers import IdcSerializer from .models import Idc from .models import Cabinet class CabinetSerializer(serializers.Serializer): #通过主键关联的类型--且当前的这条记录对应idc中是单条记录many指定,且要指定和谁关联queryset idc = serializers.PrimaryKeyRelatedField(many=False, queryset=Idc.objects.all()) name = serializers.CharField(required=True) #此方法作用是把上面字段成员属性序列化成标准字典--可自定字段即格式类型 def to_representation(self, instance): idc_obj = instance.idc ret = super(CabinetSerializer, self).to_representation(instance) ret["idc"] = { "id": idc_obj.id, "name": idc_obj.name } return ret #此方法是反序列化的第一步:它拿到的是提交过来的原始数据即QueryDict => request.GET,request.POST,body def to_internal_value(self, data): return super(CabinetSerializer, self).to_internal_value(data) #create方法要把实例传进去--创建数据 def create(self, validated_data): print(validated_data) return Cabinet.objects.create(**validated_data)
2.若上述文件中idc字段是只读的(即不能往idc字段提交数据不能被反序列化),那么就不需要关联关系,那就用如下方法
from rest_framework import serializers from idcs.serializers import IdcSerializer from idcs.models import Idc from .models import Cabinet class CabinetSerializer(serializers.Serializer): #通过主键关联的类型--且当前的这条记录对应idc中是单条记录many指定,且要指定和谁关联queryset idc = serializers.PrimaryKeyRelatedField(many=False, queryset=Idc.objects.all()) name = serializers.CharField(required=True) def to_representation(self, instance): idc_obj = instance.idc ret = super(CabinetSerializer, self).to_representation(instance) ret["idc"] = { "id": idc_obj.id, "name": idc_obj.name } return ret #此方法是反序列化的第一步:它拿到的是提交过来的原始数据即QueryDict => request.GET,request.POST,body def to_internal_value(self, data): """ 反序列化第一步:拿到的是提交过来的原始数据: QueryDict => request.GET, request.POST """ print(data) return super(CabinetSerializer, self).to_internal_value(data) #create方法要把实例传进去--创建数据 def create(self, validated_data): return Cabinet.objects.create(**validated_data)