美文网首页
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