django: django rest framework Viewsets 和 Serializers

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/linux_player_c/article/details/80772763

django rest framework Viewsets 和 Serializers


使用drf的Viewsets和Serializers可以大大简化视图和对数据进行增删该查的编写代码。本文将会通过一个示例项目,详细地介绍利用drf对数据进行操作。

示例代码github地址:

https://github.com/jinjidejuren/drf_learn

项目的结构如下所示:
这里写图片描述

在对一个数据模型进行操作,一般的操作步骤如下:

1.确定models.py文件中模型的结构,也就是模型所包含的数据结构(该结构会映射到数据库中);
2.编写各模型对应的序列化类;
3.实现模型的视图操作类(在该类中可以实现搜索、分页、过滤、排序和权限控制等相关操作);
4.实现相关路由信息;

接下来我们逐个实现上述步骤,完成django rest framework开发的常见模式。而且在drf的官方文档中对各部分的实现也有详细的介绍。官方文档地址如下:
http://www.django-rest-framework.org/

django rest framework的使用要求如下:

REST framework requires the following:

Python (2.7, 3.2, 3.3, 3.4, 3.5, 3.6)
Django (1.10, 1.11, 2.0)
The following packages are optional:

coreapi (1.32.0+) - Schema generation support.
Markdown (2.1.0+) - Markdown support for the browsable API.
django-filter (1.0.1+) - Filtering support.
django-crispy-forms - Improved HTML display for filtering.
django-guardian (1.1.1+) - Object level permissions support.

python的版本最好是3.6.x, django 这里使用的是1.11版本,下边的其他组件,可以使用pip进行安装:

pip install coreapi Markdown django-filter django-crispy-forms django-guardian

在项目的配置文件settings/base.py中添加rest_framework到应用列表中:

INSTALLED_APPS = [
    # 'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'apps.assets',
    'apps.rbac'
]

自己的应用apps.assets也需要添加到应用列表中。

django rest framework的登录地址可以注册在主路由文件中,在conf/urls.py的urlpatterns中做如下设置:

url(r'^assets/v1/', include('apps.assets.urls')),
url(r'^api-auth/', include('rest_framework.urls')),

第一行我们对api接口的url设定版本为v1,这是为了符合restful接口标准(后续将会介绍restful接口设计标准,以及接口文档的编写)。

在apps/assets/models.py文件中定义各model模型,这个示例实现了Region(区域)、MachineRoom(机房)、Cabinet(机柜)、Device(设备):

from django.db import models


class Region(models.Model):
    """
    区域
    """
    region_name = models.CharField(verbose_name=u'区域', max_length=64, blank=True, unique=True)
    created_time = models.DateTimeField(verbose_name=u'创建时间', auto_now_add=True, null=True)
    modified_time = models.DateTimeField(verbose_name=u'修改时间', null=True)
    is_delete = models.IntegerField(u'删除', default=0)

    class Meta:
        verbose_name = u'区域'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.region_name


class MachineRoom(models.Model):
    """
    机房
    """
    room_name = models.CharField(verbose_name=u'机房名称', max_length=64, blank=True, unique=True)
    room_code = models.CharField(verbose_name=u'机房编号', max_length=64, blank=True, null=True)
    region_id = models.IntegerField(verbose_name=u'区域id', blank=True)
    created_time = models.DateTimeField(verbose_name=u'创建时间', auto_now_add=True, null=True)
    modified_time = models.DateTimeField(verbose_name=u'修改时间', null=True)
    is_delete = models.IntegerField(u'删除', default=0)

    class Meta:
        verbose_name = u'机房'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.room_name


class Cabinet(models.Model):
    """
    机柜
    """
    cabinet_name = models.CharField(verbose_name=u'机柜名称', max_length=64, blank=True)
    cabinet_code = models.CharField(verbose_name=u'机柜编号', max_length=64, blank=True)
    room_id = models.IntegerField(verbose_name=u'机房id', blank=True)
    created_time = models.DateTimeField(verbose_name=u'创建时间', auto_now_add=True, null=True)
    modified_time = models.DateTimeField(verbose_name=u'修改时间', null=True)
    is_delete = models.IntegerField(u'删除', default=0)

    class Meta:
        verbose_name = u'机柜'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.cabinet_name


class Device(models.Model):
    """
    设备
    """
    type_choices = (
        ('storage', '存储设备'),
        ('safe', '安全设备')
    )

    device_name = models.CharField(verbose_name=u'设备名称', max_length=64,
                                   blank=True, unique=True)
    device_type = models.CharField(verbose_name=u'设备类型', max_length=32,
                                   choices=type_choices, blank=True)
    brand = models.CharField(verbose_name=u'品牌', max_length=32, blank=True, null=True)
    model = models.CharField(verbose_name=u'型号', max_length=32, blank=True, null=True)
    hardware = models.TextField(verbose_name=u'硬件信息', blank=True, null=True)
    cabinet_id = models.IntegerField(verbose_name=u'机柜id', blank=True)
    created_time = models.DateTimeField(verbose_name=u'创建时间', auto_now_add=True, null=True)
    modified_time = models.DateTimeField(verbose_name=u'修改时间', null=True)
    is_delete = models.IntegerField(u'删除', default=0)

    class Meta:
        verbose_name = u'设备'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.device_name

实现上述model的序列化类,写入serializers.py文件:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 18-5-23 下午10:36
# @Author  : zhang chi
# @Site    : 
# @File    : serializers.py
# @Software: PyCharm
from rest_framework import serializers
from .models import *


class RegionSerializer(serializers.ModelSerializer):
    """
    区域序列化
    """

    class Meta:
        model = Region
        fields = ('id', 'region_name', 'created_time', 'modified_time')


class MachineRoomSerializer(serializers.ModelSerializer):
    """
    机房序列化
    """

    class Meta:
        model = MachineRoom
        fields = ('id', 'room_name', 'room_code', 'region_id',
                  'created_time', 'modified_time')


class CabinetSerializer(serializers.ModelSerializer):
    """
    机柜序列化
    """

    class Meta:
        model = Cabinet
        fields = ('id', 'cabinet_name', 'cabinet_code', 'room_id',
                  'created_time', 'modified_time')


class DeviceSerializer(serializers.ModelSerializer):
    """
    设备序列化
    """

    class Meta:
        model = Device
        fields = ('id', 'device_name', 'device_type', 'brand', 'model',
                  'hardware', 'cabinet_id', 'created_time', 'modified_time')


class ServiceSerializer(serializers.ModelSerializer):
    """
    服务器序列化
    """

    class Meta:
        model = Server
        fields = ('id', 'project', 'manager', 'service_tag', 'server_status', 'server_name',
                  'environment', 'brand', 'model', 'assets_number', 'ip_addr', 'cabinet_id')

接着需要实现views.py中各model的视图,这里我们推荐继承ModelViewSet,ModelViewSet帮我们做了很多增、删、查、改的操作,简化了代码的编写,apps/assets/views.py实现如下:

from rest_framework import viewsets
from rest_framework import permissions

from .serializers import *
from .paginations import *


class RegionViewSet(viewsets.ModelViewSet):
    """
    区域操作视图
    """
    queryset = Region.objects.all()
    serializer_class = RegionSerializer
    pagination_class = MyFormatResultsSetPagination
    permission_classes = (CustomerAccessPermission, )


class MachineRoomViewSet(viewsets.ModelViewSet):
    """
    机房操作视图
    """
    queryset = MachineRoom.objects.all()
    serializer_class = MachineRoomSerializer
    pagination_class = MyFormatResultsSetPagination


class CabinetViewSet(viewsets.ModelViewSet):
    """
    机柜操作视图
    """
    queryset = Cabinet.objects.all()
    serializer_class = CabinetSerializer
    pagination_class = MyFormatResultsSetPagination


class DeviceViewSet(viewsets.ModelViewSet):
    """
    设备操作视图
    """
    queryset = Device.objects.all()
    serializer_class = DeviceSerializer
    pagination_class = MyFormatResultsSetPagination

queryset、serializer_class、pagination_class分别对应ModelViewSet的返回集合、序列化类和分页类,如果有需求还可以设置排序方法、搜索、过滤的方法。这些类将会影响着返回的结果集合。所有操作的本质都是通过设置各种条件,将数据库中的数据按照指定的条件查询筛选出来


设置url

上述视图最后都需要用户访问url获取,所以需要将路由添加到urls.py中,在conf/urls.py中,包含了assets的路由表。在apps/assets/urls.py中添加路由:

from django.conf.urls import url, include
from rest_framework import routers
from apps.assets import views

router = routers.DefaultRouter()
router.register(r'regions', views.RegionViewSet, base_name='regions')
router.register(r'machine_rooms', views.MachineRoomViewSet, base_name='machine_rooms')
router.register(r'cabinets', views.CabinetViewSet, base_name='cabinets')
router.register(r'devices', views.DeviceViewSet, base_name='devices')


urlpatterns = [
    url(r'^', include(router.urls))
]

测试

我在本机调试时开发的端口为8060,访问http://127.0.0.1:8060/assets/v1/页面内容如下:
这里写图片描述

访问regions内容:http://127.0.0.1:8060/assets/v1/regions/

这里写图片描述
可以在这个页面上进行新增操作,如果指定具体某个id的信息,可以进行编辑删除操作。例如访问id为1的regions:http://127.0.0.1:8060/assets/v1/regions/1/
这里写图片描述


小结

作为一个drf入门的教程,我们可以了解到常见的开发模式。具体的细节和拓展在后续的课程进行讲解。例如过滤、排序、分页、搜索和权限控制。

猜你喜欢

转载自blog.csdn.net/linux_player_c/article/details/80772763
今日推荐