diff --git a/api/__init__.py b/api/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/api/router.py b/api/router.py new file mode 100644 index 0000000000000000000000000000000000000000..b527e27341017e33f7f2db59c75a8af4a2ce2f75 --- /dev/null +++ b/api/router.py @@ -0,0 +1,17 @@ +from django.conf.urls import url, include +from rest_framework import routers + +from appStore.env.views import EnvViewSet +from appStore.stream.views import StreamViewSet + +router = routers.DefaultRouter() +#################### +# 公共地址映射 # +################### +# router.register(r'stream', StreamViewSet, basename='stream') +router.register(r'env', EnvViewSet, basename='env') + +urlpatterns = [ + # url(r'^y_upload_file/', y_upload_file), # upload_file + url(r'', include(router.urls)), +] diff --git a/env/__init__.py b/env/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/env/admin.py b/env/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e --- /dev/null +++ b/env/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/env/apps.py b/env/apps.py new file mode 100644 index 0000000000000000000000000000000000000000..5f61f54f15d65e1cff941d6b9bf1b394f10bb94c --- /dev/null +++ b/env/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class EnvConfig(AppConfig): + name = 'appStore.env' diff --git a/env/migrations/__init__.py b/env/migrations/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/env/models.py b/env/models.py new file mode 100644 index 0000000000000000000000000000000000000000..c9e24d089f9d8cc0a2aade8f8b8ef15672ba9f7e --- /dev/null +++ b/env/models.py @@ -0,0 +1,87 @@ +from django.db import models + + +# Create your models here. + +class Env(models.Model): + """环境信息表""" + + hwinfo_machineinfo_manufacturer = models.CharField(max_length=50, verbose_name='manufacturer') + hwinfo_machineinfo_product = models.CharField(max_length=50, verbose_name='product') + hwinfo_machineinfo_serialnumber = models.CharField(max_length=255, verbose_name='serialnumber') + hwinfo_bios_vendor = models.CharField(max_length=50, verbose_name='vendor') + hwinfo_bios_version = models.CharField(max_length=50, verbose_name='version') + hwinfo_cpu_Vendor_ID = models.CharField(max_length=50, verbose_name='Vendor ID') + hwinfo_cpu_CPU_family = models.IntegerField(verbose_name='CPU family') + hwinfo_cpu_model_name = models.CharField(max_length=50, verbose_name='model_name') + hwinfo_cpu_CPU_MHz = models.TextField(max_length=100, verbose_name='CPU MHz') + hwinfo_cpu_CPUs = models.IntegerField(verbose_name='CPU(s)') + hwinfo_cpu_Threads_per_core = models.IntegerField(verbose_name='Thread(s) per core') + hwinfo_cpu_CPU_Arch = models.CharField(max_length=50, verbose_name='CPU Arch') + hwinfo_cpu_CPU_op_mode = models.CharField(max_length=50, verbose_name='CPU op-mode') + hwinfo_cpu_Byte_Order = models.CharField(max_length=50, verbose_name='Byte Order') + hwinfo_cpu_On_line_CPUs_list = models.CharField(max_length=50, verbose_name='On-line CPU(s) list') + hwinfo_cpu_Virtualization = models.CharField(max_length=50, blank=True, null=True, verbose_name='Virtualization') + hwinfo_cpu_Virtualization_type = models.CharField(max_length=50, verbose_name='Virtualization type') + hwinfo_cpu_L1d_cache = models.CharField(max_length=50, verbose_name='L1d cache:') + hwinfo_cpu_L1i_cache = models.CharField(max_length=50, verbose_name='L1i cache') + hwinfo_cpu_L2_cache = models.CharField(max_length=50, verbose_name='L2 cache') + hwinfo_cpu_L3_cache = models.CharField(max_length=50, verbose_name='L3 cache') + hwinfo_memory_Flags = models.TextField(verbose_name='Flags') + hwinfo_memory_vendor = models.TextField(verbose_name='vendor') + hwinfo_memory_mem_type = models.CharField(max_length=50, verbose_name='mem_type') + hwinfo_memory_total_size = models.CharField(max_length=50, verbose_name='total_size') + hwinfo_memory_mem_used = models.CharField(max_length=50, verbose_name='mem_used') + hwinfo_memory_mem_count = models.IntegerField(verbose_name='mem_count') + hwinfo_memory_mem_free = models.CharField(max_length=50, verbose_name='mem_free') + hwinfo_memory_mem_freq = models.CharField(max_length=50, verbose_name='mem_freq') + hwinfo_memory_swap = models.CharField(max_length=50, verbose_name='swap') + # disk可能有多组的情况,所以在里直接把所有disk的json数据集体存入后期在做list化处理拿数据 + hwinfo_disk = models.TextField(verbose_name='disk', default="") + # hwinfo_disk_name = models.CharField(max_length=50, verbose_name='name') + # hwinfo_disk_part_type = models.CharField(max_length=50, verbose_name='part_type') + # hwinfo_disk_vendor = models.CharField(max_length=50, verbose_name='vendor') + # hwinfo_disk_model = models.CharField(max_length=50, verbose_name='model') + # hwinfo_disk_size = models.CharField(max_length=50, verbose_name='size') + # hwinfo_disk_rota = models.CharField(max_length=50, verbose_name='rota') + # hwinfo_disk_sched = models.CharField(max_length=50, verbose_name='sched') + # hwinfo_disk_rq_size = models.CharField(max_length=50, verbose_name='rq_size') + # hwinfo_disk_tran = models.CharField(max_length=50, verbose_name='tran') + # hwinfo_disk_mntpoint = models.CharField(max_length=50, verbose_name='mntpoint=/') + # hwinfo_disk_mntpoint_home = models.CharField(max_length=50, verbose_name='mntpoint=/home') + hwinfo_nicinfo = models.TextField(verbose_name='nicinfo', default="") + # hwinfo_nicinfo_logicalname = models.CharField(max_length=250, verbose_name='logicalname') + # hwinfo_nicinfo_product = models.CharField(max_length=50, verbose_name='product') + # hwinfo_nicinfo_speed = models.CharField(max_length=50, verbose_name='speed') + swinfo_os_curr_UTC_time = models.CharField(max_length=50, verbose_name='curr UTC time') + swinfo_os_os_id = models.CharField(max_length=50, verbose_name='os_id') + swinfo_os_os_arch = models.CharField(max_length=50, verbose_name='os_arch') + swinfo_os_osversion = models.CharField(max_length=50, verbose_name='osversion') + swinfo_os_kernel = models.TextField(verbose_name='kernel') + swinfo_os_grub = models.TextField(verbose_name='grub') + swinfo_runtime_sysconf = models.TextField(verbose_name='sysconf') + swinfo_runtime_sysctl = models.TextField(verbose_name='sysctl') + swinfo_runtime_systemctlinfo = models.TextField(verbose_name='systemctlinfo') + swinfo_runtime_driverinfo = models.TextField(verbose_name='driverinfo') + swinfo_runtime_rpmlist = models.TextField(verbose_name='rpmlist') + swinfo_runtime_ipclist = models.TextField(verbose_name='ipclist') + swinfo_runtime_selinux_status = models.CharField(max_length=50, verbose_name='selinux_status') + swinfo_runtime_power_status = models.CharField(max_length=50, verbose_name='power_status') + swinfo_runtime_cpu_sched = models.CharField(max_length=50, verbose_name='cpu_sched') + swinfo_runtime_loadavg = models.CharField(max_length=50, verbose_name='loadavg') + swinfo_runtime_uptime = models.CharField(max_length=50, verbose_name='uptime') + swinfo_software_ver_gccversion = models.CharField(max_length=50, verbose_name='gccversion') + swinfo_software_ver_glibcversion = models.CharField(max_length=50, verbose_name='glibcversion') + swinfo_software_ver_javaversion = models.TextField(verbose_name='javaversion') + swinfo_software_ver_g_version = models.CharField(max_length=50, verbose_name='g++version') + swinfo_software_ver_gfortranversion = models.CharField(max_length=50, verbose_name='gfortranversion') + swinfo_software_ver_pythonversion = models.CharField(max_length=50, verbose_name='pythonversion') + nwinfo_nic = models.TextField(verbose_name='nic', default="") + # nwinfo_nic_nicname = models.CharField(max_length=50, verbose_name='nicname') + # nwinfo_nic_ip = models.GenericIPAddressField(verbose_name='ip') + # nwinfo_nic_hwaddr = models.CharField(max_length=50, verbose_name='hwaddr') + # nwinfo_nic_gateway = models.CharField(max_length=50, verbose_name='gateway') + # nwinfo_nic_mtu = models.IntegerField(verbose_name='mtu') + + class Meta: + db_table = 'env' diff --git a/env/serializers.py b/env/serializers.py new file mode 100644 index 0000000000000000000000000000000000000000..90a257acf518b8f5afadf32e835eb25a99d70cea --- /dev/null +++ b/env/serializers.py @@ -0,0 +1,11 @@ +from rest_framework import serializers +from appStore.env.models import Env + +class EnvSerializer(serializers.ModelSerializer): + """ + 环境数据序列化 + """ + + class Meta: + model = Env + fields = '__all__' diff --git a/env/tests.py b/env/tests.py new file mode 100644 index 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /dev/null +++ b/env/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/env/views.py b/env/views.py new file mode 100644 index 0000000000000000000000000000000000000000..9ec0da3ffbbc578fe534f4da470655acb09cab10 --- /dev/null +++ b/env/views.py @@ -0,0 +1,22 @@ +import json +from base64 import b64decode + +from django.http import JsonResponse, request, HttpRequest +from django.shortcuts import render + +# Create your views here. +from rest_framework import status +from appStore.env.serializers import EnvSerializer +from appStore.utils.common import LimsPageSet, json_response, get_error_message +from appStore.utils.customer_view import CusModelViewSet + +class EnvViewSet(CusModelViewSet): + """ + stream数据管理 + """ + # queryset = Stream.objects.all().order_by('id') + serializer_class = EnvSerializer + # pagination_class = LimsPageSet + + + diff --git a/kytuningProject/urls.py b/kytuningProject/urls.py index bc60300d7ecc216850cd0d0f04404166459b51fe..1c2bcdb62a1e8096c3f265363f089129b7f3ec9e 100644 --- a/kytuningProject/urls.py +++ b/kytuningProject/urls.py @@ -18,5 +18,6 @@ from django.urls import path from django.conf.urls import include urlpatterns = [ - path('admin/', admin.site.urls), -] + # path('admin/', admin.site.urls), + path('kytuning/', include('appStore.api.router')), +] \ No newline at end of file diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/utils/common.py b/utils/common.py new file mode 100644 index 0000000000000000000000000000000000000000..687ff335efd9bfdc79ac4b32ea5df92b327b745f --- /dev/null +++ b/utils/common.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python +# encoding: utf-8 +""" +公共函数 +@author: Wqz +@time: 11/6/19 4:33 PM +""" +from django.core.paginator import Paginator, EmptyPage +from django.forms import model_to_dict +from django.http import JsonResponse +from rest_framework import pagination, status +from rest_framework.permissions import BasePermission +from appStore.utils import constants + + +def return_time(test_time): + time = test_time.split('-')[0] + '-' + test_time.split('-')[1] + '-' + test_time.split('-')[2] + ' ' + \ + test_time.split('-')[3] + ':' + test_time.split('-')[4] + ':' + test_time.split('-')[5] + return time + + +def json_response(data=None, code=None, message=None): + """ + 返回自定义格式数据 + :param data: + :param code: + :param message: + :return: + """ + res = { + 'data': data, + 'code': code, + 'message': message + } + return JsonResponse(res) + + +def list_response(result, code, message): + """ + :param result: + :param code: + :param message: + :return: + """ + res = {} + if result.data: + res['data'] = result.data + if code: + res['code'] = code + if message: + res['message'] = message + return JsonResponse(res) + + +def model_to_dict_myself(queryset, **kwargs): + """ + 返回model_to_dict转换的字段 + """ + if not queryset: + return {} + data = [] + if 'exclude' in kwargs.keys(): + for query in queryset: + dict = model_to_dict(query, exclude=kwargs['exclude']) + data.append(dict) + elif 'fields' in kwargs.keys(): + for query in queryset: + dict = model_to_dict(query, fields=kwargs['fields']) + data.append(dict) + else: + for query in queryset: + dict = model_to_dict(query) + data.append(dict) + return data + + +# def jwt_response_payload_handler(token, user=None, request=None): +# """ +# 自定义jwt认证成功返回数据 +# """ +# return { +# 'token': token, +# 'user_id': user.id, +# 'username': user.username, +# 'user_group_id':user.user_group_id, +# 'user_type':user.user_type +# } + +def get_error_message(serializer): + """ + 返回错误信息 + :param serializer: + :return: + """ + for _, error in serializer.errors.items(): + return error[0] + + +class LimsPageSet(pagination.PageNumberPagination): + """ + 分页设置 + 分页样式 ?page=1&page_size=10 + """ + page_size = 20 + page_size_query_param = 'page_size' + max_page_size = 1000 + page_query_param = 'page' + + +# class ZbmPermission(BasePermission): +# """ +# 管理员和超级管理员可以对系统进行各种 +# 权限操作,普通用户只能对信息进行查看 +# """ +# def has_permission(self, request, view): +# try: +# user_type = request.user.user_type_choices +# if user_type == 2 or request.user.is_superuser or request.method == 'GET': +# return True +# return False +# except: +# pass + + +def get_page(data, objs): + """ + 进行分页 + :param data: + :param objs: + :return: + """ + try: + page = int(data.get('page', 1)) + page_size = int(data.get('page_size', 5)) + except Exception as e: + return json_response({}, status.HTTP_400_BAD_REQUEST, '参数类型不对') + paginator = Paginator(objs, page_size) # 设置每一页显示几条 创建一个panginator对象 + try: + current_num = page # 当在url内输入的?page = 页码数 显示你输入的页面数目 默认为第2页 + list = paginator.page(current_num) + except EmptyPage: + list = paginator.page(1) # 当输入的page是不存在的时候就会报错 + return list diff --git a/utils/constants.py b/utils/constants.py new file mode 100644 index 0000000000000000000000000000000000000000..0d636fa89602312a69e546b3cd188d6f9f8a6850 --- /dev/null +++ b/utils/constants.py @@ -0,0 +1,26 @@ +import datetime + +NOW_TIME = datetime.datetime.now() + +# 最近一天时间戳 +LAST_DAY = 86400000 + +RESOURCE_TYPE_IMAGE_SENSOR = 'building_sensor_image' +RESOURCE_TYPE_IMAGE_SHOW = 'buliding_show_image' + +TODAY = ' 23:59:59' + +SENSOR_TYPE = {"1":"倾斜","2":"裂缝","3":"应变","4":"沉降","5":"振动"} +MON_TYPE = {"1":"监控","2":"观察","3":"预警","4":"提醒"} + + +# 七牛云配置 +QN_DOMAIN = 'http://qbpf75h7n.bkt.clouddn.com' +QN_ACCESS_KEY = 'CzjANWjTghSKJa9qubpTDJu8DCk6YcMXCgGdS2rO' +QN_SECRET_KEY = 'jLIWyjWuREnS3d6gzn9eWIENdj9zKVrv1yU2exOm' +QN_BUCKET = 'zhubangkeji' + +#北京2传感器对应边 +BJ_SENSOR = {"3_23_37_167_0":"W-SZ-20200601-09-ZD-07-01_100_9", + "3_23_37_167_1":"W-SZ-20200601-09-ZD-07-01_102_9", + "3_23_37_167_2":"W-SZ-20200601-09-ZD-07-01_103_9"} \ No newline at end of file diff --git a/utils/customer_mixin.py b/utils/customer_mixin.py new file mode 100644 index 0000000000000000000000000000000000000000..afcba0fa2897927f005cf03ca3202dc57864e17a --- /dev/null +++ b/utils/customer_mixin.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# encoding: utf-8 +""" +@author: morgan +@time: 8/7/19 4:26 PM +""" +from __future__ import unicode_literals + +from rest_framework import status + +from appStore.utils.common import json_response, get_error_message, list_response + + +class CusCreateModelMixin(object): + """ + Create a model instance. + """ + + def create(self, request, *args, **kwargs): + serializer = self.get_serializer(data=request.data) + if serializer.is_valid(): + self.perform_create(serializer) + return json_response(serializer.data, status.HTTP_200_OK, '创建成功!') + return json_response(serializer.errors, status.HTTP_400_BAD_REQUEST, get_error_message(serializer)) + + def perform_create(self, serializer): + serializer.save() + + +class CusListModelMixin(object): + """ + List a queryset. + """ + def list(self, request, *args, **kwargs): + queryset = self.filter_queryset(self.get_queryset()) + try: + page = self.paginate_queryset(queryset) + except: + return json_response({}, status.HTTP_200_OK, '计划列表获取为空,可能是page/page_size参数不对') + if page is not None: + serializer = self.get_serializer(page, many=True) + result = serializer.data + result = self.get_paginated_response(result) + return list_response(result, status.HTTP_200_OK, '列表') + serializer = self.get_serializer(queryset, many=True) + return json_response(serializer.data, status.HTTP_200_OK, '列表') + + +class CusRetrieveModelMixin(object): + """ + Retrieve a model instance.单个 + """ + + def retrieve(self, request, *args, **kwargs): + instance = self.get_object() + serializer = self.get_serializer(instance) + return json_response(serializer.data, status.HTTP_200_OK, '获取成功!') + + +class CusUpdateModelMixin(object): + """ + Update a model instance. + """ + + def update(self, request, *args, **kwargs): + partial = kwargs.pop('partial', True) + instance = self.get_object() + serializer = self.get_serializer(instance, data=request.data, partial=partial) + if serializer.is_valid(): + self.perform_update(serializer) + if getattr(instance, '_prefetched_objects_cache', None): + # If 'prefetch_related' has been applied to a queryset, we need to + # forcibly invalidate the prefetch cache on the instance. + instance._prefetched_objects_cache = {} + return json_response(serializer.data, status.HTTP_200_OK, '更新成功!') + return json_response(serializer.errors, status.HTTP_400_BAD_REQUEST, get_error_message(serializer)) + + def perform_update(self, serializer): + serializer.save() + + +class CusDestroyModelMixin(object): + """ + Destroy a model instance. + """ + + def destroy(self, request, *args, **kwargs): + instance = self.get_object() + self.perform_destroy(instance) + return json_response(True, status.HTTP_200_OK, '删除成功!') + + def perform_destroy(self, instance): + instance.delete() diff --git a/utils/customer_view.py b/utils/customer_view.py new file mode 100644 index 0000000000000000000000000000000000000000..40578019385a47b401778833b00210c15cfd1d5c --- /dev/null +++ b/utils/customer_view.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python +# encoding: utf-8 +""" +@author: morgan +@time: 8/7/19 4:29 PM +""" +from __future__ import unicode_literals + +from collections import OrderedDict +from functools import update_wrapper +from inspect import getmembers + +from django.urls import NoReverseMatch +from django.utils.decorators import classonlymethod +from django.views.decorators.csrf import csrf_exempt + +from rest_framework import generics, views +from rest_framework.reverse import reverse + +from appStore.utils.customer_mixin import CusRetrieveModelMixin, CusListModelMixin, CusCreateModelMixin, \ + CusUpdateModelMixin, \ + CusDestroyModelMixin + + +def _is_extra_action(attr): + return hasattr(attr, 'mapping') + + +class ViewSetMixin(object): + """ + This is the magic. + Overrides `.as_view()` so that it takes an `actions` keyword that performs + the binding of HTTP methods to actions on the Resource. + For example, to create a concrete view binding the 'GET' and 'POST' methods + to the 'list' and 'create' actions... + view = MyViewSet.as_view({'get': 'list', 'post': 'create'}) + """ + + @classonlymethod + def as_view(cls, actions=None, **initkwargs): + """ + Because of the way class based views create a closure around the + instantiated view, we need to totally reimplement `.as_view`, + and slightly modify the view function that is created and returned. + """ + # The name and description initkwargs may be explicitly overridden for + # certain route confiugurations. eg, names of extra actions. + cls.name = None + cls.description = None + + # The suffix initkwarg is reserved for displaying the viewset type. + # This initkwarg should have no effect if the name is provided. + # eg. 'List' or 'Instance'. + cls.suffix = None + + # The detail initkwarg is reserved for introspecting the viewset type. + cls.detail = None + + # Setting a basename allows a view to reverse its action urls. This + # value is provided by the router through the initkwargs. + cls.basename = None + + # actions must not be empty + if not actions: + raise TypeError("The `actions` argument must be provided when " + "calling `.as_view()` on a ViewSet. For example " + "`.as_view({'get': 'list'})`") + + # sanitize keyword arguments + for key in initkwargs: + if key in cls.http_method_names: + raise TypeError("You tried to pass in the %s method name as a " + "keyword argument to %s(). Don't do that." + % (key, cls.__name__)) + if not hasattr(cls, key): + raise TypeError("%s() received an invalid keyword %r" % ( + cls.__name__, key)) + + # name and suffix are mutually exclusive + if 'name' in initkwargs and 'suffix' in initkwargs: + raise TypeError("%s() received both `name` and `suffix`, which are " + "mutually exclusive arguments." % (cls.__name__)) + + def view(request, *args, **kwargs): + self = cls(**initkwargs) + # We also store the mapping of request methods to actions, + # so that we can later set the action attribute. + # eg. `self.action = 'list'` on an incoming GET request. + self.action_map = actions + + # Bind methods to actions + # This is the bit that's different to a standard view + for method, action in actions.items(): + handler = getattr(self, action) + setattr(self, method, handler) + + if hasattr(self, 'get') and not hasattr(self, 'head'): + self.head = self.get + + self.request = request + self.args = args + self.kwargs = kwargs + + # And continue as usual + return self.dispatch(request, *args, **kwargs) + + # take name and docstring from class + update_wrapper(view, cls, updated=()) + + # and possible attributes set by decorators + # like csrf_exempt from dispatch + update_wrapper(view, cls.dispatch, assigned=()) + + # We need to set these on the view function, so that breadcrumb + # generation can pick out these bits of information from a + # resolved URL. + view.cls = cls + view.initkwargs = initkwargs + view.actions = actions + return csrf_exempt(view) + + def initialize_request(self, request, *args, **kwargs): + """ + Set the `.action` attribute on the view, depending on the request method. + """ + request = super(ViewSetMixin, self).initialize_request(request, *args, **kwargs) + method = request.method.lower() + if method == 'options': + # This is a special case as we always provide handling for the + # options method in the base `View` class. + # Unlike the other explicitly defined actions, 'metadata' is implicit. + self.action = 'metadata' + else: + self.action = self.action_map.get(method) + return request + + def reverse_action(self, url_name, *args, **kwargs): + """ + Reverse the action for the given `url_name`. + """ + url_name = '%s-%s' % (self.basename, url_name) + kwargs.setdefault('request', self.request) + + return reverse(url_name, *args, **kwargs) + + @classmethod + def get_extra_actions(cls): + """ + Get the methods that are marked as an extra ViewSet `@action`. + """ + return [method for _, method in getmembers(cls, _is_extra_action)] + + def get_extra_action_url_map(self): + """ + Build a map of {names: urls} for the extra actions. + This method will noop if `detail` was not provided as a view initkwarg. + """ + action_urls = OrderedDict() + + # exit early if `detail` has not been provided + if self.detail is None: + return action_urls + + # filter for the relevant extra actions + actions = [ + action for action in self.get_extra_actions() + if action.detail == self.detail + ] + + for action in actions: + try: + url_name = '%s-%s' % (self.basename, action.url_name) + url = reverse(url_name, self.args, self.kwargs, request=self.request) + view = self.__class__(**action.kwargs) + action_urls[view.get_view_name()] = url + except NoReverseMatch: + pass # URL requires additional arguments, ignore + + return action_urls + + +class ViewSet(ViewSetMixin, views.APIView): + """ + The base ViewSet class does not provide any actions by default. + """ + pass + + +class GenericViewSet(ViewSetMixin, generics.GenericAPIView): + """ + The GenericViewSet class does not provide any actions by default, + but does include the base set of generic view behavior, such as + the `get_object` and `get_queryset` methods. + """ + pass + + +class CusReadOnlyModelViewSet(CusRetrieveModelMixin, + CusListModelMixin, + GenericViewSet): + """ + 只读 列表和详情 + """ + pass + + +class CusReadOnlyListModelViewSet(CusListModelMixin, + GenericViewSet): + """ + 只读列表 + """ + pass + + +class CusModelViewSet(CusCreateModelMixin, + CusRetrieveModelMixin, + CusUpdateModelMixin, + CusDestroyModelMixin, + CusListModelMixin, + GenericViewSet): + """ + 都允许 + """ + pass + + +class CusUpdateModelViewSet(CusUpdateModelMixin, + GenericViewSet): + """ + 只允许更新 + """ + pass + + +class CusCreateModelViewSet(CusCreateModelMixin, + GenericViewSet): + """ + 只允许创建 + """ + pass + + +class CusNotDeViewSet(CusCreateModelMixin, + CusRetrieveModelMixin, + CusUpdateModelMixin, + CusListModelMixin, + GenericViewSet): + """ + 不允许删除 + """ + pass