查看端口是否被占用—小妙招
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
网友评论