一.5.序列化应用之服务器制造厂与型号app功能

 1.环境准备:

 (python36env) [vagrant@CentOS7 apps]$ django-admin startapp manufacturer

(1)激活:'manufacturer.apps.ManufacturerConfig'

 (2)模型:manufacturer/models.py

from django.db import models

#制造厂表(一)
class Manufacturer(models.Model):
    vendor_name = models.CharField("厂商名称", max_length=32, db_index=True, unique=True, help_text="厂商名称")
    tel = models.CharField("联系电话", null=True, max_length=15, help_text="联系电话")
    email = models.EmailField("联系邮件", null=True,blank=True,max_length=32, help_text="联系邮件")
    remark = models.CharField("备注", max_length=300,null=True, help_text="备注")
    def __str__(self):
        return self.vendor_name
    class Meta:
        db_table = "resources_manufacturer"
        ordering = ["id"]

#型号表(多)--foreignkey放多中
class ProductModel(models.Model):
    model_name = models.CharField("型号名称",max_length=20, help_text="型号名称")
    vendor = models.ForeignKey(Manufacturer,verbose_name="所属制造商", help_text="所属制造商",on_delete=models.CASCADE)
    def __str__(self):
        return self.model_name
    class Meta:
        db_table = "resources_productmodel"
        #排序
        ordering = ["id"]

(python36env) [vagrant@CentOS7 devops]$ python manage.py makemigrations manufacturer

(python36env) [vagrant@CentOS7 devops]$ python manage.py migrate manufacturer

(3)序列化manufacturer/serializers.py:---使用的是模型序列化,所以所有字段的格式,数据类型可直接在模型中加

from rest_framework import serializers
from .models import Manufacturer, ProductModel
#ModelSerializer模型序列化和Serializer序列化的区别是:它有Meta选项,且它帮我们实现了create和update方法,不用再写
class ManufacturerSerializer(serializers.ModelSerializer):

    class Meta:
        #指定它模型是哪个
        model = Manufacturer
        #序列化哪些字段
        fields = "__all__"

class ProductModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = ProductModel
        fields = "__all__"

(4)视图manufacturer/views.py:

from django.shortcuts import render
from rest_framework import viewsets
from .models import Manufacturer, ProductModel
from .serializers import ManufacturerSerializer,ProductModelSerializer

class ManufacturerViewset(viewsets.ModelViewSet):
    """
    retrieve:返回指定制造商信息
     list:返回指定制造商列表
     update:更新制造商信息
     destroy:删除制造商记录
     create:创建制造商记录
     partial_update:更新部分字段
    """
    #1.指定queryset
    queryset = Manufacturer.objects.all()
    #2.指定序列化类
    serializer_class = ManufacturerSerializer

class ProductModelViewset(viewsets.ModelViewSet):
    """
    retrieve:返回指定制造商信息
     list:返回指定制造商列表
     update:更新制造商信息
     destroy:删除制造商记录
     create:创建制造商记录
     partial_update:更新部分字段
    """
    #1.指定queryset
    queryset = ProductModel.objects.all()
    #2.指定序列化类
    serializer_class = ProductModelSerializer

(5)urls.py路由:

from django.conf.urls import include, url
from django.contrib import admin
from rest_framework.routers import DefaultRouter
from idcs.views import IdcViewset
from users.views import UserViewset
from cabinet.views import CabinetViewset
from manufacturer.views import ManufacturerViewset,ProductModelViewset
from rest_framework.documentation import include_docs_urls

route = DefaultRouter()
route.register("idcs", IdcViewset, basename="idcs")
#注册时三个参数:资源定位符,类,别名
route.register("users", UserViewset, basename="users")
route.register("cabinet", CabinetViewset, basename="cabinet")
route.register("manufacturer", ManufacturerViewset, basename="manufacturer")
route.register("productmodel", ProductModelViewset, basename="productmodel")
urlpatterns = [
    url(r'^', include(route.urls)),
    url(r'^docs/', include_docs_urls("lizhihua运维平台接口文档"))
]

效果如下几图

 但是如下图中:

 2.完善功能

(1)manufacturer/Serializer.py中class ProductModelSerializer类中可增加如下方法:

    def to_representation(self, instance):
        vendor = instance.vendor
        ret = super(ProductModelSerializer, self).to_representation(instance)
        ret["vendor"] = {
            "id": vendor.id,
            "name": vendor.vendor_name
        }
        return ret

最终效果如下图了:

但是上述效果中,你若再添加一戴尔的R710型号那模型中是可允许R710有重复的记录,但从业务逻辑上是不允许的, 所以此时就需要通过验证来解决这个问题----从业务层面上去处理这种验证关系--序列化中处理。

首先这里需要验证的是模型名称不能重复,只要它是个字符串在模型层面是可以重复的,但在业务层面不允许重复---两种方式:基于字段和基于模型去验证

https://www.django-rest-framework.org/api-guide/validators/#advanced-field-defaults----帮助文档

(2)manufacturer/Serializer.py中class ProductModelSerializer类中可增加如下方法:

class ProductModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = ProductModel
        fields = "__all__"
    # #基于字段级别验证法:如把model_name字段转成大写--这只能是单个字段的,若要多个字段要用模型对象级别验证--表级别验证
    # def validate_model_name(self, value):
    #     return value.upper()
    #基于模型对象级别验证法:
    def validate(self, attrs):
        #取到数据
        manufacturer_obj = attrs["vendor"]
        try:
            manufacturer_obj.productmodel_set.get(model_name__exact=attrs["model_name"])
            raise serializers.ValidationError("该型号已经存在")
        except ProductModel.DoesNotExist:
            return attrs

    def to_representation(self, instance):
        vendor = instance.vendor
        ret = super(ProductModelSerializer, self).to_representation(instance)
        ret["vendor"] = {
            "id": vendor.id,
            "name": vendor.vendor_name
        }
        return ret
原文地址:https://www.cnblogs.com/dbslinux/p/13097363.html