本项目采用前后端分离的方式实现
一.立项
1.首先GIT上创建一个自己的项目
2.进入桌面,将项目克隆下来:git clone git的网址
3.用pycharm打开文件,将静态文件复制到根目录下,并进行提交
git add front_end_pc
git status
git commit -m '上传前端文件'
git push
4.使用前端node.js 提供的服务器live-server作为前端开发服务器使用。
安装node.js的版本控制工具nvm,在终端中执行
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
重新进入终端,使用nvm安装最新版本的node.js
nvm install node
安装live-server
npm install -g live-server
进入前端的文件,输入:live-server就可以进行前端界面的访问(8080端口)
5.创建django项目并安装django restful framework (DRF)
在.virtualenvs中创建项目虚拟环境:mkvirtualenv meiduo_fenghua -p python3
pip install django==1.11.11
pip install djangorestframework
django-admin startproject 项目名称
查找解释器位置:which python
添加解释器给项目
环境中添加runserver后运行manage.py
二.环境配置
1.修改settings.py文件
项目运行有开发环境和生产环境,flask项目通过工厂函数进行分配,django项目通过创建两个settings文件进行环境的区分
将原先的settings.py配置文件进行拆分:一个用于开发环境,一个用于生产环境
在同级目录创建settings包,里边定义两个py文件:dev(开发),prod(生产)
然后更改项目manage.py文件中的meiduo_mall.settings为meiduo_mall.settings.dev
部署的时候在wsgi.py 文件中将meiduo_mall.settings改为meiduo_mall.settings.prod即可
2.创建数据库并指定访问用户
create database meiduo_mall default charset=utf8;
为本项目创建数据库用户(不再使用root账户)
create user meiduo identified by 'meiduo';
grant all on meiduo_mall.* to 'meiduo'@'%';
flush privileges;
说明:
第一句:创建用户账号 meiduo, 密码 meiduo (由identified by 指明)
第二句:授权meiduo_mall数据库下的所有表(meiduo_mall.*)的所有权限(all)给用户meiduo在以任何ip访问数据库的时候('meiduo'@'%')
第三句:刷新生效用户权限
3.配置文件的基本配置
①添加DRF:在INSTALLED_APPS中添加'rest_framework'
②修改mysql数据库:
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 3306, # 数据库端口
'USER': 'meiduo', # 数据库用户名
'PASSWORD': 'meiduo', # 数据库用户密码
'NAME': 'meiduo_mall' # 数据库名字
}
安装pymysql:pip install PyMySQL
在项目同名目录的init文件中将python3的指定成python2的MySQLdb
③ 配置redis数据库(redis和mysql都是CS架构,使用时需要启动服务)
安装redis数据库:pip install django-redis
添加配置信息:
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/0",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
"session": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "session"
④语言和时区
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': 'INFO',
'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': 'INFO', # 日志器接收的最低日志级别
},
}
}
注意:在meiduo_mall中添加logs文件夹,因为是空文件夹,所以创建.gitkeep文件,并在忽略文件中添加logs/*.log,自己的日志不能上传
⑥配置异常()
修改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',
}
三.导包路径说明
查看导包路径的方法:
在dev中
import sys
在BASE_DIR下边
print(sys.path)
['/home/python/Desktop/Meiduo/meiduo_mall','/home/python/Desktop/Meiduo',
'/home/python/.virtualenvs/meiduo_fenghua/lib/python35.zip', '/home/python/.virtualenvs/meiduo_fenghua/lib/python3.5', '/home/python/.virtualenvs/meiduo_fenghua/lib/python3.5/plat-x86_64-linux-gnu', '/home/python/.virtualenvs/meiduo_fenghua/lib/python3.5/lib-dynload', '/usr/lib/python3.5',
'/usr/lib/python3.5/plat-x86_64-linux-gnu', '/home/python/.virtualenvs/meiduo_fenghua/lib/python3.5/site-packages']
REST_FRAMEWORK = {
# 异常处理
'EXCEPTION_HANDLER': 'meiduo_mall.utils.exceptions.exception_handler',
}
从列表得知导包路径有/home/python/Desktop/Meiduo/meiduo_mall,
所以异常处理的导包路径为meiduo_mall.utils.exceptions.exception_handler
还有from XX import XX也一样,上边的列表已经指定了系统配置好的前半段路径,我们只需补充后半段即可。
四.用户模块(注册,登陆)
在meuduo/meiduo_mall/meiduo_mall下创建apps包用来存放所有应用,因为这个目录下就是处理业务逻辑的,而应用就是处理业务的。(等价于flask的moduels)
然后创建应用python ../../ manage.py startapp users
在应用的models文件中创建用户的模型类
django为我们提供了一个原生的用户模型类AbstractUser
INSTALLED_APPS 中的 'django.contrib.auth',就代表使用django默认用户认证系统,我们尽量打开他,用于站点的权限和组。且依赖于session的,所以数据库有一个表django_session,本项目不使用session做状态保持,而是修改默认的认证机制而使用JWT认证!!!!!!!!!!!!!!!我们只使用该机制(该机制很庞大)中的用户模型类AbstractUser
class AbstractUser(AbstractBaseUser, PermissionsMixin):
"""
An abstract base class implementing a fully featured User model with
admin-compliant permissions.
Username and password are required. Other fields are optional.
"""
username_validator = UnicodeUsernameValidator() if six.PY3 else ASCIIUsernameValidator()
username = models.CharField(
_('username'),
max_length=150,
unique=True,
help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
validators=[username_validator],
error_messages={
'unique': _("A user with that username already exists."),
},
)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('email address'), blank=True)
is_staff = models.BooleanField( # 职员
_('staff status'),
default=False,
help_text=_('Designates whether the user can log into this admin site.'),
)
is_active = models.BooleanField( # 激活
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = UserManager() # 管理器
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
abstract = True # 执行migrate时不执行迁移,所以要自定义模型类
def clean(self):
super(AbstractUser, self).clean()
self.email = self.__class__.objects.normalize_email(self.email)
def get_full_name(self):
"""
Returns the first_name plus the last_name, with a space in between.
"""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"Returns the short name for the user."
return self.first_name
def email_user(self, subject, message, from_email=None, **kwargs):
"""
Sends an email to this User.
"""
send_mail(subject, message, from_email, [self.email], **kwargs)
models中定义模型类
from django.contrib.auth.models import AbstractUser
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
因为替换了默认的AbstactUser,所以要重新配置
AUTH_USER_MODEL = 'users.User'
然后注册app
'users.apps.UsersConfig'
为了适应AUTH_USER_MODEL,必须以users开头,所以还要追加导包路径
追加导包路径:/home/python/Desktop/Meiduo/meiduo_mall/meiduo_mall/apps
在BASE_DIR下边写
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
然后进行数据库迁移即可:
python manage.py makemigrations
python manage.py migrate
结论:
AUTH_USER_MODEL = 'users.User'实现数据库中的表的数据维护的是User,否则维护的是原始的AbstractUser