mirror of
https://github.com/hequan2017/seal.git
synced 2026-02-13 15:16:16 +08:00
0.2 增加 API 例子
This commit is contained in:
11
README.md
11
README.md
@@ -1,8 +1,9 @@
|
||||
# 海豹
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
> django-base-templastes
|
||||
|
||||
> 因本项目开始时间为3月1日,是 国际海豹日,故项目起名为 海豹 seal
|
||||
@@ -11,11 +12,11 @@
|
||||
|
||||
|
||||
## 介绍
|
||||
* 基于bootstrap4+django2.1+python3.6+celery异步任务
|
||||
* 基于bootstrap4+django2.1+python3.6+celery4 异步任务
|
||||
* 前端模板 inspinia 2.9
|
||||
* 会尽量多加一些注释
|
||||
* 采用cbv开发方式,提高开发效率
|
||||
* python3.7 兼容性未做测试
|
||||
* 增加 drf api 例子
|
||||
|
||||
|
||||
## DEMO
|
||||
@@ -48,6 +49,8 @@ python manage.py createsuperuser
|
||||
python manage.py runserver 0.0.0.0:80
|
||||
|
||||
```
|
||||
|
||||
|
||||
* 扩展功能-异步1 推荐 定时任务用celery
|
||||
```bash
|
||||
#需要安装redis
|
||||
|
||||
@@ -3,11 +3,11 @@ from django.db import models
|
||||
|
||||
class Ecs(models.Model):
|
||||
TYPE_CHOICES = (
|
||||
('0', '阿里云'),
|
||||
('1', '腾讯云'),
|
||||
('2', '华为云'),
|
||||
('3', '亚马逊'),
|
||||
('4', '其他'),
|
||||
('阿里云', '阿里云'),
|
||||
('腾讯云', '腾讯云'),
|
||||
('华为云', '华为云'),
|
||||
('亚马逊', '亚马逊'),
|
||||
('其他', '其他'),
|
||||
)
|
||||
hostname = models.CharField(max_length=96, verbose_name='主机名', blank=True, null=True, )
|
||||
type = models.CharField(choices=TYPE_CHOICES, max_length=16, verbose_name='主机类型')
|
||||
|
||||
8
assets/serializers.py
Normal file
8
assets/serializers.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from rest_framework import serializers
|
||||
from assets.models import Ecs
|
||||
|
||||
|
||||
class EcsSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Ecs
|
||||
fields = '__all__'
|
||||
@@ -9,4 +9,8 @@ urlpatterns = [
|
||||
path('ecs-update-<int:pk>', views.EcsUpdateView.as_view(), name='ecs-update'),
|
||||
path('ecs-detail-<int:pk>', views.EcsDetailView.as_view(), name='ecs-detail'),
|
||||
path('ecs-delete', views.EcsDeleteView.as_view(), name='ecs-delete'),
|
||||
|
||||
|
||||
path('api/ecs', views.ApiEcsList.as_view()),
|
||||
path('api/ecs/<int:pk>', views.ApiEcsDetail.as_view()),
|
||||
]
|
||||
|
||||
@@ -11,6 +11,15 @@ from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMix
|
||||
from django.views.generic import ListView, View, DetailView, CreateView, UpdateView
|
||||
from assets.models import Ecs
|
||||
from assets.form import EcsForm
|
||||
from assets.serializers import EcsSerializer
|
||||
from rest_framework import permissions
|
||||
from rest_framework import generics
|
||||
from rest_framework.authentication import TokenAuthentication
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from rest_framework import filters
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.response import Response
|
||||
|
||||
logger = logging.getLogger('assets')
|
||||
|
||||
@@ -26,7 +35,6 @@ class EcsCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
|
||||
template_name = 'assets/ecs-create.html'
|
||||
success_url = reverse_lazy('assets:ecs-list')
|
||||
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {}
|
||||
if '__next__' in self.request.POST: # 为了获取 点击本页之前的 浏览网页
|
||||
@@ -42,7 +50,7 @@ class EcsCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
|
||||
def get_success_url(self):
|
||||
return self.request.POST['__next__']
|
||||
|
||||
def form_valid(self, form): ## 保存结果 可以进行 手动 修改 再保存
|
||||
def form_valid(self, form): # 保存结果 可以进行 手动 修改 再保存
|
||||
obj = form.save(commit=False)
|
||||
obj.save()
|
||||
return super().form_valid(form)
|
||||
@@ -53,8 +61,6 @@ class EcsCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
|
||||
return self.render_to_response(self.get_context_data(form=form))
|
||||
|
||||
|
||||
|
||||
|
||||
class EcsListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
||||
permission_required = ('assets.view_ecs',)
|
||||
template_name = 'assets/ecs-list.html'
|
||||
@@ -73,14 +79,13 @@ class EcsListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
|
||||
context = {
|
||||
"ecs_list": ecs_list,
|
||||
'ecs_count': self.queryset.count() if self.queryset != '' else 0,
|
||||
"filter_dict":self.filter_dict ## 把查询条件返回给前端
|
||||
"filter_dict": self.filter_dict # 把查询条件返回给前端
|
||||
}
|
||||
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
|
||||
class EcsUpdateView(LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
|
||||
"""
|
||||
Ecs 更新
|
||||
@@ -117,13 +122,12 @@ class EcsDetailView(LoginRequiredMixin, PermissionRequiredMixin, DetailView):
|
||||
pk = self.kwargs.get(self.pk_url_kwarg, None)
|
||||
context = {
|
||||
"ecs": self.model.objects.get(id=pk),
|
||||
"nid":pk
|
||||
"nid": pk
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
|
||||
|
||||
|
||||
class EcsDeleteView(LoginRequiredMixin, PermissionRequiredMixin, View):
|
||||
"""
|
||||
Ecs 删除
|
||||
@@ -135,4 +139,20 @@ class EcsDeleteView(LoginRequiredMixin, PermissionRequiredMixin, View):
|
||||
ret = {'status': True, 'error': None, }
|
||||
nid = self.request.POST.get('nid', None)
|
||||
self.model.objects.get(id=nid).delete()
|
||||
return HttpResponse(json.dumps(ret))
|
||||
return HttpResponse(json.dumps(ret))
|
||||
|
||||
|
||||
# Ecs Api drf 中文文档 http://drf.jiuyou.info/#/drf/requests
|
||||
class ApiEcsList(generics.ListCreateAPIView):
|
||||
queryset = Ecs.objects.get_queryset().order_by('id')
|
||||
serializer_class = EcsSerializer
|
||||
filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
|
||||
filter_fields = ('id', 'hostname', 'type', 'instance_id')
|
||||
search_fields = ('id', 'hostname',)
|
||||
permission_classes = (permissions.DjangoModelPermissions,) # 继承 django的权限
|
||||
|
||||
|
||||
class ApiEcsDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
queryset = Ecs.objects.get_queryset().order_by('id')
|
||||
serializer_class = EcsSerializer
|
||||
permission_classes = (permissions.DjangoModelPermissions,)
|
||||
|
||||
@@ -5,24 +5,33 @@ billiard==3.5.0.5
|
||||
celery==4.2.1
|
||||
certifi==2018.11.29
|
||||
chardet==3.0.4
|
||||
coreapi==2.3.3
|
||||
coreschema==0.0.4
|
||||
decorator==4.3.0
|
||||
Django==2.1.7
|
||||
django-bootstrap4==0.0.7
|
||||
django-celery-beat==1.4.0
|
||||
django-celery-results==1.0.4
|
||||
django-cors-headers==2.5.2
|
||||
django-crispy-forms==1.7.2
|
||||
django-filter==2.1.0
|
||||
django-pure-pagination==0.3.0
|
||||
django-timezone-field==3.0
|
||||
djangorestframework==3.9.2
|
||||
dramatiq==1.5.0
|
||||
gevent==1.4.0
|
||||
greenlet==0.4.15
|
||||
idna==2.8
|
||||
ipython==6.4.0
|
||||
ipython-genutils==0.2.0
|
||||
itypes==1.1.0
|
||||
jedi==0.12.0
|
||||
Jinja2==2.10
|
||||
jsonfield==2.0.2
|
||||
kombu==4.4.0
|
||||
MarkupSafe==1.1.1
|
||||
mysqlclient==1.4.2.post1
|
||||
openapi-codec==1.3.2
|
||||
parso==0.2.1
|
||||
pathtools==0.1.2
|
||||
pexpect==4.6.0
|
||||
@@ -38,8 +47,10 @@ PyYAML==5.1
|
||||
redis==3.2.0
|
||||
requests==2.21.0
|
||||
simplegeneric==0.8.1
|
||||
simplejson==3.16.0
|
||||
six==1.11.0
|
||||
traitlets==4.3.2
|
||||
uritemplate==3.0.0
|
||||
urllib3==1.24.1
|
||||
vine==1.2.0
|
||||
watchdog==0.8.3
|
||||
|
||||
@@ -12,6 +12,7 @@ https://docs.djangoproject.com/en/2.1/ref/settings/
|
||||
|
||||
import os
|
||||
import sys
|
||||
import socket
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
@@ -41,12 +42,16 @@ INSTALLED_APPS = [
|
||||
'bootstrap4',
|
||||
'django_celery_results',
|
||||
'django_celery_beat',
|
||||
|
||||
'rest_framework',
|
||||
'rest_framework.authtoken',
|
||||
'corsheaders',
|
||||
'django_filters',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'corsheaders.middleware.CorsMiddleware',
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
'django.middleware.csrf.CsrfViewMiddleware',
|
||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
@@ -80,24 +85,25 @@ AUTHENTICATION_BACKENDS = ('system.views.CustomBackend',) ## 重新登录验证
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
|
||||
if socket.gethostname().endswith('test'):
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'HOST': '192.168.100.50',
|
||||
'PORT': '3306',
|
||||
'NAME': 'seal',
|
||||
'USER': 'root',
|
||||
'PASSWORD': '123456',
|
||||
}
|
||||
}
|
||||
else:
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# DATABASES = {
|
||||
# 'default': {
|
||||
# 'ENGINE': 'django.db.backends.mysql',
|
||||
# 'HOST': '192.168.100.50',
|
||||
# 'PORT': '3306',
|
||||
# 'NAME': 'seal',
|
||||
# 'USER': 'root',
|
||||
# 'PASSWORD': '123456',
|
||||
# }
|
||||
# }
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
|
||||
@@ -185,7 +191,6 @@ PAGINATION_SETTINGS = {
|
||||
# 表格table 一页 展示数据
|
||||
DISPLAY_PER_PAGE = 15
|
||||
|
||||
|
||||
## celery 4
|
||||
CELERY_RESULT_BACKEND = 'redis://localhost:6379/1'
|
||||
# CELERY_RESULT_BACKEND = 'django-db'
|
||||
@@ -207,6 +212,32 @@ CELERY_ENABLE_UTC = False
|
||||
CELERY_TASK_SERIALIZER = 'json'
|
||||
CELERY_RESULT_SERIALIZER = 'json'
|
||||
|
||||
|
||||
## 钉钉 报警机器人 地址 调用地方为 system.tasks.ding_ding_to_info
|
||||
web_hook_url=""
|
||||
web_hook_url = ""
|
||||
|
||||
## rest api
|
||||
REST_FRAMEWORK = {
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
||||
'rest_framework.authentication.BasicAuthentication',
|
||||
'rest_framework.authentication.TokenAuthentication',
|
||||
'rest_framework.authentication.SessionAuthentication',
|
||||
),
|
||||
'DEFAULT_RENDERER_CLASSES': (
|
||||
'rest_framework.renderers.JSONRenderer',
|
||||
'rest_framework.renderers.BrowsableAPIRenderer' #注释掉 可以关闭 api web界面
|
||||
),
|
||||
'DEFAULT_PERMISSION_CLASSES': (
|
||||
# 'rest_framework.permissions.AllowAny',
|
||||
'rest_framework.permissions.IsAuthenticated',
|
||||
),
|
||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
|
||||
'PAGE_SIZE': 15,
|
||||
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',),
|
||||
}
|
||||
|
||||
CORS_ALLOW_CREDENTIALS = True
|
||||
CORS_ORIGIN_ALLOW_ALL = True
|
||||
CORS_ORIGIN_WHITELIST = (
|
||||
'*',
|
||||
)
|
||||
MIDDLEWARE_CLASSES = ('system.views.DisableCSRFCheck',)
|
||||
26
seal/urls.py
26
seal/urls.py
@@ -1,28 +1,20 @@
|
||||
"""seal URL Configuration
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/2.1/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
from django.conf.urls import include
|
||||
from system.views import index
|
||||
from rest_framework.authtoken import views
|
||||
from rest_framework.documentation import include_docs_urls
|
||||
|
||||
API_TITLE = '海豹 API 文档'
|
||||
API_DESCRIPTION = '海豹 API 文档'
|
||||
|
||||
urlpatterns = [
|
||||
path('', index),
|
||||
path('index', index, name="index"),
|
||||
path('system/', include('system.urls', namespace='system')),
|
||||
path('assets/', include('assets.urls', namespace='assets')),
|
||||
path('admin/', admin.site.urls,)
|
||||
|
||||
path('admin/', admin.site.urls, ),
|
||||
path('api/token', views.obtain_auth_token),
|
||||
path('api/docs/', include_docs_urls(title=API_TITLE, description=API_DESCRIPTION, authentication_classes=[],
|
||||
permission_classes=[]))
|
||||
]
|
||||
|
||||
@@ -16,4 +16,5 @@ class Users(AbstractUser):
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
def __str__(self):
|
||||
return self.username
|
||||
return self.username
|
||||
|
||||
|
||||
@@ -102,4 +102,9 @@ def logout_view(request):
|
||||
:return:
|
||||
"""
|
||||
logout(request)
|
||||
return redirect('system:login')
|
||||
return redirect('system:login')
|
||||
|
||||
|
||||
class DisableCSRFCheck(object):
|
||||
def process_request(self, request):
|
||||
setattr(request, '_dont_enforce_csrf_checks', True)
|
||||
|
||||
Reference in New Issue
Block a user