diff --git a/README.md b/README.md index 0a131e7..1694216 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,16 @@ ![语言](https://img.shields.io/badge/language-python3.6-blue.svg) ![语言](https://img.shields.io/badge/env-django2.1.7-red.svg) ![bootstrap4](https://img.shields.io/badge/model-bootstrap4-mauve.svg) +![RESETful](https://img.shields.io/badge/env-RESETful-red.svg) +![GraphQL](https://img.shields.io/badge/env-GraphQL-red.svg) > django-base-templastes > 因本项目开始时间为3月1日,是 国际海豹日,故项目起名为 海豹 seal -> 主要为 django 基础开发平台, MVC 模式 开发.支持 非前后端分离 和 前后端分离模式,可以拿来参考 开发 django项目 +> 主要为 django 基础开发平台, MVC 模式 开发.支持 非前后端分离 和 前后端分离模式,可以拿来参考 开发 django项目 + +> 支持 RESETful 和 GraphQL > vue 前端地址 https://github.com/hequan2017/seal-vue 持续开发中 @@ -21,11 +25,15 @@ * 采用cbv开发方式 * drf api 例子 * 前端 Vue版本 +* GraphQL ## DEMO ![列表](document/demo/1.jpg) ![添加](document/demo/2.jpg) +![API](document/demo/3.jpg) +![API](document/demo/4.jpg) +![API](document/demo/5.jpg) ## templates @@ -36,6 +44,46 @@ * document 代码规范 +## GraphQL +> 具体代码 请参考 seal/schema.py + +> 请求地址 : http://localhost/graphql + +> GraphQL 请求参数 +``` +query{ + users{ + id, + username, + email + } +} + +mutation createUser { + createUser (username: "test1") { + info { + id, + }, + ok + } +} + +mutation updateUser { + updateUser (pk:2,username: "test2") { + info { + id, + }, + ok + } +} + +mutation deleteUser { + deleteUser (pk:2) { + ok + } +} +``` + ## 部署 @@ -54,7 +102,7 @@ python manage.py runserver 0.0.0.0:80 ``` -## 其他 +## 异步任务 * 扩展功能-异步1 推荐 定时任务用celery ```bash #需要安装redis @@ -87,13 +135,16 @@ for i in Users.objects.all(): ``` -### 售后服务 +## 售后服务 * bootstrap4 中文文档 https://code.z01.com/v4/ * cbv 中文文档 http://ccbv.co.uk/projects/Django/2.1/django.views.generic.edit/ +* GraphQL 中文参考文档 https://passwo.gitbook.io/graphql/index/drf + +### 其他 * 有问题 可以加QQ群: 620176501 django开发讨论群 * 欢迎提出你的需求和意见,或者来加入到本项目中一起开发。 -## 作者 +### 作者 * 何全 diff --git a/assets/models.py b/assets/models.py index 1976993..e8b089c 100644 --- a/assets/models.py +++ b/assets/models.py @@ -8,9 +8,10 @@ class Ecs(models.Model): ('华为云', '华为云'), ('亚马逊', '亚马逊'), ('其他', '其他'), + (None,None), ) hostname = models.CharField(max_length=96, verbose_name='主机名', blank=True, null=True, ) - type = models.CharField(choices=TYPE_CHOICES, max_length=16, verbose_name='主机类型') + type = models.CharField(choices=TYPE_CHOICES, max_length=16, verbose_name='主机类型', blank=True, null=True, ) instance_id = models.CharField(max_length=64, verbose_name='实例ID', unique=True) instance_name = models.CharField(max_length=96, verbose_name='标签', blank=True, null=True, ) os_name = models.CharField(max_length=64, verbose_name='系统版本', blank=True, null=True, ) diff --git a/document/demo/3.jpg b/document/demo/3.jpg new file mode 100644 index 0000000..709181f Binary files /dev/null and b/document/demo/3.jpg differ diff --git a/document/demo/4.jpg b/document/demo/4.jpg new file mode 100644 index 0000000..bdebc97 Binary files /dev/null and b/document/demo/4.jpg differ diff --git a/document/demo/5.jpg b/document/demo/5.jpg new file mode 100644 index 0000000..605d065 Binary files /dev/null and b/document/demo/5.jpg differ diff --git a/requirements.txt b/requirements.txt index d083ac0..caeed80 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ amqp==2.4.2 +aniso8601==3.0.2 argh==0.26.2 backcall==0.1.0 billiard==3.5.0.5 @@ -8,7 +9,7 @@ chardet==3.0.4 coreapi==2.3.3 coreschema==0.0.4 decorator==4.3.0 -Django==2.1.7 +Django==2.2rc1 django-bootstrap4==0.0.7 django-celery-beat==1.4.0 django-celery-results==1.0.4 @@ -20,6 +21,10 @@ django-timezone-field==3.0 djangorestframework==3.9.2 dramatiq==1.5.0 gevent==1.4.0 +graphene==2.1.3 +graphene-django==2.2.0 +graphql-core==2.1 +graphql-relay==0.4.5 greenlet==0.4.15 idna==2.8 ipython==6.4.0 @@ -37,6 +42,7 @@ pathtools==0.1.2 pexpect==4.6.0 pickleshare==0.7.4 prometheus-client==0.2.0 +promise==2.2.1 prompt-toolkit==1.0.15 ptyprocess==0.5.2 Pygments==2.2.0 @@ -46,13 +52,16 @@ pytz==2018.4 PyYAML==5.1 redis==3.2.0 requests==2.21.0 +Rx==1.6.1 simplegeneric==0.8.1 simplejson==3.16.0 +singledispatch==3.4.0.3 six==1.11.0 +sqlparse==0.3.0 traitlets==4.3.2 uritemplate==3.0.0 urllib3==1.24.1 vine==1.2.0 watchdog==0.8.3 watchdog-gevent==0.1.0 -wcwidth==0.1.7 +wcwidth==0.1.7 \ No newline at end of file diff --git a/seal/schema.py b/seal/schema.py new file mode 100644 index 0000000..7408af5 --- /dev/null +++ b/seal/schema.py @@ -0,0 +1,105 @@ +from system.models import Users +from graphene_django import DjangoObjectType +import graphene + + +# 相关文档 https://passwo.gitbook.io/graphql/index/drf +class UserType(DjangoObjectType): + class Meta: + model = Users + + +class Query(graphene.ObjectType): + users = graphene.List(UserType) + + # List == Field: + # List 返回结果会是遍历所有查询结果 + # Field 返回结果只存在单个 (其中可添加参数, ex. pk) + single_user = graphene.Field(UserType, pk=graphene.Int()) + + # 定义函数名的格式: resolve_字段 + # **kwargs 传递参数 + # pk: 如果在字段中定义, 则方法参数中必含 + def resolve_users(self, info, **kwargs): + return Users.objects.all() + + def resolve_single_user(self, info, pk): + return Users.objects.get(id=pk) + + +class TQuery(Query, graphene.ObjectType): + pass + + +class CreateUser(graphene.Mutation): + class Arguments: + username = graphene.String(required=True) + + info = graphene.Field(UserType) + ok = graphene.Boolean() + + def mutate(self, info, **kwargs): + # print(info.context.user, '==当前用户==') + # kwargs 是传递参数中的变量 + # user = info.context.user + user_obj = Users(**kwargs) + try: + user_obj.save() + ok = True + except Exception as e: + print(e) + ok = False + return CreateUser(ok=ok, info=user_obj) + + +class CMutation(object): + create_user = CreateUser.Field() + + +class UpdateUser(graphene.Mutation): + class Arguments: + username = graphene.String() + pk = graphene.Int(required=True) + + info = graphene.Field(UserType) + ok = graphene.Boolean() + + def mutate(self, info, **kwargs): + pk = kwargs.get('pk') + user_obj = Users.objects.get(id=pk) + if not user_obj: + return UpdateUser(ok=False) + user_obj.__dict__.update(**kwargs) + user_obj.save() + ok = True + return UpdateUser(ok=ok, info=user_obj) + + +class UMutation(object): + update_user = UpdateUser.Field() + + +class DeleteUser(graphene.Mutation): + class Arguments: + pk = graphene.Int() + + ok = graphene.Boolean() + + def mutate(self, info, **kwargs): + pk = kwargs.get('pk') + + user = Users.objects.get(id=pk) + user.delete() + return DeleteUser(ok=True) + + +class DMutation(object): + delete_user = DeleteUser.Field() + + +class Mutations(CMutation, UMutation,DMutation,graphene.ObjectType): + pass + + +schema = graphene.Schema(query=TQuery, mutation=Mutations) + diff --git a/seal/settings.py b/seal/settings.py index 7939d3a..9c8107e 100644 --- a/seal/settings.py +++ b/seal/settings.py @@ -46,8 +46,13 @@ INSTALLED_APPS = [ 'rest_framework.authtoken', 'corsheaders', 'django_filters', + 'graphene_django', ] +GRAPHENE = { + 'SCHEMA': 'seal.schema.schema' +} + MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', diff --git a/seal/urls.py b/seal/urls.py index 7d2c650..314b297 100644 --- a/seal/urls.py +++ b/seal/urls.py @@ -4,6 +4,8 @@ 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 +from graphene_django.views import GraphQLView +from seal.schema import schema API_TITLE = '海豹 API 文档' API_DESCRIPTION = '海豹 API 文档' @@ -16,5 +18,6 @@ urlpatterns = [ 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=[])) + permission_classes=[])), + path('graphql/', GraphQLView.as_view(graphiql=True, schema=schema)), ]