[django]梳理drf知识点2

外键关系的自动维护

  • 原始提交的server数据
{
  ...
  "manufacturer": "DELL",
  "model_name": "R730"
  ...
}
  • server和manufacture&productmodel的关系

  • server如何验证manufacture&productmodel 实现他两自动维护的?

字段关系的自动维护

  • 原始数据
{
  ...
  "ip": "192.168.1.1",
  "network": [
    {
      "name": "eth0",
      "ips": [
        {
          "ip_addr": "10.1.1.1",
          "netmask": "255.255.255.0"
        }
      ],
      "mac_address": "00-50-56-C0-00-10"
    }
  ]
  ...
}
  • 模型关系

  • 希望实现提交server数据,可以自动维护network表和ip表.
    并且实现数据一致.

我可能多次提交一份server数据,里面的数据不一致, 实现自动更新相关表.

class ServerAutoReportSerializer(serializers.Serializer):
    """
    服务器同步序列化类
    """
    ip = serializers.CharField(required=True)
    hostname = serializers.CharField(required=True, max_length=20)
    cpu = serializers.CharField(required=True, max_length=50)
    mem = serializers.CharField(required=True, max_length=20)
    disk = serializers.CharField(required=True, max_length=200)
    os = serializers.CharField(required=True, max_length=50)
    sn = serializers.CharField(required=True, max_length=50)

    manufacturer = serializers.CharField(required=True)
    model_name = serializers.CharField(required=True)

    uuid = serializers.CharField(required=True, max_length=50)

    # 网卡和ip模型
    network = serializers.JSONField(required=True)

    # 验证制造商
    def validate_manufacturer(self, value):
        try:
            manufacturer_obj = Manufacturer.objects.get(vender_name__exact=value)
        except Manufacturer.DoesNotExist:
            manufacturer_obj = Manufacturer.objects.create(vender_name=value)
        return manufacturer_obj

    # 验证型号
    def validate(self, attrs):
        manufacturer_obj = attrs['manufacturer']
        try:
            attrs['model_name'] = manufacturer_obj.productmodel_set.get(model_name__exact=attrs['model_name'])
        except ProductModel.DoesNotExist:
            attrs['model_name'] = ProductModel.objects.create(model_name=attrs['model_name'], vender=manufacturer_obj)
        return attrs

    # 验证服务器
    def create(self, validated_data):
        sn = validated_data['sn']
        uuid = validated_data['uuid']
        try:
            # 检测是否存在
            ## 虚拟机uuid
            ## 物理机sn
            if sn == uuid or sn == '' or sn.startwith('vmware'):
                server_obj = Server.objects.get(uuid__contains=uuid)
            else:
                server_obj = Server.objects.get(sn__contains=sn)

        except Server.DoesNotExist:
            # 不存在,则创建
            return self.create_server(validated_data)
        else:
            # 存在则,更新
            return self.update_server(server_obj, validated_data)

    def create_server(self, validated_data):
        network = validated_data.pop('network')
        server_obj = Server.objects.create(**validated_data)
        self.check_server_network_device(server_obj, network)
        return self.obj

    def check_server_network_device(self, server_obj, network):
        current_device_queryset = []
        for device in network:
            try:
                # 检测device是否存在
                device_obj = server_obj.networkdevice_set.get(name__exact=device['name'])

            except NetworkDevice.DoesNotExist:
                # device不存在
                device_obj = self.create_network_device(server_obj, device)
            current_device_queryset.append(device_obj)

        for device_obj in list(set(server_obj.networkdevice_set.all()) - set(current_device_queryset)):
            device_obj.delete()

    def update_server(self, instance, validated_data):
        instance.ip = validated_data.get("ip", instance.ip)
        instance.hostname = validated_data.get("hostname", instance.hostname)
        instance.cpu = validated_data.get("cpu", instance.cpu)
        instance.mem = validated_data.get("mem", instance.mem)
        instance.disk = validated_data.get("disk", instance.disk)
        instance.os = validated_data.get("os", instance.os)
        instance.save()
        self.check_server_network_device(instance, validated_data['network'])
        return instance

    def create_network_device(self, server_obj, device):
        ips = device.pop('ips')
        device['host'] = server_obj
        device_obj = NetworkDevice.objects.create(**device)
        self.check_ip(device_obj, ips)
        return device_obj

    def check_ip(self, device_obj, ifnets):
        current_ip_queryset = []
        for ifnet in ifnets:
            try:
                ifnet_obj = device_obj.ip_set.get(ip_addr_exact=ifnet['ip_addr'])
            except:
                ifnet_obj = self.create_ip(device_obj, ifnet)
            current_ip_queryset.append(ifnet_obj)

        for ifnet in list(set(device_obj.ip_set.all()) - set(current_ip_queryset)):
            ifnet.delete()

    def create_ip(self, network_obj, ifnet):
        ifnet['device'] = network_obj
        return IP.objects.create(**ifnet)

    def to_representation(self, instance):
        res = {
            'ip': instance.ip,
            'hostname': instance.hostname
        }
        return res
  • 知识点: 代码逻辑
create:
    try:
        # 服务器是否存在
    except:
        # 不存在,创建服务器
        self.create_server()
    else:
        # 存在, 更新服务器
        self.update_server()

def create_server():
    #创建服务器
    #检查网卡
def check_network_device():
    #创建网卡: 定义create_network
    #检测ip

def check_ip()
    #创建ip: 定义create_ip
  • 知识点: 去重思想
提交的相对现有的:
现有的比提交的多了, 删除
先有的比提交的少了, 不做操作

        for device_obj in list(set(server_obj.networkdevice_set.all()) - set(current_device_queryset)):
            device_obj.delete()

productmodel的2种更新写法

通过系统的update

需要 productmode/1 PUT这种实现. 适用于前端和用户交互.

自己实现update, 这种就post方法实现 新增+更新.

适用于后端搜集数据

创建prodcutmodel条目时 1,通过manufacture验证productmodel唯一性 2,productmodel既有字段的更新写法

  • 原始数据,第一次提交
{
    "model_name": "mi8",
    "vender": "xiaomi",
    "nick_model_name": "xiaomi8888"
}

第二次提交, 我希望更新一下nick_model_name字段

{
    "model_name": "mi8",
    "vender": "xiaomi",
    "nick_model_name": "xiaomi"
}
class ProductModelSerializer(serializers.Serializer):  # 必须实现create: `create()` must be implemented.
    model_name = serializers.CharField(max_length=20)
    vender = serializers.CharField(max_length=20)
    nick_model_name = serializers.CharField(max_length=40)

    # 制造商验证
    def validate_vender(self, value):
        try:
            # 制造商是否存在
            manufacturer_obj = Manufacturer.objects.get(vender_name__exact=value)
        except Manufacturer.DoesNotExist:
            manufacturer_obj = Manufacturer.objects.create(vender_name=value)
        return manufacturer_obj

    def create(self, validated_data):
        manufacturer_obj = validated_data['vender']
        try:
            # 型号是否存在
            productmodel_obj = manufacturer_obj.productmodel_set.get(model_name__exact=validated_data['model_name'])
        except ProductModel.DoesNotExist:
            # productmodel不存在: 创建
            productmodel_obj = self.create_productmodel(validated_data)
        else:
            # productmodel存在: 更新(这里更新这个obj的nick_model_name字段,一般外键不更新)
            productmodel_obj = self.update_productmodel(productmodel_obj, validated_data)
        return productmodel_obj

    def create_productmodel(self, validated_data):
        productmodel_obj = ProductModel.objects.create(**validated_data)
        return productmodel_obj

    def update_productmodel(self, instance, validated_data):
        instance.model_name = validated_data.get('model_name', instance.model_name)
        instance.nick_model_name = validated_data.get('nick_model_name', instance.nick_model_name)
        instance.save()
        return instance

原文地址:https://www.cnblogs.com/iiiiiher/p/9921613.html