zoukankan      html  css  js  c++  java
  • 工单项目(后端)用于思考

    1 Django端

    • 项目目录
    └─opwf_project
        ├─celery_task
        │  └─__pycache__
        ├─db
        ├─logs
        ├─opwf
        │  ├─apps
        │  │  ├─inform
        │  │  │  ├─migrations
        │  │  │  │  └─__pycache__
        │  │  │  └─__pycache__
        │  │  ├─user
        │  │  │  ├─migrations
        │  │  │  │  └─__pycache__
        │  │  │  └─__pycache__
        │  │  ├─workerorder
        │  │  │  ├─migrations
        │  │  │  │  └─__pycache__
        │  │  │  └─__pycache__
        │  │  └─workflow
        │  │      ├─migrations
        │  │      │  └─__pycache__
        │  │      └─__pycache__
        │  ├─libs
        │  ├─opwf
        │  │  ├─apps
        │  │  └─__pycache__
        │  ├─static
        │  │  ├─admin
        │  │  │  ├─css
        │  │  │  │  └─vendor
        │  │  │  │      └─select2
        │  │  │  ├─fonts
        │  │  │  ├─img
        │  │  │  │  └─gis
        │  │  │  └─js
        │  │  │      ├─admin
        │  │  │      └─vendor
        │  │  │          ├─jquery
        │  │  │          ├─select2
        │  │  │          │  └─i18n
        │  │  │          └─xregexp
        │  │  ├─dist
        │  │  │  └─static
        │  │  │      ├─css
        │  │  │      └─js
        │  │  └─rest_framework
        │  │      ├─css
        │  │      ├─docs
        │  │      │  ├─css
        │  │      │  ├─img
        │  │      │  └─js
        │  │      ├─fonts
        │  │      ├─img
        │  │      └─js
        │  ├─templates
        │  │  └─search
        │  │      └─indexes
        │  │          └─workerorder
        │  ├─utils
        │  │  └─__pycache__
        │  ├─whoosh_index
        │  └─__pycache__
        ├─packages
        ├─scrips
        └─uwsgi_conf
    

    1.1 全局配置文件

    • opwf_project/opwf/opwf
    1.1.1 settings.py
    import datetime
    import os, sys
    
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
    
    CELERY_DIR = '/home/worker/opwf_project/celery_task'
    
    sys.path.insert(0, CELERY_DIR)
    # 加入celery的路径
    
    
    SECRET_KEY = 'uorj1ni^mnut@wo@c%)iv)%5=8dxlml4-j0!f3b%4#f*8a5)3t'
    DEBUG = True
    
    ALLOWED_HOSTS = ['*']
    # 默认是所有网址
    
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'rest_framework',
        'corsheaders',
        'haystack', # haystack要放在应用的上面
        'user.apps.UserConfig',
        'workflow.apps.WorkflowConfig',
        'workerorder.apps.WorkerorderConfig',
        'inform.apps.InformConfig',
        # 'jwt',
        # 'rest_framework_jwt',
        # 'rest_framework.authentication'
    
    
    ]
    
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'corsheaders.middleware.CorsMiddleware',
        # 'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    
    ROOT_URLCONF = 'opwf.urls'
    CORS_ORIGIN_ALLOW_ALL = True
    
    CORS_ORIGIN_WHITELIST = (
        'http://127.0.0.1:8080',
        'http://localhost:8080',
    )
    CORS_ALLOW_CREDENTIALS = True
    
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [os.path.join(BASE_DIR,'templates')],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]
    
    WSGI_APPLICATION = 'opwf.wsgi.application'
    
    
    # Database
    # https://docs.djangoproject.com/en/2.0/ref/settings/#databases
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'opwf_db',
            'USER': 'root',
            'PASSWORD': '1',
            'HOST': '127.0.0.1',
            'PORT': '3306'
        }
    }
    
    
    # Password validation
    # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators
    
    REST_FRAMEWORK = {
        # 文档报错: AttributeError: ‘AutoSchema’ object has no attribute ‘get_link’
        # 用下面的设置可以解决
        'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema',
        # 默认设置是:
        # 'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.openapi.AutoSchema',
    
        # 异常处理器
        # 'EXCEPTION_HANDLER': 'user.utils.exception_handler',
    
        # Base API policies      默认渲染器类
        'DEFAULT_RENDERER_CLASSES': [
            'rest_framework.renderers.JSONRenderer',
            'rest_framework.renderers.BrowsableAPIRenderer',
        ],
        # 默认解析器类
        'DEFAULT_PARSER_CLASSES': [
            'rest_framework.parsers.JSONParser',
            'rest_framework.parsers.FormParser',
            'rest_framework.parsers.MultiPartParser'
        ],
        # 1.认证器(全局)
        'DEFAULT_AUTHENTICATION_CLASSES': [
            'rest_framework_jwt.authentication.JSONWebTokenAuthentication',  # 在 DRF中配置JWT认证
            # 'rest_framework.authentication.SessionAuthentication',  # 使用session时的认证器
            # 'rest_framework.authentication.BasicAuthentication'  # 提交表单时的认证器
        ],
    
        # 2.权限配置(全局): 顺序靠上的严格
        'DEFAULT_PERMISSION_CLASSES': [
            # 'rest_framework.permissions.IsAdminUser',  # 管理员可以访问
            # 'rest_framework.permissions.IsAuthenticated',  # 认证用户可以访问
            # 'rest_framework.permissions.IsAuthenticatedOrReadOnly',  # 认证用户可以访问, 否则只能读取
            'rest_framework.permissions.AllowAny',  # 所有用户都可以访问
        ],
        # 3.限流(防爬虫)
        'DEFAULT_THROTTLE_CLASSES': [
            'rest_framework.throttling.AnonRateThrottle',
            'rest_framework.throttling.UserRateThrottle',
        ],
        # 3.1限流策略
        # 'DEFAULT_THROTTLE_RATES': {
        #     'user': '100/hour',  # 认证用户每小时100次
        #     'anon': '300/day',  # 未认证用户每天能访问3次
        # },
    
        'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'rest_framework.negotiation.DefaultContentNegotiation',
        'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata',
        'DEFAULT_VERSIONING_CLASS': None,
    
        # 4.分页(全局):全局分页器, 例如 省市区的数据自定义分页器, 不需要分页
        # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
        # # 每页返回数量
        # 'PAGE_SIZE': 3,
        # 5.过滤器后端
        'DEFAULT_FILTER_BACKENDS': [
            'django_filters.rest_framework.DjangoFilterBackend',
            # 'django_filters.rest_framework.backends.DjangoFilterBackend', 包路径有变化
        ],
    
        # 5.1过滤排序(全局):Filtering 过滤排序
        'SEARCH_PARAM': 'search',
        'ORDERING_PARAM': 'ordering',
    
        'NUM_PROXIES': None,
    
        # 6.版本控制:Versioning  接口版本控制
        'DEFAULT_VERSION': None,
        'ALLOWED_VERSIONS': None,
        'VERSION_PARAM': 'version',
    
        # Authentication  认证
        # 未认证用户使用的用户类型
        'UNAUTHENTICATED_USER': 'django.contrib.auth.models.AnonymousUser',
        # 未认证用户使用的Token值
        'UNAUTHENTICATED_TOKEN': None,
    
        # View configuration
        'VIEW_NAME_FUNCTION': 'rest_framework.views.get_view_name',
        'VIEW_DESCRIPTION_FUNCTION': 'rest_framework.views.get_view_description',
    
        'NON_FIELD_ERRORS_KEY': 'non_field_errors',
    
        # Testing
        'TEST_REQUEST_RENDERER_CLASSES': [
            'rest_framework.renderers.MultiPartRenderer',
            'rest_framework.renderers.JSONRenderer'
        ],
        'TEST_REQUEST_DEFAULT_FORMAT': 'multipart',
    
        # Hyperlink settings
        'URL_FORMAT_OVERRIDE': 'format',
        'FORMAT_SUFFIX_KWARG': 'format',
        'URL_FIELD_NAME': 'url',
    
        # Encoding
        'UNICODE_JSON': True,
        'COMPACT_JSON': True,
        'STRICT_JSON': True,
        'COERCE_DECIMAL_TO_STRING': True,
        'UPLOADED_FILES_USE_URL': True,
    
        # Browseable API
        'HTML_SELECT_CUTOFF': 1000,
        'HTML_SELECT_CUTOFF_TEXT': "More than {count} items...",
    
        # Schemas
        'SCHEMA_COERCE_PATH_PK': True,
        'SCHEMA_COERCE_METHOD_NAMES': {
            'retrieve': 'read',
            'destroy': 'delete'
        },
    
        # 'Access-Control-Allow-Origin':'http://localhost:8080',
        # 'Access-Control-Allow-Credentials': True
    
    }
    
    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ]
    
    
    # Internationalization
    # https://docs.djangoproject.com/en/2.0/topics/i18n/
    
    LANGUAGE_CODE = 'zh-hans'
    
    TIME_ZONE = 'Asia/Shanghai'
    
    USE_I18N = True
    
    USE_L10N = True
    
    USE_TZ = False
    
    
    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/2.0/howto/static-files/
    
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'static/dist')
    # STATICFILES_DIRS = [
    #     os.path.join(BASE_DIR, 'static/dist')
    # ]
    AUTH_USER_MODEL = 'user.User'
    
    # jwt载荷中的有效期设置
    JWT_AUTH = {
        # 1.token前缀:headers中 Authorization 值的前缀
        'JWT_AUTH_HEADER_PREFIX': 'JWT',
        # 2.token有效期:一天有效
        'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
        # 3.刷新token:允许使用旧的token换新token
        'JWT_ALLOW_REFRESH': True,
        # 4.token有效期:token在24小时内过期, 可续期token
        'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(hours=24),
        # 5.自定义JWT载荷信息:自定义返回格式,需要手工创建
        'JWT_RESPONSE_PAYLOAD_HANDLER': 'user.utils.jwt_response_payload_handler',
    }
    
    # 邮箱配置
    # 配置邮件发送
    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    EMAIL_HOST = 'smtp.qq.com'  # 如果为163邮箱,设置为smtp.163.com
    EMAIL_PORT = 25  # 或者 465/587是设置了 SSL 加密方式
    # 发送邮件的邮箱
    EMAIL_HOST_USER = '742327252@qq.com'
    # 在邮箱中设置的客户端授权密码
    EMAIL_HOST_PASSWORD = 'czwiakrihfmpbfej'  # 第三方登陆使用的授权密码
    EMAIL_USE_TLS = True  # 这里必须是 True,否则发送不成功
    # 收件人看到的发件人, 必须是一直且有效的
    EMAIL_FROM = '姬如飞羽<742327252@qq.com>'
    DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
    
    # 缓存配置
    CACHES = {
        # django存缓默认位置,redis 0号库
        # default: 连接名称
        "default": {
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": "redis://127.0.0.1:6379/0",
            "OPTIONS": {
                "CLIENT_CLASS": "django_redis.client.DefaultClient",
            }
        },
        # django session存 reidis 1 号库(现在基本不需要使用)
        "session": {
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": "redis://127.0.0.1:6379/1",
            "OPTIONS": {
                "CLIENT_CLASS": "django_redis.client.DefaultClient",
            }
        },
        # 邮件,存redis 2号库
        "email": {
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": "redis://127.0.0.1:6379/2",
            "OPTIONS": {
                "CLIENT_CLASS": "django_redis.client.DefaultClient",
            }
        }
    }
    # 配置session使用redis存储
    SESSION_ENGINE = "django.contrib.sessions.backends.cache"
    # 配置session存储的位置: 使用cache中的 session配置
    SESSION_CACHE_ALIAS = "session"
    
    # 全文检索配置
    HAYSTACK_SEARCH_RESULTS_PER_PAGE = 4   # 搜索出多条数据时需要分页
    # HAYSTACK_CONNECTIONS = {
    #     'default': {
    #         # 'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
    #         'ENGINE': 'workerorder.whoosh_cn_backend.MyWhooshEngine',
    #         'PATH': os.path.join(BASE_DIR, 'whoosh_index')     # 指定倒排索引 存放位置
    #     }
    # }
    
    # ES引擎
    HAYSTACK_CONNECTIONS = {
          'default': {
                  'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
                  'URL': 'http://192.168.56.100:9200/',     # Elasticsearch服务器ip地址,端口号固 定为9200
                  'INDEX_NAME': 'opwf_db',                    # Elasticsearch建立的反向索引库的名称
          },
    }
    #
    # 添加此项,当数据库改变时,会自动更新索引,非常方便
    HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
    
    1.1.2 __init__.py
    import pymysql
    pymysql.install_as_MySQLdb()
    
    1.1.3 urls.py
    • 此处为主路由配置
    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('user/', include('user.urls')),
        path('workflow/', include('workflow.urls')),
        path('workerorder/', include('workerorder.urls')),
        path('inform/', include('inform.urls'))
    ]
    
    1.1.4 wsgi.py
    import os
    from django.core.wsgi import get_wsgi_application
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "opwf.settings")
    application = get_wsgi_application()
    

    1.2 user模块

    • 主要为用户的权限管理,角色管理以及信息管理
    1.2.1 models.py
    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    
    class User(AbstractUser):
        '''
        username:用户名
        password:密码
        mobile:手机号
        email:邮箱
        '''
        username = models.CharField(max_length=30, unique=True)
        # 写上 unique=True 就可以指定唯一,验证字段的时候自动验证
        password = models.CharField(max_length=256)
        mobile = models.CharField(max_length=11)
        email = models.CharField(max_length=30)
        token = models.CharField(max_length=256, default='')
        weixin = models.CharField(max_length=30, null=True)
        date_joined = models.DateField(auto_now_add=True)
    
        class Meta:
            db_table = 'user_user'
            verbose_name = '用户表'
            verbose_name_plural = verbose_name
    
    
    class Role(models.Model):
        '''
        name:角色名称
        description:描述
        '''
        zh_name = models.CharField(max_length=30)
        en_name = models.CharField(max_length=30)
        description = models.TextField()
    
        class Meta:
            db_table = 'user_role'
            verbose_name = '角色表'
            verbose_name_plural = verbose_name
    
    
    
    class UserRole(models.Model):
        user = models.ForeignKey(User, on_delete=models.CASCADE)
        role = models.ForeignKey(Role, on_delete=models.CASCADE)
    
        class Meta:
            db_table = 'user_userrole'
            verbose_name = '用户角色表'
            verbose_name_plural = verbose_name
    
    1.2.2 serializers.py
    # -*- coding: utf-8 -*-
    from rest_framework import serializers
    from rest_framework_jwt.serializers import jwt_payload_handler
    from rest_framework_jwt.settings import api_settings
    from user.models import User, UserRole, Role
    
    class UserModelSerializer(serializers.ModelSerializer):
        is_superuser = serializers.CharField(default=0)
        roles = serializers.SerializerMethodField(required=False)
        
        class Meta:
            model = User
            fields = '__all__'
            
        def create(self, data):
            username = data.get('username', '')
            password = data.get('password', '')
            mobile = data.get('mobile', '')
            email = data.get('email', '')
            weixin = data.get('weixin', '')
            user = User(username=username, email=email, mobile=mobile, weixin=weixin)
            user.set_password(password)
            user.save()
            return user
    
        def get_roles(self, row):
            roles_json = UserRole.objects.filter(user=row).values('role__id', "role__zh_name")
            print('111', roles_json)
            print('222', list(roles_json))
            print(type(list(roles_json)))
            return list(roles_json)
    
        def get_serializer_class(self):
            return UserModelSerializer
    
    class UserSerializer(serializers.Serializer):
        id = serializers.IntegerField(read_only=True)
        username = serializers.CharField()
        password = serializers.CharField()
        mobile = serializers.CharField()
        email = serializers.EmailField()
        weixin = serializers.CharField()
        token = serializers.CharField(read_only=True)
    
        def create(self, data):
            username = data.get('username', '')
            password = data.get('password', '')
            mobile = data.get('mobile', '')
            email = data.get('email', '')
            weixin = data.get('weixin', '')
            user = User(username=username, email=email, mobile=mobile, weixin=weixin)
            user.set_password(password)
            user.save()
            # 补充生成记录登录状态的token
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            user.token = token
            return user
    
        
    class UserRoleSerializer(serializers.ModelSerializer):
        class Meta:
            model = UserRole
            fields = '__all__'
    
            
    class RoleSerializer(serializers.ModelSerializer):
        class Meta:
            model = Role
            fields = "__all__"
    
    1.2.3 urls.py
    # -*- coding: utf-8 -*-
    
    from django.urls import path
    from rest_framework.routers import DefaultRouter
    from rest_framework_jwt.views import obtain_jwt_token
    from user import views
    
    router = DefaultRouter()
    router.register(r'user', views.UserViewSet)
    router.register(r'user_get', views.UserGetViewSet)
    router.register(r'role', views.RoleViewSet)
    router.register(r'role_get', views.RoleGetViewSet)
    
    urlpatterns = [
        path('login/', obtain_jwt_token),
        path('register/', views.RegisterView.as_view()),
        path('is_superuser/', views.IsSuperUser.as_view()),
    ]
    
    urlpatterns += router.urls
    
    1.2.4 views.py
    import datetime
    import random
    from django.contrib.auth.hashers import make_password
    from django.shortcuts import render
    from rest_framework import viewsets
    from rest_framework.pagination import PageNumberPagination
    from rest_framework.response import Response
    from rest_framework.views import APIView
    from utils.MyAuthorization import MyPermission, decodeToken
    from user.models import User, Role, UserRole
    from user.serializers import UserSerializer, UserModelSerializer, RoleSerializer, UserRoleSerializer
    
    
    # 分页(局部):自定义分页器 局部
    class PageNum(PageNumberPagination):
        page_size = 4                           # 每页显示多少条
        page_size_query_param = 'page_size'     # 查询字符串中代表每页返回数据数量的参数名, 默认值: None
        page_query_param = 'page'               # 查询字符串中代表页码的参数名, 有默认值: page
        max_page_size = None                    # 最大页码数限制
    
    
    class UserViewSet(viewsets.ModelViewSet):
        permission_classes = (MyPermission,)
        queryset = User.objects.all()
        serializer_class = UserModelSerializer
        filter_fields = {"username", 'mobile', 'weixin', 'email'}
        pagination_class = PageNum  # 注意不是列表(只能有一个分页模式)
        # permission_classes = (MyPermission,)
    
        def perform_update(self, serializer):
            user_obj = serializer.save()
            # 原有的serializer反序列化添加
            roles = self.request.data.get('roles')
            user_obj.userrole_set.all().delete()
            for role_id in roles:
                userrole = UserRole.objects.create(user=user_obj, role_id=role_id)
        
        def get_serializer_class(self):
            print('action------->', self.action)
            return UserModelSerializer
    
        
    class UserGetViewSet(viewsets.ModelViewSet):
        queryset = User.objects.all()
        serializer_class = UserSerializer
        permission_classes = (MyPermission,)
    
        
    class RoleViewSet(viewsets.ModelViewSet):
        queryset = Role.objects.all()
        serializer_class = RoleSerializer
        filter_fields = {"zh_name"}
        pagination_class = PageNum  # 注意不是列表(只能有一个分页模式)
        permission_classes = (MyPermission,)
    
        
    class RoleGetViewSet(viewsets.ModelViewSet):
        # 用于角色查看接口(没有分页的那种)
        queryset = Role.objects.all()
        serializer_class = RoleSerializer
        permission_classes = (MyPermission,)
    
    
    class RegisterView(APIView):
        permission_classes = (MyPermission,)
        
        def post(self, request):
            username = request.data.get('username')
            password = request.data.get('password')
            password_new = request.data.get('password_new')
            role = request.data.get('roles')
            print(role)
            if not all([username, password, password_new]):
                return Response(
                    {'msg': '信息不全', 'code': 400}
                )
            if password != password_new:
                return Response(
                    {'code': 400, 'msg':'两次登录密码不一致'}
                )
            user_serializer = UserSerializer(data=request.data)
            if user_serializer.is_valid():
                user_serializer.save()
                user_obj = User.objects.filter(username=username).first()
                print(user_obj)
                new_list = []
                for i in role:
                    role_obj = Role.objects.filter(id=i).first()
                    # UserRole.objects.create(user=user_obj, role=role_obj)
                    # UserRole.objects.create(user_id=user_obj.id, role_id=role_obj.id)
                    new_list.append((UserRole(user=user_obj, role=role_obj)))
                UserRole.objects.bulk_create(new_list)
                return Response(
                    {'msg': '注册成功', 'code': 200, 'data':user_serializer.data}
                )
    
            return Response(
                {'msg': '注册失败', 'error': user_serializer.errors }
            )
    
        
    class IsSuperUser(APIView):
        
        def get(self, request):
            user_list = decodeToken(request)
            user_id = user_list.get('user_id')
            obj = User.objects.filter(pk=user_id).first()
            if obj.is_superuser == 1:
                return Response({'type': 1, 'code': 200})
            return Response({'type': 2, 'code': 200})
    
    1.2.5 utils.py
    # -*- coding: utf-8 -*-
    # from rest_framework_jwt.views import obtain_jwt_token
    # 为urls.py中的导包
    def jwt_response_payload_handler(token, user=None, request=None, role=None):
        """
            自定义jwt认证成功返回数据
            :token 返回的jwt
            :user 当前登录的用户信息[对象]
            :request 当前本次客户端提交过来的数据
            :role 角色
        """
        if user.first_name:
            name = user.first_name
        else:
            name = user.username
            return {
                'authenticated': 'true',
                 'id': user.id,
                 "role": role,
                 'name': name,
                 'username': user.username,
                 'email': user.email,
                 'token': token,
            }
    
    1.2.6 admin.py
    from django.contrib import admin
    from .models import *
    
    admin.site.register(User)
    admin.site.register(Role)
    admin.site.register(UserRole)
    

    1.3 workerorder模块

    • 主要针对工单模板的管理以及动态生成工单模板效果的实现
    1.3.1 models.py
    from django.db import models
    from utils.MyBaseModel import BaseModel
    from user.models import User
    from workflow.models import FlowConf
    
    
    class WorkOrderModel(BaseModel):
        '''
        flowconf:工单名称(一对多,FlowConf)
        create_user:工单创建用户(一对多,User表)
        create_ts:创建时间
        order_status:工单状态(审批中/被驳回/完成)
        description:描述(text,存储用户工单描述)
        '''
        status_choices = (
            ('1', '审批中'),
            ('2', '被驳回'),
            ('3', '完成')
        )
        flowconf = models.ForeignKey(FlowConf, on_delete=models.CASCADE, null=True)
        create_user = models.ForeignKey(User, on_delete=models.CASCADE)
        order_status = models.CharField('工单状态', help_text='审批中/被驳回/完成', choices=status_choices, default='1', max_length=30)
        parameter = models.TextField(default='{}')
        # description = models.TextField('描述', help_text='存储用户工单描述')
    
        class Meta:
            db_table = 'workerorder_workerorder'
            verbose_name = '实例化工单'
            verbose_name_plural = verbose_name
    
    
    class SubOrderModel(BaseModel):
        '''
        mainorder:一对多(WorkOrder)实例化工单相连
        approve_user:一对多(内置User表)审批人
        approbe_user_role:审批角色
        approve_userrole_id:审批角色id
        sequence_number:审批序号
        approve_ts:审批时间
        action_status:审批状态(待审批/通过/拒绝/退回)
        suborder_status:子任务状态(待处理/已经处理/待上一节点处理)
        approve_text:审批意见
        approve_type_id: 审批类型
        '''
        action_status_choices = (
            ('1', '待审批'),
            ('2', '通过'),
            ('3', '拒绝'),
            ('4', '退回')
        )
        suborder_status_choices = (
            ('1', '待处理'),
            ('2', '已经处理'),
            ('3', '待上一节点处理')
        )
        mainorder = models.ForeignKey(WorkOrderModel, on_delete=models.CASCADE)
        approve_user = models.ForeignKey(User, null=True, blank=True, on_delete=models.SET_NULL, default='')
        approbe_user_role = models.CharField('审批角色', max_length=30, null=True)
        approve_userrole_id = models.IntegerField('审批角色id', null=True)
        sequence_number = models.IntegerField('审批序号')
        approve_ts = models.DateTimeField('审批时间', auto_now_add=True)
        action_status = models.CharField('审批状态', help_text='待审批/通过/拒绝/退回', choices=action_status_choices, default='1', max_length=30)
        suborder_status = models.CharField('子任务状态', help_text='待处理/已经处理/待上一节点处理', choices=suborder_status_choices, default='1', max_length=30)
        approve_text = models.TextField('审批意见')
        type_choice = (
            ('1', '角色审批'),
            ('2', '指定人员审批')
        )
        approve_type_id = models.CharField(max_length=30, choices=type_choice)
    
        class Meta:
            db_table = 'workerorder_suborder'
            verbose_name = '实例化子工单'
            verbose_name_plural = verbose_name
    
    1.3.2 serializers.py
    # -*- coding: utf-8 -*-
    
    from rest_framework import serializers
    from workerorder.models import WorkOrderModel, SubOrderModel
    
    class SubOrderSerializer(serializers.ModelSerializer):
        approve_user_name = serializers.SerializerMethodField(required=False)
        action_status_name = serializers.SerializerMethodField(required=False)
        suborder_status_name = serializers.SerializerMethodField(required=False)
        flowconf_name = serializers.SerializerMethodField(required=False)
        flowconf = serializers.SerializerMethodField(required=False)
        mainorder = serializers.SerializerMethodField(required=False)
        
        class Meta:
            model = SubOrderModel
            fields = "__all__"
    
        # row中提供了大量的方法和字段,可以用dir(row)的方法来打印出内置的方法和属性
        def get_action_status_name(self, row):
            return dict(row.action_status_choices)[row.action_status]
    
        def get_suborder_status_name(self, row):
            return dict(row.suborder_status_choices)[row.suborder_status]
    
        def get_approve_user_name(self, row):
            if row.approve_user:
                return row.approve_user.username
            else:
                return ''
        def get_flowconf_name(self, row):
            return row.mainorder.flowconf.name
    
        def get_flowconf(self, row):
            return row.mainorder.flowconf.id
    
        def get_mainorder(self, row):
            return row.mainorder_id
    
    class SubOrderDeepSerializer(serializers.ModelSerializer):
    
        class Meta:
            model = SubOrderModel
            fields = '__all__'
    
    
    class WorkOrderSerializer(serializers.ModelSerializer):
        subordermodel_set = SubOrderDeepSerializer(many=True)
        order_status_name = serializers.SerializerMethodField(required=False)
        create_user_name = serializers.SerializerMethodField(required=False)
        flowconf_name = serializers.CharField(required=False, source='flowconf.name')
    
        class Meta:
            model = WorkOrderModel
            fields = '__all__'
    
        def get_order_status_name(self, row):
            status_choices = dict(row.status_choices)
            return status_choices[row.order_status]
    
        def get_create_user_name(self, row):
            # print(type(row.create_user.username))
            # <str>
            return row.create_user.username
    
    
    class WorkOrderTextSerializer(serializers.ModelSerializer):
        class Meta:
            model = WorkOrderModel
            fields = '__all__'
    
    1.3.3 urls.py
    # -*- coding: utf-8 -*-
    from django.urls import path
    from workerorder.views import *
    
    urlpatterns = [
        path('workorder/', WorkOrderView.as_view()),
        path('suborder_get/', SubOrderView.as_view()),
        path('suborder/', SubOrderGetView.as_view()),
        path('workorder_search/', SearchWorkOrderView.as_view()),
        path('suborder_search/', SearchSubOrderVIew.as_view()),
    ]
    
    1.3.4 views.py
    • 本模块中的views采用了初级封装,代码还是不够完美,但是第一次做项目,还是值得纪念!
    import json
    from django.conf import settings
    from django.core.paginator import InvalidPage, Paginator
    from django.http import JsonResponse, HttpResponse
    from haystack.forms import ModelSearchForm
    from rest_framework.response import Response
    from rest_framework.views import APIView
    from user.models import User
    from utils.MyAuthorization import decodeToken, getAuthorization
    from utils.MyPaginator import basePaginator
    from workerorder.models import WorkOrderModel, SubOrderModel
    from workerorder.serializers import WorkOrderSerializer, SubOrderSerializer
    from workerorder.utils import getSuborder, getWorkerorder, addWorkerOrder, chooseSuborder, serFields, esSearchWorkOrder, esSearchSubOrder
    
    
    class WorkOrderView(APIView):
        serializer_class = WorkOrderSerializer
        page_size = 4
    
        def get(self, request):
            id = request.query_params.get('id')
            if id is None:
                if request.user.is_superuser:
                    queryset = WorkOrderModel.objects.all()
                    ret = basePaginator(queryset, request, self.page_size, self.serializer_class)
                else:
                    user_info = decodeToken(request)
                    queryset = getWorkerorder(user_info)
                    ret = basePaginator(queryset, request, self.page_size, self.serializer_class)
            else:
                ser = WorkOrderModel.objects.filter(id=id)
                ret = WorkOrderSerializer(ser, many=True).data
            return Response(ret)
    
        def post(self, request):
            res = addWorkerOrder(request)
            return Response(res)
    
    
    class SubOrderView(APIView):
        serializer_class = SubOrderSerializer
        page_size = 4
    
        def get(self, request):
            mainorder = request.query_params.get('mainorder')
            if mainorder is None:
                if request.user.is_superuser:
                    queryset = SubOrderModel.objects.all()
                    ret = basePaginator(queryset, request, self.page_size, self.serializer_class)
                else:
                    user_info = decodeToken(request)
                    queryset = getSuborder(user_info)
                    ret = basePaginator(queryset, request, self.page_size, self.serializer_class)
            else:
                ser = SubOrderModel.objects.filter(mainorder_id=mainorder)
                ret = SubOrderSerializer(ser, many=True).data
            return Response(ret)
    
        def post(self, request):
            res = chooseSuborder(request)
            return Response(res)
    
    
    class SubOrderGetView(APIView):
        serializer_class = SubOrderSerializer
        page_size = 4
    
        def get(self, request):
            ret = getAuthorization(request)
            val = serFields(ret)
            return Response(val)
    
    
    class SearchWorkOrderView(APIView):
        def get(self, request):
            data = esSearchWorkOrder(request)
            return Response(data)
    
    
    class SearchSubOrderVIew(APIView):
        def get(self, request):
            data = esSearchSubOrder(request)
            return Response(data)
    
    1.3.5 utils.py
    # -*- coding: utf-8 -*-
    import os, sys
    from django.core.paginator import Paginator, InvalidPage
    from haystack.forms import ModelSearchForm
    
    
    from utils.MyAuthorization import decodeToken
    from user.models import Role, User, UserRole
    from workerorder.models import WorkOrderModel, SubOrderModel
    from workflow.models import FlowConf, NewFlowUserRoleActionConf
    
    def getSuborder(user_info):
        user_id = user_info.get('user_id')
        role_list = user_info.get('role_id')
        queryset = SubOrderModel.objects.all()
        results = []
        for val in queryset:
            # worker_id = val.mainorder_id
            # create_user_id = WorkOrderModel.objects.filter(pk=worker_id).first().create_user_id
            # print(1111, create_user_id)
            # if create_user_id == user_id:
            #     results.append(val)
            # else:
            if val.approve_type_id == '2':
                if val.approve_user_id == user_id:
                    print(val.approve_user_id)
                    results.append(val)
            elif val.approve_type_id == '1':
                if val.approve_userrole_id in role_list:
                    print(val.approve_userrole_id)
                    results.append(val)
        return results
    
    def getWorkerorder(user_info):
        queryset = []
        suborder_list = []
        # suborder_queryset = getSuborder(user_info)
        # for i in suborder_queryset:
        #     if i.mainorder_id not in suborder_list:
        #         suborder_list.append(i.mainorder_id)
        workerorder_queryset = WorkOrderModel.objects.all()
        user_id = user_info.get('user_id')
        for i in workerorder_queryset:
            if i.create_user_id == user_id:
                queryset.append(i)
            else:
                if i.id in suborder_list:
                    queryset.append(i)
        return queryset
    
    def addWorkerOrder(request):
        user_info = decodeToken(request)
        user_id = user_info.get('user_id')
        name = request.data.get('name')
        form = request.data.get('form')
        flowconf = FlowConf.objects.filter(name=name).first().pk
        dic = {
            'flowconf_id': flowconf,
            'create_user_id': user_id,
            'order_status': '1',
            'parameter': form
        }
        work_obj = WorkOrderModel.objects.create(**dic)
        approveconf_obj = list(NewFlowUserRoleActionConf.objects.filter(flowconf_id=work_obj.flowconf_id).values())
        time = 0
        for item in approveconf_obj:
            if item['approvetype'] == '1':
                if time == 0:
                    child_data = {
                        'mainorder_id': work_obj.id,
                        'approbe_user_role': Role.objects.filter(pk=item['approve_type_id']).first().zh_name,
                        'approve_user_id':None,
                        # 不加就报错
                        'approve_userrole_id': item['approve_type_id'],
                        'sequence_number': item['sequence'],
                        'approve_type_id': '1'
                    }
                    print('child_data', child_data)
                    SubOrderModel.objects.create(**child_data)
                    time += 1
                else:
                    child_data = {
                        'mainorder_id': work_obj.id,
                        'approbe_user_role': Role.objects.filter(pk=item['approve_type_id']).first().zh_name,
                        'approve_user_id': None,
                        # 不加就报错
                        'approve_userrole_id': item['approve_type_id'],
                        'sequence_number': item['sequence'],
                        'approve_type_id': '1',
                        'suborder_status': '3'
                    }
                    SubOrderModel.objects.create(**child_data)
                    time += 1
            if item['approvetype'] == '2':
                if time == 0:
                    child_data = {
                        'mainorder_id': work_obj.id,
                        'approve_user_id': User.objects.filter(pk=item['approve_type_id']).first().id,
                        'approbe_user_role': '',
                        'approve_userrole_id': None,
                        'sequence_number': item['sequence'],
                        'approve_type_id': '2'
                    }
                    print('obj', child_data)
                    SubOrderModel.objects.create(**child_data)
                    time += 1
                else:
                    child_data = {
                        'mainorder_id': work_obj.id,
                        'approve_user_id': User.objects.filter(pk=item['approve_type_id']).first().id,
                        'approbe_user_role': '',
                        'approve_userrole_id': None,
                        'sequence_number': item['sequence'],
                        'approve_type_id': '2',
                        'suborder_status': '3'
                    }
                    print('obj', child_data)
                    SubOrderModel.objects.create(**child_data)
        user_list = []
        user_id = SubOrderModel.objects.filter(mainorder_id=work_obj.id, sequence_number=1).first().approve_user_id
        if user_id:
            user_list.append(user_id)
        else:
            role_id = SubOrderModel.objects.filter(mainorder_id=work_obj.id, sequence_number=1).first().approve_userrole_id
            user_get = UserRole.objects.filter(role_id=role_id).values('user_id')
            for i in user_get:
                user_list.append(i.get('user_id'))
        sys.path.insert(0, r'/home/worker/opwf_project')
        from celery_task import tasks
        tasks.send_email.delay(user_list)
        res = {'msg': '添加成功', 'code': 200, 'id': work_obj.pk, 'flowconf': work_obj.flowconf_id}
        return res
    
    def chooseSuborder(request):
        # 子工单id
        suborder_id = request.data.get('suborder_id')
        # 子工单审批状态
        action_status = request.data.get('action_status')
        # 意见
        decision = request.data.get('decision')
        # 所属实例工单id
        mainorder = SubOrderModel.objects.filter(pk=suborder_id).first().mainorder_id
        # 子工单序号
        sequence_number = SubOrderModel.objects.filter(pk=suborder_id).first().sequence_number
        SubOrderModel.objects.filter(pk=suborder_id).update(action_status=action_status)
        SubOrderModel.objects.filter(pk=suborder_id).update(suborder_status=2)
        SubOrderModel.objects.filter(pk=suborder_id).update(approve_text=decision)
        squenue_list = []
        squenue_obj = SubOrderModel.objects.filter(mainorder_id=mainorder).values('sequence_number')
        for i in squenue_obj:
            squenue_list.append(i.get('sequence_number'))
        print('list', squenue_list)
        index = squenue_list.index(sequence_number) + 1
        print('index', index)
        if action_status == '4':
            # 4 子工单退回--------主工单 驳回
            WorkOrderModel.objects.filter(pk=mainorder).update(order_status=2)  # 主工单一旦完成,子工单不变
            text = '驳回'
            sys.path.insert(0, r'/home/worker/opwf_project')
            from celery_task import tasks_back
            tasks_back.back_email(WorkOrderModel.objects.get(pk=mainorder).create_user.username, WorkOrderModel.objects.get(pk=mainorder).create_user.email, text)
            # if squenue_list[index-1] != squenue_list[-1]:
            #     for m in squenue_list[index:]:
            #         SubOrderModel.objects.filter(sequence_number=m).update(suborder_status=2)
            #         SubOrderModel.objects.filter(sequence_number=m).update(action_status=action_status)
        if action_status == '3':
            # 3 子工单拒绝-------主工单 完成
            WorkOrderModel.objects.filter(pk=mainorder).update(order_status=3)  # 主工单一旦驳回,子工单不变
            text = '拒绝'
            sys.path.insert(0, r'/home/worker/opwf_project')
            from celery_task import tasks_back
            tasks_back.back_email(WorkOrderModel.objects.get(pk=mainorder).create_user.username,
                       WorkOrderModel.objects.get(pk=mainorder).create_user.email, text)
            # if squenue_list[index-1] != squenue_list[-1]:
            # for m in squenue_list[index:]:
            #     SubOrderModel.objects.filter(sequence_number=m).update(suborder_status=2)
            #     SubOrderModel.objects.filter(sequence_number=m).update(action_status=action_status)
        if action_status == '2':
            # suborder_status 1 待处理 2 已经处理 3 待上一节点处理
            if squenue_list[index - 1] == squenue_list[-1]:
                WorkOrderModel.objects.filter(pk=mainorder).update(order_status=3)
                text = '通过'
                sys.path.insert(0, r'/home/worker/opwf_project')
                from celery_task import tasks_back
                tasks_back.back_email(WorkOrderModel.objects.get(pk=mainorder).create_user.username,
                           WorkOrderModel.objects.get(pk=mainorder).create_user.email, text)
            else:
                # suborder_status 1 待处理 2 已经处理 3 待上一节点处理
                SubOrderModel.objects.filter(mainorder_id=mainorder, sequence_number=index + 1).update(suborder_status=1)
                user_list = []
                user_id = SubOrderModel.objects.filter(sequence_number=index + 1, mainorder_id=mainorder).first().approve_user_id
                if user_id:
                    user_list.append(user_id)
                else:
                    role_id = SubOrderModel.objects.filter(sequence_number=index + 1, mainorder_id=mainorder).first().approve_userrole_id
                    user_get = UserRole.objects.filter(role_id=role_id).values('user_id')
                    for i in user_get:
                        user_list.append(i.get('user_id'))
                # EmailInform(user_list)
                # sys.path.insert(0, os.path.join('/home/worker/opwf_project', 'celery_task'))
                sys.path.insert(0, r'/home/worker/opwf_project')
                from celery_task import tasks
                tasks.send_email.delay(user_list)
        res = {'msg': 'ok', 'code': 200}
        return res
    
    def serFields(ret):
        for i in ret:
            if i['suborder_status'] == '1':
                i['suborder_status_name'] = '待处理'
    
                if i['action_status'] == '1':
                    i['action_status_name'] = '待审批'
                elif i['action_status'] == '2':
                    i['action_status_name'] = '通过'
                elif i['action_status'] == '3':
                    i['action_status_name'] = '拒绝'
                elif i['action_status'] == '4':
                    i['action_status_name'] = '退回'
            elif i['suborder_status'] == '2':
                i['suborder_status_name'] = '已经处理'
    
                if i['action_status'] == '1':
                    i['action_status_name'] = '待审批'
                elif i['action_status'] == '2':
                    i['action_status_name'] = '通过'
                elif i['action_status'] == '3':
                    i['action_status_name'] = '拒绝'
                elif i['action_status'] == '4':
                    i['action_status_name'] = '退回'
            elif i['suborder_status'] == '3':
                i['suborder_status_name'] = '待上一节点处理'
    
                if i['action_status'] == '1':
                    i['action_status_name'] = '待审批'
                elif i['action_status'] == '2':
                    i['action_status_name'] = '通过'
                elif i['action_status'] == '3':
                    i['action_status_name'] = '拒绝'
                elif i['action_status'] == '4':
                    i['action_status_name'] = '退回'
    
        return ret
    
    # def elastaticSearch(request):
    #     RESULTS_PER_PAGE = getattr(settings, 'HAYSTACK_SEARCH_RESULTS_PER_PAGE', 4)
    #     # 1.获取前端传过来的关键字(查询数据)
    #     query = request.GET.get('q', None)
    #     page = int(request.GET.get('page', 1))  # 第几页
    #     page_size = int(request.GET.get('page_size', RESULTS_PER_PAGE))  # 每页多少条
    #     # 2.获取查询条件,进行查询
    #     if query:
    #         form = ModelSearchForm(request.GET, load_all=True)  # 将查询条件传递给查询对象
    #         if form.is_valid():
    #             results = form.search()  # 查询出来的最终数据
    #         else:
    #             results = []
    #     else:
    #         return {"msg": 'No file found!', "data": []}
    #     # 3.对结果集进行分页
    #     paginator = Paginator(results, page_size)
    #     try:
    #         page = paginator.page(page)  # 从分好的页中拿第几页
    #     except InvalidPage:  # 如果分页出错
    #         return {"msg": 'No file found!', "data": []}
    #
    #         # 4.把查询的分页结果集对象转换成json格式
    
    def esSearchWorkOrder(request):
        user_info = decodeToken(request)
        user_id = user_info.get('user_id')
        form = ModelSearchForm(request.GET, load_all=True)  # 将查询条件传递给查询对象
        if form.is_valid():
            results = form.search()  # 查询出来的最终数据
        else:
            results = []
        jsondata = []
        for result in results:  # 课程查询结果
            if User.objects.filter(pk=user_id).first().is_superuser == False and result.create_user_id == user_id:
                jsondata.append({
                    'id': result.object.id,
                    'flowconf': result.object.flowconf_id,
                    'flowconf_name': result.object.flowconf.name,
                    'create_user_id': result.object.create_user_id,
                    'create_user_name': result.object.create_user.username,
                    'order_status_name': result.object.get_order_status_display(),
                    'create_time': str(result.object.create_time)
                })
            elif User.objects.filter(pk=user_id).first().is_superuser:
                jsondata.append({
                    'id': result.object.id,
                    'flowconf': result.object.flowconf_id,
                    'flowconf_name': result.object.flowconf.name,
                    'create_user_id': result.object.create_user_id,
                    'create_user_name': result.object.create_user.username,
                    'order_status_name': result.object.get_order_status_display(),
                    'create_time': str(result.object.create_time)
                })
        present_page = int(request.GET.get('page', 1))
        paginator_new = Paginator(jsondata, 4)
        one_page = paginator_new.page(present_page)
        count = paginator_new.count
        data = {
            'count': count,
            'results': list(one_page)
        }
        return data
    
    
    def esSearchSubOrder(request):
        user_info = decodeToken(request)
        user_id = user_info.get('user_id')
        role_id = user_info.get('role_id')
        form = ModelSearchForm(request.GET, load_all=True)  # 将查询条件传递给查询对象
        if form.is_valid():
            results = form.search()  # 查询出来的最终数据
            print(1234567,results)
        else:
            results = []
        jsondata = []
        for result in results:  # 课程查询结果
            if User.objects.filter(pk=user_id).first().is_superuser == False:
                if result.object.approve_user_id == user_id:
                    jsondata.append({
                        'id': result.object.id,
                        'mainorder': result.object.mainorder_id,
                        'flowconf_name': result.object.mainorder.flowconf.name,
                        'flowconf': result.object.mainorder.flowconf.id,
                        'approve_user_id': result.object.approve_user_id,
                        'approve_user_name': result.object.approve_user.username,
                        'action_status_name': dict(result.object.action_status_choices)[result.object.action_status],
                        'action_status': result.object.action_status,
                        'suborder_status': result.object.suborder_status,
                        'approbe_user_role': '',
                        'approve_userrole_id': result.object.approve_userrole_id,
                        'type':'search'
                    })
                if result.object.approve_user_id is None and result.object.approve_userrole_id in role_id:
                    jsondata.append({
                        'id': result.object.id,
                        'mainorder': result.object.mainorder_id,
                        'flowconf_name': result.object.mainorder.flowconf.name,
                        'flowconf': result.object.mainorder.flowconf.id,
                        'approve_user_id': result.object.approve_user_id,
                        'approve_user_name': '',
                        'action_status_name': dict(result.object.action_status_choices)[result.object.action_status],
                        'action_status': result.object.action_status,
                        'suborder_status': result.object.suborder_status,
                        'approbe_user_role': result.object.approbe_user_role,
                        'approve_userrole_id': result.object.approve_userrole_id,
                        'type': 'search'
                    })
            else:
                if result.object.approve_user_id is None:
                    jsondata.append({
                        'id': result.object.id,
                        'mainorder': result.object.mainorder_id,
                        'flowconf_name': result.object.mainorder.flowconf.name,
                        'flowconf': result.object.mainorder.flowconf.id,
                        'approve_user_id': result.object.approve_user_id,
                        'approve_user_name': '',
                        'action_status_name': dict(result.object.action_status_choices)[result.object.action_status],
                        'action_status': result.object.action_status,
                        'suborder_status': result.object.suborder_status,
                        'approbe_user_role': result.object.approbe_user_role,
                        'approve_userrole_id': result.object.approve_userrole_id,
                        'type': 'search'
                    })
                else:
                    jsondata.append({
                        'id': result.object.id,
                        'mainorder': result.object.mainorder_id,
                        'flowconf_name': result.object.mainorder.flowconf.name,
                        'flowconf': result.object.mainorder.flowconf.id,
                        'approve_user_id': result.object.approve_user_id,
                        'approve_user_name': result.object.approve_user.username,
                        'action_status_name': dict(result.object.action_status_choices)[result.object.action_status],
                        'action_status': result.object.action_status,
                        'suborder_status': result.object.suborder_status,
                        'approbe_user_role': '',
                        'approve_userrole_id': result.object.approve_userrole_id,
                        'type': 'search'
                    })
    
    
        present_page = int(request.GET.get('page', 1))
        paginator_new = Paginator(jsondata, 4)
        one_page = paginator_new.page(present_page)
        count = paginator_new.count
        data = {
            'count': count,
            'results': list(one_page)
        }
        return data
    
    1.3.6 admin.py
    from django.contrib import admin
    from .models import *
    
    # Register your models here.
    
    admin.site.register(WorkOrderModel)
    admin.site.register(SubOrderModel)
    
    1.3.3 search_indexes.py
    • 建立es索引所需
    # -*- coding: utf-8 -*-
    
    # apps/course/search_indexes.py
    # 文件名必须是 search_indexes.py
    from haystack import indexes
    from workerorder.models import WorkOrderModel, SubOrderModel
    
    
    # 修改此处,类名为模型类的名称+Index,比如模型类为GoodsInfo,则这里类名为GoodsInfoIndex(其 实可以随便写)
    class WorkOrderIndex(indexes.SearchIndex, indexes.Indexable):
        """
        Course索引类
        """
        # text为索引字段
        # document = True,这代表haystack和搜索引擎将使用此字段的内容作为索引进行检索
        # use_template=True 指定根据表中的那些字段建立索引文件的说明放在一个文件中
        text = indexes.CharField(document=True, use_template=True)
    
        # 对那张表进行查询
        def get_model(self):  # 重载get_model方法,必须要有
            """返回建立索引的模型类"""
            return WorkOrderModel  # 返回这个model
    
        # 建立索引的数据
        def index_queryset(self, using=None):
            """返回要建立索引的数据查询集"""
            # 这个方法返回什么内容,最终就会对那些方法建立索引,这里是对所有字段建立索引
            return self.get_model().objects.all()
    
    class SubOrderIndex(indexes.SearchIndex, indexes.Indexable):
        """
        Course索引类
        """
        # text为索引字段
        # document = True,这代表haystack和搜索引擎将使用此字段的内容作为索引进行检索
        # use_template=True 指定根据表中的那些字段建立索引文件的说明放在一个文件中
        text = indexes.CharField(document=True, use_template=True)
    
        # 对那张表进行查询
        def get_model(self):  # 重载get_model方法,必须要有
            """返回建立索引的模型类"""
            return SubOrderModel  # 返回这个model
    
        # 建立索引的数据
        def index_queryset(self, using=None):
            """返回要建立索引的数据查询集"""
            # 这个方法返回什么内容,最终就会对那些方法建立索引,这里是对所有字段建立索引
            return self.get_model().objects.all()
    
    1.3.4 whoosh_cn_backend.py
    • es的中文解析器
    # -*- coding: utf-8 -*-
    # 更换 text 字段的 分析方式, 变为jieba分词中的中文分析器
    from haystack.backends.whoosh_backend import WhooshEngine, WhooshSearchBackend
    from whoosh.fields import TEXT
    from jieba.analyse import ChineseAnalyzer
    
    class MyWhooshSearchBackend(WhooshSearchBackend):
        def build_schema(self, fields):
            (content_field_name, schema) = super().build_schema(fields)
            # 指定whoosh使用jieba进行分词
            schema._fields['text'] = TEXT(stored=True,
                                          analyzer=ChineseAnalyzer(),
                                          field_boost=fields.get('text').boost,
                                          sortable=True)
            return (content_field_name, schema)
    
    class MyWhooshEngine(WhooshEngine):
        backend = MyWhooshSearchBackend
    

    1.4 workflow 模块

    1.4.1 models.py
    from django.db import models
    
    # Create your models here.
    
    from utils.MyBaseModel import BaseModelFlow
    
    
    class FlowType(BaseModelFlow):
        '''
        name:工作流名称
        description:描述
        '''
    
        class Meta:
            db_table = 'workflow_flowtype'
            verbose_name = '工单分类'
            verbose_name_plural = verbose_name
    
    
    
    class FlowConf(BaseModelFlow):
        flowtype = models.ForeignKey(FlowType, on_delete=models.CASCADE)
        customfield = models.TextField('自定义字段', help_text='{}')
    
        class Meta:
            db_table = 'workflow_flowconf'
            verbose_name = '工单模板'
            verbose_name_plural = verbose_name
    
    class NewFlowUserRoleActionConf(models.Model):
        '''
        flowconf:流程审批名称(外键关联FlowConf,一对多)
        sequence:审批序号(用于排序)
        approvetype:审批类型
        approve_type_id:审批类型id
        '''
        flowconf = models.ForeignKey(FlowConf, on_delete=models.CASCADE)
        sequence = models.IntegerField('审批序号', help_text='用于排序')
        type_choice = (
            ('1', '角色组审批'),
            ('2', '指定人员审批')
        )
        approvetype = models.CharField('审批类型', choices=type_choice, max_length=30)
        approve_type_id = models.IntegerField('审批类型id')
    
        class Meta:
            db_table = 'workflow_approveconf'
            verbose_name = '配置审批流'
            verbose_name_plural = verbose_name
    
    1.4.2 serializers.py
    # -*- coding: utf-8 -*-
    
    from rest_framework import serializers
    
    from user.models import User, Role
    from workflow.models import FlowConf, FlowType, NewFlowUserRoleActionConf
    
    
    class FlowConfSerializer(serializers.ModelSerializer):
        flowtype_name = serializers.ReadOnlyField(source='flowtype.name')
        # 第一种序列化展示方法,新增字段flowtype_name储存名称
        class Meta:
            model = FlowConf
            fields = "__all__"
    
    class FlowTypeSerializer(serializers.ModelSerializer):
        class Meta:
            model = FlowType
            fields = '__all__'
    
    class ApproveConfGetSerializer(serializers.ModelSerializer):
        flowconf_name = serializers.ReadOnlyField(source='flowconf.name')
        approvetype_name = serializers.SerializerMethodField(required=False)
        approve_type_id_name = serializers.SerializerMethodField(required=False)
        class Meta:
            model = NewFlowUserRoleActionConf
            fields = '__all__'
    
        def get_approvetype_name(self, row):
            # print(row.approvetype)
            if row.approvetype == '1':
                return '角色组审批'
            elif row.approvetype == '2':
                return '指定人员审批'
            else:
                pass
                # 更多暂未设定
        def get_approve_type_id_name(self, row):
            if row.approvetype == '2':
                return User.objects.filter(pk=row.approve_type_id).first().username
            elif row.approvetype == '1':
                return Role.objects.filter(pk=row.approve_type_id).first().zh_name
            else:
                pass
    
    class ApproveConfSerializer(serializers.ModelSerializer):
        class Meta:
            model = NewFlowUserRoleActionConf
            fields = '__all__'
    
    1.4.3 urls.py
    # -*- coding: utf-8 -*-
    from django.urls import path
    from rest_framework.routers import DefaultRouter
    from workflow import views
    
    router = DefaultRouter()
    router.register(r'flowtype', views.FlowTypeViewSet)
    router.register(r'flowtype_get', views.FlowTypeGetViewSet)
    router.register(r'flowconf', views.FlowConfViewSet)
    router.register(r'flowconf_get', views.FlowConfGetViewSet)
    router.register(r'approveconf', views.ApproveConfViewSet)
    
    urlpatterns = [
    
    ]
    
    urlpatterns += router.urls
    
    1.4.4 views.py
    from django.shortcuts import render
    
    # Create your views here.
    from rest_framework.pagination import PageNumberPagination
    from rest_framework.viewsets import ModelViewSet
    
    from utils.MyAuthorization import MyPermission
    from workflow.models import FlowConf, FlowType, NewFlowUserRoleActionConf
    from workflow.serializers import FlowConfSerializer, FlowTypeSerializer, ApproveConfGetSerializer, ApproveConfSerializer
    
    
    # 分页(局部):自定义分页器 局部
    class PageNum(PageNumberPagination):
        page_size = 4                           # 每页显示多少条
        page_size_query_param = 'page_size'     # 查询字符串中代表每页返回数据数量的参数名, 默认值: None
        page_query_param = 'page'               # 查询字符串中代表页码的参数名, 有默认值: page
        max_page_size = None                    # 最大页码数限制
    
    class FlowConfViewSet(ModelViewSet):
        permission_classes = (MyPermission,)
        queryset = FlowConf.objects.all()
        serializer_class = FlowConfSerializer
        pagination_class = PageNum
        filter_fields = {'name'}
    
    class FlowConfGetViewSet(ModelViewSet):
        # permission_classes = (MyPermission,)
        queryset = FlowConf.objects.all()
        serializer_class = FlowConfSerializer
    
    class FlowTypeViewSet(ModelViewSet):
        permission_classes = (MyPermission,)
        queryset = FlowType.objects.all()
        serializer_class = FlowTypeSerializer
        pagination_class = PageNum
        filter_fields = {'name'}
    
    
    class FlowTypeGetViewSet(ModelViewSet):
        permission_classes = (MyPermission,)
        queryset = FlowType.objects.all()
        serializer_class = FlowTypeSerializer
    
    
    class ApproveConfViewSet(ModelViewSet):
        # permission_classes = (MyPermission,)
        queryset = NewFlowUserRoleActionConf.objects.all()
        serializer_class = ApproveConfGetSerializer
        pagination_class = PageNum
        filter_fields = {'flowconf'}
    
        def get_serializer_class(self):
            print(self.action)
            if self.action == 'list':
                return ApproveConfGetSerializer
            else:
                return ApproveConfSerializer
    
    1.4.5 admin.py
    from django.contrib import admin
    from .models import *
    # Register your models here.
    admin.site.register(NewFlowUserRoleActionConf)
    admin.site.register(FlowConf)
    admin.site.register(FlowType)
    

    1.5 tempaltes文件夹

    • 为es建立索引
    1.5.1 目录
    • 目录一定不能乱写,txt文件名为 模型名_text.txt 模式,不得随意更改

    image-20201212151934042

    1.5.2 subordermodel_text.txt
    • 因为表中 subordermodel 是 workordermodel 的子工单,两个表通过外键连接,所以不可以建立相同模块的索引,否则 views 中会出现找不到指定字段的情况!
    • 建立索引的命令为:python.manage.py rebuild_index
    {{object.create_time}}
    {{object.update_time}}
    {{object.approbe_user_role}}
    {{object.approve_user.username}}
    {{object.get_action_status_display}}
    {{object.get_suborder_status_display}}
    {{object.mainorder.flowconf.name}}
    
    1.5.3 workordermodel_text.txt
    {{object.get_order_status_display}}
    

    1.6 utils 公用工具

    • 此模块内的内容为公用工具
    1.6.1 MyAuthorization.py
    • token解析以及权限认证
    # -*- coding: utf-8 -*-
    from rest_framework.permissions import BasePermission
    from rest_framework_jwt.utils import jwt_decode_handler
    
    from user.models import UserRole
    from workerorder.models import SubOrderModel
    
    
    def decodeToken(request):
        token = request.META.get('HTTP_AUTHORIZATION')
        user_info = jwt_decode_handler(token[4:])
        # user_info = jwt_decode_handler(token)
        user_id = user_info.get('user_id')
        role_info = UserRole.objects.filter(user_id=user_id).values('role_id')
        role_list = []
        for i in role_info:
            role_list.append(i.get('role_id'))
        user_info['role_id'] = role_list
    
        return user_info
    
    def getAuthorization(request):
        user_info = decodeToken(request)
        user_id = user_info.get('user_id')
        role_list = user_info.get('role_id')
        # 实例化工单id
        workorder_id = request.query_params.get('mainorder')
        suborder_list = []
        for i in SubOrderModel.objects.filter(mainorder_id=workorder_id):
            suborder_list.append(i.id)
        suborder_list=sorted(suborder_list)
        queryset = []
        for suborder_id in suborder_list:
            # 审批类型id,1角色审批,2指定人审批
            obj = SubOrderModel.objects.filter(pk=suborder_id).values()[0]
            approve_type_id = obj['approve_type_id']
            if approve_type_id == '1':
                approve_userrole_id = obj['approve_userrole_id']
                if approve_userrole_id in role_list:
                    if obj['action_status'] == '1' and obj['suborder_status'] == '1':
                            obj['type'] = 1
                else:
                    obj['type'] = 0
                queryset.append(obj)
            elif approve_type_id == '2':
                approve_user = obj['approve_user_id']
                if user_id == approve_user:
                    if obj['action_status'] == '1' and obj['suborder_status'] == '1':
                        obj['type'] = 1
                else:
                    obj['type'] = 0
                queryset.append(obj)
        return queryset
    
    
    class MyPermission(BasePermission):
        # 继承的一定要是rest_framework里面的BasePermission,类的名字随意
        # has_permission 是用户对这个视图有没有 GET POST PUT PATCH DELETE 权限的分别判断
        def has_permission(self, request, view):
            print(123,request.method)
            # 可以用request.user来获取用户名
            # 可以用request.method来查询访问的方式
            # 可以用request.path_info来查询访问的路由
            # 可以用 print(dir(request))来查看方法
            # 任何用户对使用此权限类的视图都有访问权限
            if request.method == 'POST' or request.method == 'DELETE' or request.method == 'PUT' or request.method == 'GET':
                print(request.method)
                if request.user.is_superuser:
                    return True
                elif view.kwargs.get('pk') == str(request.user.id):
                    return False
    
    # has_object_permission 是用户过了 has_permission 判断有权限以后,再判断这个用户有 没有对一个具体的对象有没有操作权限
    # 这样设置以后,即使是django admin管理员也只能查询自己user标的信息,不能查询其他用户的 单条信息
    
    #     def has_object_permission(self, request, view,obj):
    #         # 判断当前用户是否有访问 /course/sections/1/ 接口权限
    #         course_detail_url = re.match('/course/sections/(d+)/$', request.path_info)
    #         if course_detail_url:
    #             user = request.user
    #             course = obj.chapters.course
    #             has_video_rights = self.video_rights(user,course)
    #             return has_video_rights
    #         return True
    
    1.6.2 MyBaseModel.py
    • 模型继承
    # -*- coding: utf-8 -*-
    from django.db import models
    
    class BaseModel(models.Model):
        is_delete = models.BooleanField('是否刪除', default=0)
        create_time = models.DateField('创建时间', auto_now_add=True, null=True)
        update_time = models.DateField('更新时间', auto_now=True, null=True)
    
        class Meta:
            abstract = True
    
    class BaseModelFlow(models.Model):
        name = models.CharField('名称', max_length=60)
        description = models.TextField('描述')
    
        class Meta:
            abstract = True
    
    1.6.3 MyEncoder.py
    • 编码问题处理
    # -*- coding: utf-8 -*-
    
    import json
    class MyEncoder(json.JSONEncoder):
    
        def default(self, obj):
            if isinstance(obj, bytes):
                return str(obj, encoding='utf-8')
    
            return json.JSONEncoder.default(self, obj)
    
    1.6.4 MyPaginator.py
    # -*- coding: utf-8 -*-
    from django.core.paginator import Paginator
    
    def basePaginator(queryset, request, page_size, serializer):
        # 当前页
        present_page = int(request.GET.get('page', 1))
        # 自定义分页器
        paginator_get = Paginator(queryset, page_size)
        # 一页数据
        one_page = serializer(paginator_get.page(present_page), many=True).data
        # 总页数
        count = paginator_get.count
        data = {
            'count': count,
            'results': one_page
        }
        return data
    
    1.6.5 MySendEmail.py
    # -*- coding: utf-8 -*-
    from django.conf import settings
    from django.core.mail import send_mail
    from workerorder.models import *
    
    
    def EmailInform(user_list):
        for user_id in user_list:
            email = User.objects.filter(pk=user_id).first().email
            username = User.objects.filter(pk=user_id).first().username
            subject = '勤奋的工单系统'
            message = ''
            from_email = settings.EMAIL_FROM
            recipient_list = [email]
            html_message = 'dear{},您有新的工单审批信息了!可以点击以下链接进行工单审批:<a href="http://127.0.0.1:8080/login/">审批工单</a>'.format(username)
            send_mail(subject=subject,
                      message=message,
                      from_email=from_email,
                      recipient_list=recipient_list,
                      html_message=html_message)
    
    
    def sayHello():
        obj = SubOrderModel.objects.filter(suborder_status='1', action_status='1')
        for i in obj:
            if i.approve_type_id == '2':
                username = User.objects.filter(pk=i.approve_user_id).first().username
                email = User.objects.filter(pk=i.approve_user_id).first().eamil
                subject = '守约的工单系统'
                message = ''
                from_email = settings.EMAIL_FROM
                recipient_list = [email]
                html_message = 'Dear{}, 您有新的指定工单需要审批,十万火急!请点击以下链接查看最新动态!<a href="http://127.0.0.1:8080/login/">宇宙无敌混世大魔王的订单系统</a>'.format(username)
                send_mail(subject=subject,
                          message=message,
                          from_email=from_email,
                          recipient_list=recipient_list,
                          html_message=html_message)
    
    
    def timeOutEmail(username, email):
        subject = '贱贱的工单'
        message = ''
        from_email = settings.EMAIL_FROM
        recipient_list = [email]
        html_message = 'Dear{},呀,一不小心,您的工单超时了呢,真可怜~请点击以下链接查看最新动态!<a href="http://127.0.0.1:8080/login/">宇宙无敌混世大魔王的订单系统</a>'.format(username)
        send_mail(subject=subject,
                  message=message,
                  from_email=from_email,
                  recipient_list=recipient_list,
                  html_message=html_message)
    
    
    def backEmail(username, email, text):
        subject = '美丽的的工单'
        message = ''
        from_email = settings.EMAIL_FROM
        recipient_list = [email]
        html_message = 'Dear{},您的您的工单审批结果已出,被{},请点击以下链接查看最新动态!<a href="http://127.0.0.1:8080/login/">宇宙无敌混世大魔王的订单系统</a>'.format(username, text)
        send_mail(subject=subject,
                  message=message,
                  from_email=from_email,
                  recipient_list=recipient_list,
                  html_message=html_message)
    

    1.7 celery_task

    • celery配置
    • celery启动命令
    celery -A celery_task.celery_lk worker -l INFO
    celery -A celery_task.celery_lk beat -l INFO
    
    • 其中出现 no model named celery_task
    # 解决方案是导入项目根目录(就是opwf_object地址)
    # 在启动celery失败的时候,记得更改celery.py为celery_lk.py启动文件
    
    1.7.1 celery_lk.py
    • celery启动文件
    # -*- coding: utf-8 -*-
    from celery import Celery
    import os,  sys
    CELERY_BASE_DIR = os.path.dirname(os.path.abspath(__file__))
    print(sys.path)
    
    
    # celery项目中的所有导包地址, 都是以CELERY_BASE_DIR为基准设定.
    # 执行celery命令时, 也需要进入CELERY_BASE_DIR目录执行.
    import django
    sys.path.insert(0, os.path.join(CELERY_BASE_DIR, '../opwf'))
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "opwf.settings")
    
    # 定义celery实例, 需要的参数, 1, 实例名, 2, 任务发布位置, 3, 结果保存位置
    app = Celery('celery',
                 broker='redis://127.0.0.1:6379/2',   # 任务存放的地方
                 backend='redis://127.0.0.1:6379/3',   # 结果存放的地方
                 include=['celery_task.tasks', 'celery_task.tasks_beat', 'celery_task.tasks_timeout', 'celery_task.tasks_back'])
                # 由于上面配置了路径,所以导入时需要注意
    
    app.conf.update(
       result_expires=3600,        #执行结果放到redis里,一个小时没人取就丢弃
    )
    
    from celery.schedules import crontab
    # 配置定时任务
    app.conf.beat_schedule = {
        'add-every-180-seconds': {
            'task': 'celery_task.tasks_beat.say_hello',
            # 'schedule': 180.0,
            # 每180秒发送一次任务
            'schedule': crontab(hour=8, minute=22, day_of_week=2),
        },
        'check-every-24-hours': {
            'task': 'celery_task.tasks_timeout.timeout_workorder',
            'schedule': 180.0,
        }
    }
    
    
    app.conf.timezone = 'Asia/Shanghai'
    
    if __name__ == '__main__':
       app.start()
    
    1.7.2 tasks.py

    image-20201212155420891

    • 异步发送邮件任务
    # -*- coding: utf-8 -*-
    # @app.task 指定将这个函数的执行交给celery异步执行
    # 相当于装饰器,将下面函数打包给app
    from celery_task.celery_lk import app
    
    @app.task(bind=True)
    def send_email(self, user_list):
        # 在方法中导包
        from utils.MySendEmail import EmailInform
        # time.sleep(5)
        try:
            # 用 res 接收发送结果, 成功是:0, 失败是:-1
            res = EmailInform(user_list)
        except Exception as e:
            res = '-1'
        if res == '-1':
            # 如果发送结果是 -1 就重试.
            self.retry(countdown=5, max_retries=3, exc=Exception('邮箱发送失败'))
    
    1.7.3 tasks_timeout.py

    image-20201212155445074

    • celery超时任务,采用 celery 定时任务实施监控,开启一个beat调度worker对工单的状态进行监控,对72小时未审批的工单创建者进行通知,将工单状态改为超时
    # -*- coding: utf-8 -*-
    # -*- coding: utf-8 -*-
    from __future__ import absolute_import, unicode_literals
    # @app.task 指定将这个函数的执行交给celery异步执行
    from django.db.models import Q
    from django.utils import timezone
    # 相当于装饰器,将下面函数打包给app
    from celery_task.celery_lk import app
    from user.models import User
    from workerorder.models import WorkOrderModel
    
    now = timezone.now()
    start_time = now - timezone.timedelta(hours=48)
    end_time = now
    
    
    @app.task(bind=True)
    def timeout_workorder(self):
        # 在方法中导包
        from utils.MySendEmail import timeOutEmail
        workorder_queryset = WorkOrderModel.objects.exclude(
            Q(create_time__range=(start_time, end_time))).filter(Q(order_status='1'))
        for query in workorder_queryset:
            username = User.objects.filter(pk=query.create_user_id).first().username
            email = User.objects.filter(pk=query.create_user_id).first().email
            res = timeOutEmail(username, email)
            WorkOrderModel.objects.filter(id=query.id).update(order_status=2)
    
    1.7.4 tasks_beat.py

    image-20201212160033505

    • celery定时任务,每周一八点半对所有在当前审批节点的用户进行工单未审批通知。
    # -*- coding: utf-8 -*-
    
    from __future__ import absolute_import, unicode_literals
    # @app.task 指定将这个函数的执行交给celery异步执行
    
    # 相当于装饰器,将下面函数打包给app
    from celery_task.celery_lk import app
    
    @app.task(bind=True)
    def say_hello(self):
        # 在方法中导包
        from utils.MySendEmail import sayHello
        # time.sleep(5)
        try:
            # 用 res 接收发送结果, 成功是:0, 失败是:-1
            res = sayHello()
        except Exception as e:
            res = '-1'
        if res == '-1':
            # 如果发送结果是 -1 就重试.
            self.retry(countdown=5, max_retries=3, exc=Exception('邮箱发送失败'))
    
    1.7.5 tasks_back.py

    image-20201212155540134

    • 工单一旦完成就通知审批人,对当前工单的状态通过邮件的方式进行告知。
    # -*- coding: utf-8 -*-
    from celery_task.celery_lk import app
    
    @app.task(bind=True)
    def back_email(self, username, email, text):
        # 在方法中导包
        from utils.MySendEmail import backEmail
        # time.sleep(5)
        try:
            # 用 res 接收发送结果, 成功是:0, 失败是:-1
            res = backEmail(username, email, text)
        except Exception as e:
            res = '-1'
        if res == '-1':
            # 如果发送结果是 -1 就重试.
            self.retry(countdown=5, max_retries=3, exc=Exception('邮箱发送失败'))
    

    1.8 项目部署

    1.8.1 nginx部署
    • 写入etc/nginx/conf.d/django.conf
    server {
            listen 1594;
            server_name 192.168.56.100;
                    location /static {
                            alias /home/worker/opwf_project/opwf/static;
                    }
    
                    location / {
                            include uwsgi_params;
                            uwsgi_pass 127.0.0.1:8000;
                            uwsgi_ignore_client_abort on;
                    }
    }
    
    server {
            listen 8888;
            server_name 192.168.56.100;
            #access_log logs/access_example.log  main;
            root /home/worker/opwf_project/opwf/static/dist;
            location / {
                    try_files $uri $uri/ @router;
            }
            location @router {
                    rewrite ^.*$ /index.html last;
            }
    }
    
    1.8.2 uwsgi_conf
    • uwsgi 部署

    image-20201212161242664

    • uwsgi.ini
    # vim /root/shiyanlou_project/uwsgi_conf/uwsgi.ini
    # vim中,A键进入插入模式,ESC退出,:wq保存并退出
    # 或者pycharm中直接粘贴也可以
    [uwsgi]
    # 使用Nginx连接时使用,Django程序所在服务器地址和端口号
    socket=127.0.0.1:8000
    # 项目目录绝对路径
    chdir=/home/worker/opwf_project/opwf
    # 项目中wsgi.py文件的目录,相对于项目目录
    wsgi-file=opwf/wsgi.py
    # 进程数(机器核数的1倍)
    processes=4
    # 线程数
    threads=20
    # uwsgi服务器的角色
    master=True
    # 存放进程编号的文件
    pidfile=uwsgi.pid
    # 日志文件
    daemonize=uwsgi.log
    # 指定依赖的虚拟环境
    virtualenv=/root/.virtualenvs/syl
    
  • 相关阅读:
    H50055:html 页面加载完后再加载js文件 ,url带有时间戳后缀
    H50054:html 页面自动刷新 http-equiv属性
    WebGL_0015:参数值在一定范围内循环变化
    H50053:switch 判断范围
    WebGL_0014:改变相机的刷新颜色
    WebGL_0013:JQuery获取json文件 读取数据
    WebGL_0012:三维讲解导航模板 Icon方式
    H50052:按钮 禁止 选择 拖拽 右键
    滑动窗口的最大值(队列)
    MapReduce程序编写过程
  • 原文地址:https://www.cnblogs.com/mapel1594184/p/14145890.html
Copyright © 2011-2022 走看看