Django - 项目实战
一、项目环境
(1).OS:ubuntu server 16.04 LTS
(2).Django版本:Django 2.0
与1.x最大的区别在于路由。
(3).python:3.6.5 / 3.5
(4).数据库:mysql 5.7
(5).操作数据库的驱动:mysqlclient(安装最新版即可)
这个驱动比pymysql要快。
装不上mysqlclient的话,依次执行下面步骤:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
sudo apt-get update sudo apt-get install libmysql-dev sudo apt-get install libmysqlclient-dev sudo apt-get install python-dev sudo pip install mysqlclient
(6).开发工具:pycharm
二、建好项目
首先分析网站有哪些大板块:新闻列表、课程展示、支付模块,以及还需要一个我们自己的后台管理系统:cms(内容管理系统)
(一).最终的结构
(二).进行配置
(1).static标签“全局化”
这样配置之后,就不需要再在每个模板页面的顶部加"{% load static %}"了。在需要的地方直接写 {% static "xxx.yyy" %} 就可以了。系统已经把这个标签“全局化”了。
(2).static文件夹配置
(3).配置模版文件的路径
上面的(1)中,已经配置好了模板文件夹的路径。就是这行 'DIRS': [os.path.join(BASE_DIR, "templates")],
(4).时区
TIME_ZONE = 'Asia/Shanghai'
(5).设置数据库
(三).遇到的问题及解决方案
(1).阿里云安全组
我们的项目设置的是8000端口,启动服务后,腾讯云没有问题可以直接访问到网站,但是阿里云因为有安全组的存在所有被挡在外面了。
解决方案:先进入控制台,然后进去那台主机对应的安全组里添加规则。
别选错了,是“入方向”!
(2).mysql远程连接的问题
首先得先去安全组里面添加3306的端口。
mysql中的root用户默认是拒绝远程连接,要么改root用户的连接方式:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1.用命令行进入mysql mysql -u root -p 2.user表是在mysql这个数据库中,需要进入mysql这个数据库中 use mysql; 3.执行sql命令 update user set host='%' where user='root' AND host='localhost'; 4.刷新系统权限相关的表 FLUSH PRIVILEGES;
要么添加一个新用户(推荐此操作):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 一、进入mysql操作 # 1.创建普通用户 CREATE USER 'username'@'%' IDENTIFIED BY 'password'; # 2.给普通用户赋权 GRANT ALL ON *.* TO 'username'@'%'; # 3.刷新系统权限相关表 FLUSH PRIVILEGES;
修改mysql的配置文件(必须修改):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 1. vim /etc/mysql/mysql.conf.d/mysqld.cnf # 2. 找到bind-address,把值127.0.0.1 改为 0.0.0.0 # 允许所有IP访问 # 3.重启mysql service mysql restart
三、静态文件制作
先把所有的静态文件都写好,再写后台。也就是看着页面需求,写逻辑。
没什么大问题,这个是已有的网站,HTML、CSS什么的都是照着参考。
这里我写了一些,自己踩到的坑,记录下来,以防忘记。
(一).icon遇到的问题
如果遇到iconfont字体对不齐,一般情况是因为使用了icon的默认大小,设置了过大的iconfont,就会把旁边的字给挤下去。如下图,文字没有水平对齐:
(1).去阿里icon,找到那个图标,点“编辑”
(2).点击放大镜,但不要让图像超出了。然后保存,重新生成CSS
四、发送短信功能
想要给用户发送短信,以个人能力搭建一个这样的服务,是不太容易的。(~你是土豪可以无视了~)
那么就要学会站在巨人的肩膀上嘚瑟,我使用了阿里云的大于短信服务。(原先的大于短信服务,现在已经集成到了阿里云的云通信中)
(一).进入阿里云的官网,找到短信服务
(二).准备工作
(1).创建accesskeys
使用子用户会比较好!我个人理解:道理跟linux的用户权限一样,root权限逆天,我们就创个子账号,让这个子账号拥有sudo权限。这里也是同样的道理。
赋予这个子用户权限,根据自己实际需要来。我为了偷懒,选了AdministratorAccess
权限选了,阿里云才会允许你点"开始创建"。接下来就是填写验证手机短信验证码,通过验证后,就会看到Accesskey了。
记得一定要把这个"AccessKey.csv"文件保存下来,阿里云有很明显的提示:只有一次保存机会!不保存、不记录,你就再也看不到"access_key_secret"的值了。什么~你说没保存!好吧,把上面的流程再走一遍吧~这没办法的~
(2).创建签名
(3).建模板
后续API中,有一个"模板code"的参数要用到,所以必须建好模板。
(4).去下载SDK
去新打开的网页中找到下图这个链接:
(5).安装
先解压,然后cd到解压开的目录中。
选好你的python环境!你项目是用哪个环境的,那就在那个环境下安装。命令:python3 setup.py install
(三).python实现发送短信功能
(1).在这个文件中进行修改
(2).代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import sys import json from aliyunsdkdysmsapi.request.v20170525 import SendSmsRequest from aliyunsdkdysmsapi.request.v20170525 import QuerySendDetailsRequest from aliyunsdkcore.client import AcsClient import uuid from aliyunsdkcore.profile import region_provider from aliyunsdkcore.http import method_type as MT from aliyunsdkcore.http import format_type as FT """ 短信业务调用接口示例,版本号:v20170525 Created on 2017-06-12 """ # 去这个文件里面找 AccessKey.csv # 为了安全,我这里删掉了 ACCESS_KEY_ID = "" ACCESS_KEY_SECRET = "" # 注意:不要更改 REGION = "cn-hangzhou" PRODUCT_NAME = "Dysmsapi" DOMAIN = "dysmsapi.aliyuncs.com" acs_client = AcsClient(ACCESS_KEY_ID, ACCESS_KEY_SECRET, REGION) region_provider.add_endpoint(PRODUCT_NAME, REGION, DOMAIN) def send_sms(phone_numbers, code): __business_id = uuid.uuid1() # 必填,固定的,不要去动它 sign_name = "django....." # 签名管理中去看 template_code = "SMS_......" # 模板code template_param = json.dumps({"code": code}) # 短信服务-模板管理,里面写了什么英文单词,这里就必须一样 # ---------- 这些是阿里云提供的代码了 START ---------- smsRequest = SendSmsRequest.SendSmsRequest() # 申请的短信模板编码,必填 smsRequest.set_TemplateCode(template_code) # 短信模板变量参数 if template_param is not None: smsRequest.set_TemplateParam(template_param) # 设置业务请求流水号,必填。 smsRequest.set_OutId(__business_id) # 短信签名 smsRequest.set_SignName(sign_name) # 短信发送的号码列表,必填。 smsRequest.set_PhoneNumbers(phone_numbers) # 调用短信发送接口,返回json smsResponse = acs_client.do_action_with_exception(smsRequest) return smsResponse # ---------- 这些是阿里云提供的代码了 END ---------- if __name__ == '__main__': send_sms("", "")
(3).项目结构
短信服务属于项目中的工具,它不是MVT中的任何一部分,只是V会用到这个工具。所以单独在项目的根目录中,建一个python包:"utils"
这是个阿里云的服务,未来也许还有其他云的服务,所以要予以区分。在"utils"中,建一个python包:"aliyunsdk"
在"aliyunsdk"中,新建一个py文件
(4).把这个文件夹复制到项目中去
别弄错了!上下两个文件夹长得很像,要复制黏贴的是第二个"aliyunsdkdysmsapi"!发送短信的功能,依赖这个python包。我之前已经丢进去了,所以上面(3)中的图片,已有了这个文件夹。
(5).敲代码
把(2)中的代码复制到你自己新建的py中
(6).去那个需要该短信服务的视图中调用接口
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
def sms_captcha(request): """ 发送短信验证码 :param request: :return: """ import random # 生成纯数字的短信验证码 # 根据实际需要编写验证码,你喜欢纯数字还是字母+数字,取决于你 # 这里我直接偷懒了 rd_code = "".join(map(str, random.sample([i for i in range(9)], 6))) ''' 1.利用列表推导式生成0-9,9个数字 2.random.sample(iterable,__len__) ''' # 通过 /account/sms_captcha/?telephone=188888888888 获取 telephone = request.GET.get("telephone") result = aliyun.send_sms(telephone, code=rd_code) # 真正要发短信需要去调用阿里云的接口 print(telephone, "---", rd_code) print("发送短信功能 : ", result) return HttpResponse("success")
(7).为视图分配路由
(8).先把前端写好
样式自己随意发挥
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<div class="input-group"> <input type="text" class="form-control" name="telephone" placeholder="请输入手机号码"> </div> <span class="sms-captcha-btn">获取短信验证码</span>
(9).编写jquery
jquery获取到前端html文本框中的内容,然后传给后端
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// 点击发送短信验证码 $(function () { var smsCaptcha = $(".sms-captcha-btn"); function send_sms() { // let telephone = document.getElementById("telephone").value; let telephone = $('input[name="telephone"]').val(); $.get({ // "url": "/account/sms_captcha/?telephone=" + telephone, "url": "/account/sms_captcha/", 'telephone': telephone, // 把数据放在data里面,是jquery推荐的。浏览器也能查看到 "data": { "telephone": telephone, }, 'success': function (result) { let count = 10; let timer = setInterval(function () { smsCaptcha.addClass("disabled"); smsCaptcha.unbind("click"); smsCaptcha.text(count); count--; if (count <= 0) { clearInterval(timer); smsCaptcha.text("获取短信验证码"); smsCaptcha.removeClass("disabled"); smsCaptcha.click(send_sms); } }, 1000); }, 'fail': function (error) { console.log(error); }, }); } smsCaptcha.click(send_sms); });
代码中用到了ajax,记住:ajax功能一定要在服务启动时才能生效。
八、七牛云的使用
favicon.ico
favicon.ico就是网站的小logo,位于下图红色箭头所指处:
(一).准备一张.ico图片
(二).把ico图片放进/static/下(代码在Linux跑的话,记得同步)
(三).修改总路由文件urls.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 这是与settings.py同级的总路由 ...其余代码略... from django.views.generic.base import RedirectView urlpatterns = [ ...其余代码略... path("favicon.ico", RedirectView.as_view(url=settings.STATIC_URL + "logo.ico")), ]
项目部署
(一).描述
发布项目是不会把代码放在Linux的用户目录下,一般迁移到 /srv/ 下。
命令:mv tzxfz /srv/tzxfz 直接把整个项目移到 /srv/ 下。
(二).设置收集静态文件的文件夹
settings.py中,加入这个设置:STATIC_ROOT = "/static_dist/" 用于收集静态文件。
收集静态文件命令:python manage.py collectstatic
(三).安装uwsgi
uwsgi是一个应用服务器,非静态文件的网络请求就必须通过他完成,他也可以充当静态文件服务器,但不是他的强项。
uwsgi是使用python编写的,因此通过 pip install uwsgi 就可以了。注意:uwsgi必须安装在系统级别的Python环境中,不要安装到虚拟环境中!
(1).在项目的根目录下,创建一个文件 tzxfz_uwsgi.ini
(2).编写这个配置文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
[uwsgi] # 这个别忘了 chdir = /srv/tzxfz # Django的wsgi文件,绝对路径 module = /srv/tzxfz/tzxfz/wsgi.py # Python虚拟环境的路径 home = /root/.virtualenvs/django-env # 进程相关的设置 # 主进程 master = true # 最大数量的工作进程 processes = 10 # socket文件路径,绝对路径(任何地方都可以,只要有权限就行) socket = /tmp/tzxfz.sock # 设置socket的权限 chmod-socket = 666 # 退出的时候是否清理环境 vacuum = true
(3).然后使用命令 uwsgi --ini tzxfz.ini 看下是否还能启动这个项目。
(四).安装nginx
nginx是一个web服务器。用来加载静态文件和接收http请求的。
(1).通过命令 sudo apt install nginx 进行安装。
(2).编写nginx配置文件
在 /etc/nginx/conf.d 目录下,新建一个文件 tzxfz.conf
(3).编辑这个文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
upstream tzxfz { server unix:///tmp/tzxfz.sock; } # 配置服务器 server { # 监听的端口号 listen 80; # 域名 server_name 118.24.0.251; charset utf-8; # 最大的文件上传尺寸 client_max_body_size 75M; # 静态文件访问的url location /static { # 静态文件地址 alias /srv/tzxfz/static_dist; } # 最后,发送所有非静态文件请求到django服务器 location / { uwsgi_pass tzxfz; # uwsgi_params文件地址 include /etc/nginx/uwsgi_params; } }
(4).运行命令:service nginx configtest 如果不报错,右边有了[OK],说明成功。
(5).nginx常用命令
启动nginx:service nginx start
关闭nginx:service nginx stop
重启nginx:service nginx restart
部分技巧
(一).根据app之间的依赖关系,分别进行迁移
从一台服务器迁移到另外一台服务器,有时候makemigrations的时候会报错误,大意是无xxx模块的引入。
大致原因:其他app需要依赖一个"顶级"app,如下图的apps结构所示,account是账号的app,而且app都引用依赖了这个account。如果account没有迁移过去,而其他app先行过去了,导致找不到account,所以就会报错,提示无法找到xxx模块。
解决办法:
手动迁移,先要把顶级依赖的model给makemigrations过去,然后migrate让其生效,再依次迁移其他的模块。