美文网首页
Python(六十二)提升系统

Python(六十二)提升系统

作者: Lonelyroots | 来源:发表于2022-02-17 18:10 被阅读0次

    查看端口是否被占用—小妙招

    netstat -ano:在cmd中输入命令,即可查看本地所有端口

    1. 创建项目环境

    mkvirtualenv -p /usr/bin/python3 promote:创建一个虚拟环境promote。


    pip install django -i https://pypi.douban.com/simple
    pip install djangorestframework -i https://pypi.douban.com/simple
    pip install pymysql -i https://pypi.douban.com/simple

    rmvirtualenv promote:如果解释器设置错误,删除虚拟环境promote

    CREATE DATABASE `promote` CHARSET='utf8';:新建一个数据库
    GRANT ALL PRIVILEGES ON `promote`.* TO 'promoteu'@'%' IDENTIFIED BY 'qwe123';:新建一个数据库用户promoteu,密码qwe123。
    FLUSH PRIVILEGES;:刷新权限
    EXIT;:退出数据库

    django-admin startproject promote:创建一个django项目promote

    ......(pycharm新建项目步骤省略不写)
    不知道同步到哪一级,可以cd到出现manage.py文件为止,然后通过pwd查看路径。


    将文件download下来,然后通过pycharm的settings进行django项目的部署。

    2. settings文件配置

    promote/settings.py:

    ALLOWED_HOSTS = ['*']       # 允许所有的主机进行访问(五、容联云发送短信)
    

    2.1. 数据库配置

    config/dbs/mysql.cnf:

    [client]
    database = promote
    user = promoteu
    password = qwe123
    host = 127.0.0.1
    port = 3306
    default-character-set = utf8
    

    promote/settings.py:

    DATABASES = {
        'sqlite3': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': BASE_DIR / 'db.sqlite3',
        },
        # 通过cnf文件配置数据库(五、容联云发送短信)
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'OPTIONS':{
                'read_default_file':'config/dbs/mysql.cnf'
            },
        }
    }
    

    promote/init.py:

    #(五、容联云发送短信)
    
    import pymysql
    
    pymysql.install_as_MySQLdb()
    

    2.2. 日志记录

    logs/promote.log:

    promote/settings.py:

    # 配置日志器,记录网站的日志信息(五、容联云发送短信)
    LOGGING = {
        # 版本
        'version': 1,
        # 是否禁用已存在的日志器
        'disable_existing_loggers': False,
        'formatters': {
            'verbose': {
                'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
            },
            'simple': {
                'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
            },
        },
        'filters': {
            'require_debug_true': {
                '()': 'django.utils.log.RequireDebugTrue',
            },
        },
        'handlers': {
            'console': {
                'level': 'DEBUG',
                'filters': ['require_debug_true'],
                'class': 'logging.StreamHandler',
                'formatter': 'simple'
            },
            'file': {
                'level': 'INFO',
                'class': 'logging.handlers.RotatingFileHandler',
                'filename': os.path.join(BASE_DIR, "logs/promote.log"),  # 日志文件的位置
                'maxBytes': 300 * 1024 * 1024,
                'backupCount': 10,
                'formatter': 'verbose'
            },
        },
        'loggers': {
            'django': {  # 定义了一个名为django的日志器
                'handlers': ['console', 'file'],
                'propagate': True,
                'level': 'INFO',  # 日志器接收的最低日志级别
            },
        }
    }
    

    2.3. 时区修改:

    promote/settings.py:

    LANGUAGE_CODE = 'zh-hans'       #(五、容联云发送短信)
    
    TIME_ZONE = 'Asia/Shanghai'     #(五、容联云发送短信)
    
    USE_I18N = True
    
    USE_L10N = True
    
    USE_TZ = False       #(五、容联云发送短信)
    

    2.4. 添加apps到项目的搜索路径

    promote/settings.py:

    # 添加apps到项目的搜索路径(五、容联云发送短信)
    sys.path.insert(0,BASE_DIR)
    sys.path.insert(1,os.path.join(BASE_DIR,'apps'))
    

    2.5. 过滤推送文件


    vim .gitignore:编辑提交文件

    3. 登录admin后台

    3.1. 创建超级管理员

    makemigrations:先映射文件,
    migrate:提交映射文件
    createsuperuser:创建超级管理员



    admin后台管理

    4. Token令牌

    4.1. Token的本质

    加密了的字符串数据,意味着前端可以是任何编程语言开发的APP/小程序,都可以用Token进行验证。

    4.2. Token含义

    不需要服务器频繁的去与数据库进行交互查询账户密码是否正确,改为解密,服务器进行解密就OK啦!
    登陆之后,服务器生成Token,之后每次客户端请求携带Token即可。Token为了减轻服务器的压力,减少频繁的查询数据库。



    下图意为客户端找到令牌发放者,进行身份验证,然后拿着令牌进入提升城。


    4.3. JWT

    JWT:JSON Web Token是Token令牌生成的规范。
    由三部分组成:
    header 头部:包含加密方式,通常使用HMAC,SHA256方式。
    payload 载体 数据:Token要包含的数据。
    signature 签名:将Header和payload使用Base64编码伪加密生成,加入签名字符用加密算法加密一遍,得到唯一的签名。用来防止其他人篡改Token中的信息。


    4.4. 私钥隐藏

    config/secret.py:

    SECRET_KEY = ......(省略不写,创建项目自带)
    

    promote/settings.py:

    from config.secret import SECRET_KEY
    SECRET_KEY = SECRET_KEY
    

    5. 登录

    这里需要先在虚拟机中导入令牌生成规范模块pip install djangorestframework-jwt -i https://pypi.douban.com/simple

    5.1. Token令牌过期时间配置

    promote/settings.py:

    可以通过REST framework JWT Auth 官方文档查看程序如何编写。

    import datetime
    
    # 过期时间配置
    JWT_AUTH = {
        'JWT_EXPIRATION_DELTA':datetime.timedelta(days=1),      # 令牌有效时间为一天,你可以刷新有效时间,七天以后必须要登录
    }
    

    5.2. 新建app:users、school:

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'rest_framework',       # (五、容联云发送短信)
        'users',        # (五、容联云发送短信)
        'school',        # (五、容联云发送短信)
    ]
    

    apps/users/urls.py:

    通过rest_framework_jwt.views的obtain_jwt_token方法进行路由配置,不需要写视图函数,就可以完成简单的登录。

    # (五、容联云发送短信)
    
    from django.urls import path
    from rest_framework_jwt.views import obtain_jwt_token
    
    urlpatterns = [
        path('login/',obtain_jwt_token)
    ]
    

    5.3. 网页登录查看

    通过路由访问,可以得到如下界面,输入注册的账户,可以获得Token令牌。


    一般情况下,我们是看不懂Token的值是什么意思,所以我们需要用到一个网页工具
    开发工具箱-JWT在线解密

    6. 用pycharm连接数据库

    为方便数据库操作,我们通过pycharm来连接数据库
    第一次使用需要下载插件


    下载了插件以后,可能还会出现这样的错误:


    [08S01] Communications link failure
    
    The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
    java.net.ConnectException: Connection refused: connect.
    

    解决方法:不妨将linux的MySQL换个端口转发出来试试看。

    连接成功,会出现下方这个界面,接下来,就任你操作了!


    7. 班级管理系统

    7.1. 班级管理系统代码

    apps/school/models.py:

    # (五、容联云发送短信)
    
    from django.db import models
    from django.contrib.auth.models import User
    
    # Create your models here.
    class Classes(models.Model):
        name = models.CharField(max_length=30,verbose_name='班级名')
        slogan = models.TextField(verbose_name='口号',null=True,blank=True)
        create_time = models.DateTimeField(auto_now_add=True,verbose_name='创建时间')
        update_time = models.DateTimeField(auto_now=True,verbose_name='修改时间')
        is_delete = models.BooleanField(default=False,verbose_name='逻辑删除')
    
        member = models.ManyToManyField(User)
    
        class Meta:
            db_table = 'classes'
            verbose_name = '班级'     # verbose_name 表示单数形式
            verbose_name_plural = verbose_name      # verbose_name_plural表示复数形式
    
        def delete(self, using=None, keep_parents=False):
            self.is_delete = True
            self.save()
    

    apps/school/serializers.py:

    # (五、容联云发送短信)
    
    from rest_framework.serializers import ModelSerializer
    from .models import Classes
    from users.serializers import UserSerializer
    
    class ClassesSerializer(ModelSerializer):
        class Meta:
            model = Classes     # 选择映射的模型类
            exclude = ['id','is_delete']        # 不要'id'与'is_delete'这两个字段
    

    apps/school/views.py

    # (五、容联云发送短信)
    
    from django.shortcuts import render
    from rest_framework.viewsets import ModelViewSet
    from .models import Classes
    from .serializers import ClassesSerializer
    
    class ClassesViewSet(ModelViewSet):
        queryset = Classes.objects.filter(is_delete=False)       # 查询集
        serializer_class = ClassesSerializer
    

    apps/school/urls.py:

    # (五、容联云发送短信)
    
    from rest_framework.routers import DefaultRouter        # 默认的路由器
    from .views import ClassesViewSet
    
    urlpatterns = [
    
    ]
    
    router = DefaultRouter()        # 创建路由器,多了个导航功能,告诉我们有哪些根路由
    router.register('classes',ClassesViewSet)       # 注册班级的路由
    urlpatterns += router.urls      # 拼接获取生成的路由列表
    

    promote/urls.py:

    from django.contrib import admin
    from django.urls import path,include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('users/',include('users.urls')),
        path('school/',include('school.urls')),
    ]
    

    7.2. 序列化器嵌套

    为了将user信息显示出来,而不是id,所以我们需要做序列化器嵌套


    apps/school/models.py:

    # (五、容联云发送短信)
    
    from django.db import models
    from django.contrib.auth.models import User
    
    # Create your models here.
    class Classes(models.Model):
        name = models.CharField(max_length=30,verbose_name='班级名')
        slogan = models.TextField(verbose_name='口号',null=True,blank=True)
        create_time = models.DateTimeField(auto_now_add=True,verbose_name='创建时间')
        update_time = models.DateTimeField(auto_now=True,verbose_name='修改时间')
        is_delete = models.BooleanField(default=False,verbose_name='逻辑删除')
    
        member = models.ManyToManyField(User)
    
        class Meta:
            db_table = 'classes'
            verbose_name = '班级'     # verbose_name 表示单数形式
            verbose_name_plural = verbose_name      # verbose_name_plural表示复数形式
    
        def delete(self, using=None, keep_parents=False):
            self.is_delete = True
            self.save()
    

    apps/users/serializers.py:

    # (五、容联云发送短信)
    
    from rest_framework.serializers import ModelSerializer
    from django.contrib.auth.models import User
    
    class UserSerializer(ModelSerializer):
        class Meta:
            model = User
            exclude = ['id','password']
    

    apps/school/serializers.py:

    # (五、容联云发送短信)
    
    from rest_framework.serializers import ModelSerializer
    from .models import Classes
    from users.serializers import UserSerializer
    
    
    class ClassesSerializer(ModelSerializer):
        # 序列化器的嵌套
        member = UserSerializer(many=True)
    
        class Meta:
            model = Classes     # 选择映射的模型类
            exclude = ['id','is_delete']        # 不要'id'与'is_delete'这两个字段
    

    apps/school/views.py

    # (五、容联云发送短信)
    
    from django.shortcuts import render
    from rest_framework.viewsets import ModelViewSet
    from .models import Classes
    from .serializers import ClassesSerializer
    
    class ClassesViewSet(ModelViewSet):
        queryset = Classes.objects.filter(is_delete=False)       # 查询集
        serializer_class = ClassesSerializer
    

    apps/school/urls.py:

    # (五、容联云发送短信)
    
    from rest_framework.routers import DefaultRouter        # 默认的路由器
    from .views import ClassesViewSet
    
    urlpatterns = [
    
    ]
    
    router = DefaultRouter()        # 创建路由器,多了个导航功能,告诉我们有哪些根路由
    router.register('classes',ClassesViewSet)       # 注册班级的路由
    urlpatterns += router.urls      # 拼接获取生成的路由列表
    

    promote/urls.py:

    from django.contrib import admin
    from django.urls import path,include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('users/',include('users.urls')),
        path('school/',include('school.urls')),
    ]
    

    除了序列化器嵌套,这种方法也同样适用。
    这是一个只读字段。它通过调用附加到的序列化程序类上的方法来获取其值。它可用于将任何类型的数据添加到对象的序列化表示中。
    SerializerMethodField(method_name=None),method_name:要调用的序列化程序上方法的名称。如果不包含此默认值get_<field_name>。则method_name参数引用的序列化方法应该接受一个参数(除了self),它是被序列化的对象。它应该返回想要包含在对象的序列化表示中的任何内容。

    apps/school/serializers.py:

    # (五、容联云发送短信)
    
    from rest_framework.serializers import ModelSerializer
    from .models import Classes
    from rest_framework.fields import SerializerMethodField      # 序列化器方法字段
    from users.serializers import UserSerializer
    
    
    class ClassesSerializer(ModelSerializer):
        memberDetail = SerializerMethodField()    # 将memberDetail字段设置成SerializerMethodField(),自动调用 get_变量名 方法
        class Meta:
            model = Classes     # 选择映射的模型类
            exclude = ['id','is_delete']        # 不要'id'与'is_delete'这两个字段
    
            extra_kwargs = {
                'member':{'write_only':True}
            }       # 这样做了以后,没有member字段显示
    
        def get_memberDetail(self,classes):
            serializer = UserSerializer(classes.member.all(),many=True)
            data = {
                'teacher' : [i for i in serializer.data if i['is_staff'] or 1 in i['groups']],     # is_staff为1是超级管理员,或auth_group表里id为1的用户
                'student' : [i for i in serializer.data if 2 in i['groups']]
            }
            return data     # 将data数据返还给member
    
    运行结果

    这里我们用postman接口测试软件来访问Classes List。


    Postman
    运行结果

    8. 权限设置

    为了防止学生也能够查看所有信息,我们需要做权限设置

    apps/users/serializers.py:

    # (五、容联云发送短信)
    
    from rest_framework.serializers import ModelSerializer
    from django.contrib.auth.models import User
    
    class UserSerializer(ModelSerializer):
        class Meta:
            model = User
            exclude = ['id','password']
    

    apps/school/serializers.py:

    # (五、容联云发送短信)
    
    from rest_framework.serializers import ModelSerializer
    from .models import Classes
    from rest_framework.fields import SerializerMethodField      # 序列化器方法字段
    from users.serializers import UserSerializer
    
    
    class ClassesSerializer(ModelSerializer):
        memberDetail = SerializerMethodField()    # 将memberDetail字段设置成SerializerMethodField(),自动调用 get_变量名 方法
        class Meta:
            model = Classes     # 选择映射的模型类
            exclude = ['id','is_delete']        # 不要'id'与'is_delete'这两个字段
    
            extra_kwargs = {
                'member':{'write_only':True}
            }       # 这样做了以后,没有member字段显示
    
        def get_memberDetail(self,classes):
            serializer = UserSerializer(classes.member.all(),many=True)
            data = {
                'teacher' : [i for i in serializer.data if i['is_staff'] or 1 in i['groups']],     # is_staff为1是超级管理员,或auth_group表里id为1的用户
                'student' : [i for i in serializer.data if 2 in i['groups']]
            }
            return data     # 将data数据返还给member
    

    apps/users/utils.py:

    # (五、容联云发送短信)
    
    from rest_framework.permissions import BasePermission
    from django.contrib.auth.models import Group
    
    class MyPermission(BasePermission):     # 自定义权限认证类
        # 重写权限认证方法
        def has_permission(self, request, view):
            # 得到当前的Token用户
            user = request.user
            # 获取有权限的分组:老师组
            group = Group.objects.filter(name='老师').first()
            # 获取令牌用户所属的分组
            groups = user.groups.all()
            return user.is_superuser or group in groups
    
    def jwt_token(token,user=None,request=None):
        """自定义登录成功,返回数据处理函数"""
        data = {
            'token':token,
            'username':user.username,
        }
        return data
    

    promote/settings.py:

    # 过期时间配置(五、容联云发送短信)
    JWT_AUTH = {
        'JWT_EXPIRATION_DELTA':datetime.timedelta(days=1),      # 令牌有效时间为一天,你可以刷新有效时间,七天以后必须要登录
        'JWT_RESPONSE_PAYLOAD_HANDLER':'users.utils.jwt_token'
    }
    
    
    # 认证(五、容联云发送短信)
    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework_jwt.authentication.JSONWebTokenAuthentication',     # 全局认证方式为JWT认证方式
            'rest_framework.authentication.SessionAuthentication',
            'rest_framework.authentication.BasicAuthentication',
        ),
    }
    

    apps/school/views.py:

    # (五、容联云发送短信)
    
    from django.shortcuts import render
    from rest_framework.viewsets import ModelViewSet
    from .models import Classes
    from .serializers import ClassesSerializer
    from rest_framework.permissions import IsAuthenticated
    from users.utils import MyPermission
    
    class ClassesViewSet(ModelViewSet):
        # permission_classes = [IsAuthenticated]      # 登录才有操作权限
        permission_classes = [MyPermission]      # 使用自定义权限
    
        queryset = Classes.objects.filter(is_delete=False)       # 查询集
        serializer_class = ClassesSerializer
    

    apps/school/urls.py:

    # (五、容联云发送短信)
    
    from rest_framework.routers import DefaultRouter        # 默认的路由器
    from .views import ClassesViewSet
    
    urlpatterns = [
    
    ]
    
    router = DefaultRouter()        # 创建路由器,多了个导航功能,告诉我们有哪些根路由
    router.register('classes',ClassesViewSet)       # 注册班级的路由
    urlpatterns += router.urls      # 拼接获取生成的路由列表
    

    文章到这里就结束了!希望大家能多多支持Python(系列)!六个月带大家学会Python,私聊我,可以问关于本文章的问题!以后每天都会发布新的文章,喜欢的点点关注!一个陪伴你学习Python的新青年!不管多忙都会更新下去,一起加油!

    Editor:Lonelyroots

    相关文章

      网友评论

          本文标题:Python(六十二)提升系统

          本文链接:https://www.haomeiwen.com/subject/ivzjlrtx.html