我们将Django的应用放到了 工程目录/meiduo_mall/apps
目录下,如果创建一个应用,比如users,那么在配置文件的INSTALLED_APPS中注册应用应该如下:
INSTALLED_APPS = [
...
'meiduo_mall.apps.users.apps.UsersConfig',
]
为了还能像如下方式简便的注册引用,我们需要向Python解释器的导包路径中添加apps应用目录的路径。
INSTALLED_APPS = [
...
'users.apps.UsersConfig',
]
我们将配置文件改为放在settings子目录下,所以 配置文件中的BASE_DIR
指向的变为了meiduo/meiduo_mall/meiduo_mall
。
使用sys.path
添加
目录,即可添加apps应用的导包路径。
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# 添加导包路径
import sys
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
在INSTALLED_APPS中添加rest_framework
INSTALLED_APPS = [
...
'rest_framework',
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'meiduo', # 数据库用户名
'PASSWORD': 'meiduo', # 数据库用户密码
'NAME': 'meiduo_mall' # 数据库名字
}
}
注意:
记得在meiduo/meiduo_mall/__init__.py
文件中添加
import pymysql
pymysql.install_as_MySQLdb()
安装django-redis,并配置
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://10.211.55.5:6379/0",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
"session": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://10.211.55.5:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"
除了名为default的redis配置外,还补充了名为session的redis配置,分别使用两个不同的redis库。
同时修改了Django的Session机制使用redis保存,且使用名为’session’的redis配置。
此处修改Django的Session机制存储主要是为了给Admin站点使用。
关于django-redis 的使用,说明文档可见http://django-redis-chs.readthedocs.io/zh_CN/latest/
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
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在debug模式下才输出日志
'()': '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(os.path.dirname(BASE_DIR), "logs/meiduo.log"), # 日志文件的位置
'maxBytes': 300 * 1024 * 1024,
'backupCount': 10,
'formatter': 'verbose'
},
},
'loggers': { # 日志器
'django': { # 定义了一个名为django的日志器
'handlers': ['console', 'file'], # 可以同时向终端与文件中输出日志
'propagate': True, # 是否继续传递日志信息
'level': 'DEBUG', # 日志器接收的最低日志级别
},
}
}
修改Django REST framework的默认异常处理方法,补充处理数据库异常和Redis异常。
新建utils/exceptions.py
from rest_framework.views import exception_handler as drf_exception_handler
import logging
from django.db import DatabaseError
from redis.exceptions import RedisError
from rest_framework.response import Response
from rest_framework import status
# 获取在配置文件中定义的logger,用来记录日志
logger = logging.getLogger('django')
def exception_handler(exc, context):
"""
自定义异常处理
:param exc: 异常
:param context: 抛出异常的上下文
:return: Response响应对象
"""
# 调用drf框架原生的异常处理方法
response = drf_exception_handler(exc, context)
if response is None:
view = context['view']
if isinstance(exc, DatabaseError) or isinstance(exc, RedisError):
# 数据库异常
logger.error('[%s] %s' % (view, exc))
response = Response({'message': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
return response
配置文件中添加
REST_FRAMEWORK = {
# 异常处理
'EXCEPTION_HANDLER': 'meiduo_mall.utils.exceptions.exception_handler',
}
Django提供了认证系统
Django认证系统同时处理认证和授权。简单地讲,认证验证一个用户是否它们声称的那个人,授权决定一个通过了认证的用户被允许做什么。 这里的词语“认证”同时指代这两项任务,即Django的认证系统同时提供了认证机制和权限机制。
Django的认证系统包含:
Django默认提供的认证系统中,用户的认证机制依赖Session机制,我们在本项目中将引入JWT认证机制,将用户的身份凭据存放在Token中,然后对接Django的认证系统,帮助我们来实现:
Django认证系统中提供了用户模型类User保存用户的数据,默认的User包含以下常见的基本字段:
username
必选。 150个字符以内。 用户名可能包含字母数字,_
,@
,+
.
和-
个字符。在Django更改1.10:max_length
从30个字符增加到150个字符。
first_name
可选(blank=True
)。 少于等于30个字符。
last_name
可选(blank=True
)。 少于等于30个字符。
email
可选(blank=True
)。 邮箱地址。
password
必选。 密码的哈希及元数据。 (Django 不保存原始密码)。 原始密码可以无限长而且可以包含任意字符。
groups
与Group
之间的多对多关系。
user_permissions
与Permission
之间的多对多关系。
is_staff
布尔值。 指示用户是否可以访问Admin 站点。
is_active
布尔值。 指示用户的账号是否激活。 我们建议您将此标志设置为False
而不是删除帐户;这样,如果您的应用程序对用户有任何外键,则外键不会中断。它不是用来控制用户是否能够登录。 在Django更改1.10:在旧版本中,默认is_active为False不能进行登录。
is_superuser
布尔值。 指定这个用户拥有所有的权限而不需要给他们分配明确的权限。
last_login
用户最后一次登录的时间。
date_joined
账户创建的时间。 当账号创建时,默认设置为当前的date/time。
set_password
(raw_password)设置用户的密码为给定的原始字符串,并负责密码的。 不会保存User
对象。当None
为raw_password
时,密码将设置为一个不可用的密码。
check_password
(raw_password)如果给定的raw_password是用户的真实密码,则返回True,可以在校验用户密码时使用。
管理器方法即可以通过User.objects.
进行调用的方法。
create_user
(username, email=None, password=None, **extra_fields)创建、保存并返回一个User
对象。
create_superuser
(username, email, password, **extra_fields)与create_user()
相同,但是设置is_staff
和is_superuser
为True
。
Django认证系统中提供的用户模型类及方法很方便,我们可以使用这个模型类,但是字段有些无法满足项目需求,如本项目中需要保存用户的手机号,需要给模型类添加额外的字段。
Django提供了django.contrib.auth.models.AbstractUser
用户抽象模型类允许我们继承,扩展字段来使用Django认证系统的用户模型类。
我们现在在meiduo/meiduo_mall/apps
中创建Django应用users,并在配置文件中注册users应用。
在创建好的应用models.py中定义用户的用户模型类。
class User(AbstractUser):
"""用户模型类"""
mobile = models.CharField(max_length=11, unique=True, verbose_name='手机号')
class Meta:
db_table = 'tb_users'
verbose_name = '用户'
verbose_name_plural = verbose_name
我们自定义的用户模型类还不能直接被Django的认证系统所识别,需要在配置文件中告知Django认证系统使用我们自定义的模型类。
在配置文件中进行设置
AUTH_USER_MODEL = 'users.User'
AUTH_USER_MODEL
参数的设置以点.
来分隔,表示应用名.模型类名
。
注意:Django建议我们对于AUTH_USER_MODEL
参数的设置一定要在第一次数据库迁移之前就设置好,否则后续使用可能出现未知错误。
执行数据库迁移
python manage.py makemigrations
python manage.py migrate
创建好用户模型类后,我们开始来实现第一个业务逻辑——用户注册。
分析要实现的业务逻辑,明确在这个业务中需要涉及到几个相关子业务,将每个子业务当做一个接口来设计。
分析接口的功能任务,明确接口的访问方式与返回数据:
在前后端分离的应用模式中,我们作为后端开发人员设计后端接口时,可以不用考虑返回给前端数据后,前端如何处理,这是前端开发人员的工作,我们只需明确我们要保存的或者要返回的是什么数据即可。
明确上述每一点后,即可开始编写接口。
在用户注册中,需要实现以下接口:
图片验证码、短信验证码考虑到后续可能会在其他业务中也用到,因此我们将图片验证码独立,创建一个新应用verifications,在此应用中实现图片验证码、短信验证码。
分析要实现的业务逻辑,明确在这个业务中需要涉及到几个相关子业务,将每个子业务当做一个接口来设计。
分析接口的功能任务,明确接口的访问方式与返回数据:
在前后端分离的应用模式中,我们作为后端开发人员设计后端接口时,可以不用考虑返回给前端数据后,前端如何处理,这是前端开发人员的工作,我们只需明确我们要保存的或者要返回的是什么数据即可。
明确上述每一点后,即可开始编写接口。
在用户注册中,需要实现以下接口:
图片验证码、短信验证码考虑到后续可能会在其他业务中也用到,因此我们将图片验证码独立,创建一个新应用verifications,在此应用中实现图片验证码、短信验证码。