# tracer **Repository Path**: srls/tracer ## Basic Information - **Project Name**: tracer - **Description**: 项目追踪 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 6 - **Forks**: 0 - **Created**: 2020-07-15 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 1. SAAS ## 一、涉及知识点 ### 1、虚拟环境 ``` py3: django 1.11版本 -> crm项目 [维护] django 2.0 版本 -> tracer项目 [新开发] 虚拟环境: - 虚拟1: py3 纯净,django1.11 - 虚拟2: py3 纯净,django2.0 ``` ### 2、local_settings.py本地配置 ``` 你是开发(你): 连接数据库需要在django的settings中设置,链接数据库IP:1.1.1.1 我是测试(我): 连接数据库需要在django的settings中设置,链接数据库IP:1.1.1.2 ``` ```python # settings.py try: from .local_settings import * except ImportError: ... ``` ```python #local_settings.py LANGUAGE_CODE = 'zh-hans' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': "1.1.1.1", } } ``` 除了local_settings.py,其他文件交给测试,测试自己写一个local_settings.py ```python #local_settings.py LANGUAGE_CODE = 'zh-hans' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': "1.1.1.2", } } ``` ### 3、腾讯云平台 > SMS短信,申请服务 - API,提供URL让你去访问,并根据提示传参数 ``` request.get("http://www.xxx.com/adf/jki/", json={....}) ``` - SDK,模块,下载安装模块,基于模块完成功能 ``` - sms.py 模块封装好函数,调用即可 def func(): return request.get("http://www.xxx.com/adf/jki/", json={....}) ``` ``` pip install sms ``` ```python import sms sms.func() ``` > COS对象存储,腾讯提供云硬盘,项目中上传/查看/下载文件。 ``` 使用服务器的硬盘上传/查看/下载文件,会很慢 ``` ### 4、redis(6379) ``` MySQL: 自己的电脑 另外一台电脑 pymysql模块 -> MySQL软件 -> 行为: (硬盘文件操作) create table 创建表(创建文件) insert into 表插入(写入记录) Redis: 自己的电脑 另外一台电脑 redis模块 -> Redis软件 -> 行为: (内存操作) set name="lxx" 10s , 在内存中 get name , 在内存中获取name对应值 超时时间 # 注意:1台电脑也可以操作 ``` #### 4.1 安装redis **linux --> deepin:** ``` 1. 安装命令 sudo apt-get install redis-server 2. 启动服务 /etc/init.d/redis-server start 或 systemctl start redis-server 3. 停用服务 /etc/init.d/redis-server stop 或 systemctl stop redis-server 4. 重启服务 /etc/init.d/redis-server restart 或 systemctl restart redis-server 5. 检查redis服务器系统进程 ps -aux|grep redis 6. 查看redis端口状态 netstat -nlt|grep 端口号 7. 查看服务状态 systemctl status redis-server ``` ``` 1. 查看已安装软件的可执行程序位置(以redis为例) 命令: which redis-server 结果: /usr/bin/redis-server 2. 查看已安装软件可执行程序的多个版本及man帮助文档的位置 命令: whereis redis-server 结果: redis-server: /usr/bin/redis-server /usr/share/man/man1/redis-server.1.gz 3. 查询完整的所有软件安装的文件及路径 命令: dpkg -L redis-server 结果: /. /etc /etc/default /etc/default/redis-server /etc/init.d /etc/init.d/redis-server /etc/logrotate.d /etc/logrotate.d/redis-server /etc/redis /etc/redis/redis.conf /lib /lib/systemd /lib/systemd/system /lib/systemd/system/redis-server.service /lib/systemd/system/redis-server@.service /usr /usr/bin /usr/share /usr/share/doc /usr/share/doc/redis-server /usr/share/doc/redis-server/MANIFESTO.gz /usr/share/doc/redis-server/NEWS.Debian.gz /usr/share/doc/redis-server/README.md.gz /usr/share/doc/redis-server/changelog.Debian.gz /usr/share/doc/redis-server/changelog.gz /usr/share/doc/redis-server/copyright /usr/share/man /usr/share/man/man1 /usr/share/man/man1/redis-server.1.gz /usr/bin/redis-server /usr/share/doc/redis-server/00-RELEASENOTES.gz 4. 使用搜索命令来进行查询 命令: sudo find /usr -name "redis-server" 结果: /usr/share/doc/redis-server /usr/bin/redis-server ``` ### 5、django使用mysql数据库(3306) #### 5.1 安装mysql #### 5.2 创建表 - settings.py中设置连接MySQL ```python DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': "tracer", 'USER': 'root', 'PASSWORD': '123456', 'HOST': '127.0.0.1', 'PORT': '3306', } } ``` - 编写模型类 ```python # 1. 编写模型类 class UserInfo(models.Model): username = models.CharField(verbose_name='用户名',max_length=32, db_index=True) # db_index=Ture 创建索引 email = models.EmailField(verbose_name="邮箱",max_length=32) mobile_phone = models.CharField(verbose_name="手机号", max_length=32) password = models.CharField(verbose_name="密码", max_length=32) ``` - 消除版本问题 ![](./files/create_table_1.png) - 将模型类转换为mysql表 ``` python manage.py makemigrations # 将类转换为数据表结构 python manage.py migrate # 根据上一句代码生成数据表 ``` # 2. 项目开发 - 一期:用户认证(短信认证、图片验证码、django ModelForm组件) -> 三天 - 二期:wiki、文件、问题管理 -> 1+2+2=5天 - 三期:支付、部署(linux基础) -> 2天 ## 一、day01 前戏 ### 今日概要 - 虚拟环境(项目环境) - 项目框架:local_settings - git实战应用(代码每天提交) - 通过python & 腾讯SMS发送短信 ### 今日详情 #### 1.虚拟环境virtualenv 1.1 安装 ``` pip3 install virtualenv ``` 1.2 创建虚拟环境 ``` virtualenv 环境名称 --python=python3.6 virtualenv 环境名称 --python='C:\python\python3.6.exe' # 注意:创建 [环境名称] 文件夹,放置所有的环境。例如:指定[D:\envs]放置所有虚拟环境 ``` ``` 1. 打开终端 2. 安装 virtualenv pip3 install virtualenv pip install virtualenv -i http://pypi.douban.com/simple 3. 关闭终端,再重新打开 4. 通过命令进入指定目录 win: >>>D: 切换到D盘 >>>dir 罗列当前目录下所有文件(夹) >>>cd envs 进入指定目录 linux: >cd envs 进入指定目录 >ls -la 罗列当前目录下所有文件(夹) 5. 创建虚拟环境 virtualenv env_name ``` 1.3 激活、退出虚拟环境 ``` # 激活 win: >>>cd Scripts 进入虚拟环境Scripts目录 >>>activate.exe 激活虚拟环境 linux: >source env_name/bin/activate # 退出 win: >>>cd Scripts 进入虚拟环境Scripts目录 >>>deactivate.exe 退出虚拟环境 linux: >deactivate ``` 1.4 在虚拟环境安装模块 ``` pip3 install django==1.11.7 pip3 install django==1.11.7 -i http://pypi.douban.com/simple --trusted-host ``` ``` # 将本虚拟环境中的模块及版本信息保存到requirements.txt文件中 pip freeze > requirements.txt # 安装requirements.txt中的所有模块 pip install -r requirements.txt ``` #### 2. 搭建项目环境 ``` django + 虚拟环境 ``` #### 3. 本地配置 ``` # settings.py try: from .local_settings import * except ImportError: ... ``` ``` #local_settings.py LANGUAGE_CODE = 'zh-hans' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': "1.1.1.1", } } ``` #### 4. 给别人代码 ##### 4.1 创建一个远程仓库 ![](./files/git_step1.png) ##### 4.2 本地代码推送到git - 让git忽略一些文件,创建 .gitignore 文件 ``` # git共享代码时,需要忽略,不进行上传的文件 # pycharm .idea/ .DS_Store __pycache__/ *.py[cod] *$py.class # Django stuff: local_settings.py *.sqlite3 media/ # database migrations */migrations/*.py !*/migrations/__init__.py ``` - git项目管理 ``` (web_env) licartu@licartu-PC:~/workSpace/python/web/django/tracer$ git config --global user.name "**nameUJIO" (web_env) licartu@licartu-PC:~/workSpace/python/web/django/tracer$ git config --global user.email "fsdfsd@163.com" (web_env) licartu@licartu-PC:~/workSpace/python/web/django/tracer$ git init 已初始化空的 Git 仓库于 /home/licartu/workSpace/python/web/django/tracer/.git/ (web_env) licartu@licartu-PC:~/workSpace/python/web/django/tracer$ git add . (web_env) licartu@licartu-PC:~/workSpace/python/web/django/tracer$ git commit -m '第一次提交'[master(根提交) b8d4926] 第一次提交 8 files changed, 219 insertions(+) create mode 100644 .gitignore create mode 100644 1.1.1.1 create mode 100755 manage.py create mode 100644 tracer/__init__.py create mode 100644 tracer/asgi.py create mode 100644 tracer/settings.py create mode 100644 tracer/urls.py create mode 100644 tracer/wsgi.py ``` - git本地项目推送远程仓库 ``` (web_env) licartu@licartu-PC:~/workSpace/python/web/django/tracer$ git push https://gitee.com/srls/tracer.git master 枚举对象: 10, 完成. 对象计数中: 100% (10/10), 完成. 使用 6 个线程进行压缩 压缩对象中: 100% (9/9), 完成. 写入对象中: 100% (10/10), 2.96 KiB | 2.96 MiB/s, 完成. 总共 10 (差异 1),复用 0 (差异 0) remote: Powered by GITEE.COM [GNK-5.0] To https://gitee.com/srls/tracer.git * [new branch] master -> master ``` ``` # 为 https://gitee.com/srls/tracer.git 创建一个名字 origin git remote add origin https://gitee.com/srls/tracer.git git push origin master ``` ##### 4.3 测试获取代码 ``` git clone https://gitee.com/srls/tracer.git ``` ## 二、day02 ### 今日概要 - 腾讯SMS发送短信 - Django的ModelForm组建 - redis - 注册逻辑设计 - 开发 ### 今日详情 #### 1. 腾讯发送短信 具体实现参考 “腾讯云短信.md” - 注册 - 登陆 - 找回密码 #### 2. Django的ModelForm - 自动生成标签 #### 3.下一步思路 - 点击获取验证码 - 获取手机号 - 想后台发送ajax - 手机 - tpl=register - 向手机发送验证码 - 验证码失效处理 60s #### 4. 使用redis - 方法1(推荐) ``` # 第一步:安装django-reids模块 pip install django-redis # 第二步:在django项目的settings.py文件中添加相关配置 CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://10.211.55.28:6379", # 安装redis的主机的 IP 和 端口 "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", "CONNECTION_POOL_KWARGS": { "max_connections": 1000, "encoding": 'utf-8' }, "PASSWORD": "foobared" # redis密码 } } } ``` [redis教程的链接](https://pythonav.com/wiki/detail/10/82/ "redis教程") ```python # 第三步:在django的视图中操作redis from django.shortcuts import HttpResponse from django_redis import get_redis_connection def index(request): # 去连接池中获取一个连接 conn = get_redis_connection("default") conn.set('nickname', "武沛齐", ex=10) value = conn.get('nickname') print(value) return HttpResponse("OK") ``` - 方法2 ``` # 安装redis模块 pip install redis ``` ```python import redis # 连接redis conn = redis.Redis(host="127.0.0.1", port=6379, password="123456", encoding="utf-8") # 设置键值: 15235123564="9999" 且超时时间为100秒, redis保存成 “9999”的字节 conn.set("15235123564", 9999, ex=100) # 根据键获取值,如果不存在,则返回 None value = conn.get("15235123564") print(value) ``` ## 三、day03 用户认证 ### 今日概要 - 注册 - 短信验证码登陆 - 用户名密码登陆 ### 今日详情 #### 1. 实现注册 ##### 1.1 创建 web 应用 ``` # 第一步:创建name为“web”的app python manage.py startapp web # 第二步:settings.py中进行注册 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', 'web.apps.WebConfig' ] ``` ##### 1.2 点击获取验证码 - 按钮绑定点击事件 - 获取手机号 - 发送ajax - 手机号校验 - 不能为空 - 格式正确 - 没有注册过 - 验证通过 - 发送信息 - 将验证码保存到redis中 - 成功与失败 - 失败 --> 错误信息 - 成功 --> 倒计时 - disabled属性 ```javascript $("#btnSms").prop("disabled", true); // 添加disabled属性,不可操作 $("#btnSms").prop("disabled", false); // 移除disabled属性,可以操作 ``` - 定时器 ```javascript var time = 60; var obj = setInterval(function(){ time = time -1; if (time < 1) { clearInterval(obj); } }, 1000); ``` ### 内容总结 - 视图 view.py -> views目录 - 模板,根目录templates -> 根据APP注册顺序去每个APP的templates中 - 静态文件,同上 static - 项目中多个APP且想要各自模板、静态文件隔离,建议通过APP名称再进行嵌套即可 - 路由分发 - include - name - 母版 ``` title css content js ``` - bootstrap导航条 - ModelForm生成HTML标签,自动ID(id_字段名) - 发送ajax请求 ``` $.ajax({ url: "{% url 'send_sms' %}", // url: '/send/sms/' type: "GET", data: {}, dataType: 'JSON', // 将服务器返回的数据反序列化为字典 success: function (res) { console.log(res); } }); ``` - Form & ModelForm 可以进行表单验证 ```python form = SendSmsForm(data=request.POST) form = SendSmsForm(data=request.GET) ``` - Form & ModelForm 中如果想要用视图中的值(request) ```python lass SendSMSForm(forms.Form): mobile_phone = forms.CharField(label='手机号', validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$','手机号格式错误')]) def __init__(self, request, *args, **kwargs): super().__init__(*args, **kwargs) self.request = request ``` - 短信 - redis (django-redis) - 倒计时 ## 四、day04 ### 今日概要 - 点击注册 - 用户登录 - 短信验证码登录 - 手机 or 邮箱 / 密码登录 - 项目管理(创建&星标) ### 今日详情 #### 1. 点击注册 ##### 1.1 点击收集 & ajax ##### 1.2 数据校验(每个字段) ##### 1.3 写入数据库 #### 2. 短信登录 ##### 2.1 展示界面 ##### 2.2 点击发送短信 ##### 2.3 点击登录 #### 3.用户名 / 密码登录 ##### 3.1 Python生成图片+写文字 https://www.cnblogs.com/wupeiqi/articles/5812291.html ``` # 安装python的pillow模块 pip install pillow ``` ```python # 1. 创建图片 from PIL import Image img = Image.new(mode='RGB', size=(120,30), color=(255,255,255)) # 在图片查看器中打开 img.show() # 保存到本地 with open('code.png', mode='wb') as f: img.save(f, format='png') ``` ```python # 2. 创建画笔,用于在图片上画任意内容 img = Image.new(mode='RGB', size=(120,30), color=(255,255,255)) draw = ImageDraw.Draw(img, mode='RGB') ``` ```python # 3. 画点 img = Image.new(mode='RGB', size=(120,30), color=(255,255,255)) draw = ImageDraw.Draw(img, mode='RGB') # 第一个参数:表示坐标 # 第二个参数:表示颜色 draw.point([100,100], fill='red') draw.point([100,100], fill=(255,240,230)) ``` ```python # 4. 画线 img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255)) draw = ImageDraw.Draw(img, mode='RGB') # 第一个参数:表示起始坐标和结束坐标 # 第二个参数:表示颜色 draw.line((100,100,100,300), fill='red') draw.line((100,100,300,100), fill=(255, 255, 255)) ``` ```python # 5. 画圆 img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255)) draw = ImageDraw.Draw(img, mode='RGB') # 第一个参数:表示起始坐标和结束坐标(圆要画在其中间) # 第二个参数:表示开始角度 # 第三个参数:表示结束角度 # 第四个参数:表示颜色 draw.arc((100,100,300,300),0,90,fill="red") ``` ```python # 6. 写文本 img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255)) draw = ImageDraw.Draw(img, mode='RGB') # 第一个参数:表示起始坐标 # 第二个参数:表示写入内容 # 第三个参数:表示颜色 draw.text([0,0],'python',"red") ``` ```python # 7. 写特殊字体 img = Image.new(mode='RGB', size=(120, 30), color=(255, 255, 255)) draw = ImageDraw.Draw(img, mode='RGB') # 第一个参数:表示字体文件路径 # 第二个参数:表示字体大小 font = ImageFont.truetype("kumo.ttf", 28) # 第一个参数:表示起始坐标 # 第二个参数:表示写入内容 # 第三个参数:表示颜色 # 第四个参数:表示颜色 draw.text([0, 0], 'python', "red", font=font) ``` ```python # 图片验证码 import random from PIL import Image, ImageDraw, ImageFilter, ImageFont def check_code(width=120, height=30, char_length=5, font_file='Monaco.ttf', font_size=28): code = [] img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255)) draw = ImageDraw.Draw(img, mode='RGB') def rndChar(): """ 生成随机字母 """ return chr(random.randint(65, 90)) def rndColor(): """ 生成随机颜色 """ return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255)) # 写文字 font = ImageFont.truetype(font_file, font_size) for i in range(char_length): char = rndChar() code.append(char) h = random.randint(0, 4) draw.text([i * width / char_length, h], char, font=font, fill=rndColor()) # 写干扰点 for i in range(40): draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor()) # 写干扰圆圈 for i in range(40): draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor()) x = random.randint(0, width) y = random.randint(0, height) draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor()) # 画干扰线 for i in range(5): x1 = random.randint(0, width) y1 = random.randint(0, height) x2 = random.randint(0, width) y2 = random.randint(0, height) draw.line((x1, y1, x2, y2), fill=rndColor()) img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) return img, ''.join(code) if __name__ == '__main__': # 1. 直接打开 # img,code = check_code() # img.show() # 2. 写入文件 # img,code = check_code() # with open('code.png','wb') as f: # img.save(f,format='png') # 3. 写入内存(Python3) # from io import BytesIO # stream = BytesIO() # img, code = check_code() # img.save(stream, 'png') # stream.getvalue() # 4. 写入内存(Python2) # import StringIO # stream = StringIO.StringIO() # img, code = check_code() # img.save(stream, 'png') # stream.getvalue() pass ``` ##### 3.2 Session & Cookie ##### 3.3 页面显示 ##### 3.4 登录 ## 五、day5 ### 今日概要 - django写离线脚本 - 设计表结构 - 我的表结构 - 功能实现 - 查看项目列表 - 创建项目 - 星标项目 ### 今日详情 #### 1. django离线脚本 ``` django,框架 离线,非web运行时 脚本,一个或几个py文件 ``` 在某个py文件中对django项目做一些处理 > **示例1:**使用离线脚本在用户表插入数据 ```python # 离线脚本 import django import os import sys base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(base_dir) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "tracer.settings") # 模拟django启动 django.setup() # 读取 os.environ["DJANGO_SETTINGS_MODULE"] from web import models models.UserInfo.objects.create(username="陈硕", email='chenshuo@live.com', mobile_phone='13654563215', password="12345678") ``` > **示例2:**数据库录入全国省市县信息 > **示例3:**朋友圈项目 ``` 文本审核 --> 敏感字、词语的屏蔽 ``` > **示例4:**SAAS免费版 :1G、5项目、10人 #### 2. 探讨业务 ##### 2.1 价格策略 | ID | 分类 | 标题 | 价格/年 | 项目个数 | 项目成员 | 每个项目空间 | 单文件 | 创建时间 | | :--: | :----: | :--------: | :-----: | :------: | :------: | :----------: | :----: | :------: | | 1 | 免费版 | 个人免费版 | 0 | 3 | 2 | 20M | 5M | | | 2 | 收费版 | VIP | 199 | 20 | 100 | 50G | 500M | | | 3 | 收费版 | SVIP | 299 | 50 | 200 | 100G | 1G | | | 4 | 其他 | | | | | | | | 注意:新用户注册拥有免费版的额度。 ##### 2.2 用户 | ID | 用户名 | 手机号 | 邮箱 | 密码 | | :--: | :-------: | :---------: | :---------------: | :-----------: | | 1 | alex | 13612345678 | alex@live.com | alex1111 | | 2 | xiaoming | 13645632156 | xiaoming@live.com | xiaoming1111 | | 3 | xiaoliang | 13656325698 | xiaohua@live.com | xiaohua111111 | ##### 2.3 交易 | ID | 状态 | 用户 | 价格 | 实际支付 | 开始 | 结束 | 数量(年) | 订单号 | | :--: | :----: | :--: | :--: | :------: | :--------: | :--------: | :--------: | :----: | | 1 | 已支付 | 1 | 1 | 0 | 2020-07-23 | null | 0 | ddh01 | | 2 | 已支付 | 2 | 1 | 0 | 2020-07-23 | null | 0 | ddh02 | | 3 | 已支付 | 3 | 1 | 0 | 2020-07-23 | null | 0 | ddh03 | | 4 | 已支付 | 2 | 2 | 199 | 2020-10-23 | 2021-10-23 | 1 | ddh04 | | 5 | 已支付 | 3 | 3 | 299*2 | 2020-10-25 | 2022-10-25 | 2 | ddh05 | ##### 2.4 创建存储 基于腾讯对象存储COS存储数据。 ##### 2.5 项目 | ID | 项目名称 | 描述 | 颜色 | 星标 | 参与人数 | 创建者 | 已使用空间 | | ---- | ---------- | ---- | ----- | ----- | -------- | ------ | ---------- | | 1 | 灵笼 | ... | #dddd | true | 5 | 3 | 5M | | 2 | 刺客伍六七 | ... | #uuu7 | false | 10 | 3 | 1G | | 3 | 罗小黑战记 | ... | #uu97 | false | 20 | 2 | 2G | ##### 2.6 项目参与者 | ID | 项目 | 用户 | 星标 | | ---- | ---- | ---- | ----- | | 1 | 1 | 1 | true | | 2 | 1 | 2 | false | | 3 | 2 | 3 | true | #### 3. 任务 ##### 3.1 创建表结构 ##### 3.2 离线脚本创建价格策略【免费版】 ![image-20200725150214021](/home/licartu/.config/Typora/typora-user-images/image-20200725150214021.png) ##### 3.3 用户注册【改】 - 之前:注册成功只是新建用户 - 现在: - 新建用户 - 新建交易记录【免费版】 ##### 3.4 新建项目 ##### 3.5 展示项目 ##### 3.6 星标项目 ## 六、day6 ### 今日详情 #### 1. 表结构 ```python from django.db import models # Create your models here. """ 用户信息 """ class UserInfo(models.Model): username = models.CharField(verbose_name='用户名',max_length=32, db_index=True) # db_index=Ture 创建索引 email = models.EmailField(verbose_name="邮箱",max_length=32) mobile_phone = models.CharField(verbose_name="手机号", max_length=32) password = models.CharField(verbose_name="密码", max_length=32) """ 价格策略 """ class PricePolicy(models.Model): category_choices = ( (1, '免费版'), (2, '收费版'), (3, '其他'), ) categoty = models.SmallIntegerField(verbose_name='收费类型', default=2, choices=category_choices) title = models.CharField(verbose_name='标题', max_length=32) price = models.PositiveIntegerField(verbose_name='价格') project_num = models.PositiveIntegerField(verbose_name='项目数') project_member = models.PositiveIntegerField(verbose_name='项目成员数') project_space = models.PositiveIntegerField(verbose_name='单项目空间') per_file_size = models.PositiveIntegerField(verbose_name='单文件大小(M)') create_datetime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) """ 交易记录 """ class Transaction(models.Model): status_choice = ( (1, '未支付'), (1, '已支付'), ) status = models.SmallIntegerField(verbose_name='状态', choices=status_choice) order = models.CharField(verbose_name='订单号', max_length=64, unique=True) user = models.ForeignKey(verbose_name='用户', to='UserInfo', on_delete=models.CASCADE) price_policy = models.ForeignKey(verbose_name='价格策略', to='PricePolicy', on_delete=models.CASCADE) count = models.IntegerField(verbose_name='数量(年)', help_text='0表示无限期') price = models.IntegerField(verbose_name='实际支付价格') start_datetime = models.DateTimeField(verbose_name='开始时间', null=True, blank=True) end_datetime = models.DateTimeField(verbose_name='结束时间', null=True, blank=True) create_datetime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) """ 项目表 """ class Project(models.Model): COLOR_CHOICES = ( (1, '#56b8eb'), (2, '#f28033'), (3, '#ebc656'), (4, '#a2d148'), (5, '#20bfa4'), (6, '#7461c2'), (7, '#20bfa3'), ) name = models.CharField(verbose_name='项目名', max_length=32) color = models.SmallIntegerField(verbose_name='颜色', choices=COLOR_CHOICES, default=1) desc = models.CharField(verbose_name='项目描述', max_length=255, null=True, blank=True) use_space = models.IntegerField(verbose_name='项目已使用空间', default=0) star = models.BooleanField(verbose_name='星标', default=False) join_count = models.SmallIntegerField(verbose_name='参与人员', default=1) creator = models.ForeignKey(verbose_name='创建者', to='UserInfo', on_delete=models.CASCADE) create_datetime = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) # 查询:可以省事 # 增加,删除,修改:无法完成 # project_user = models.ManyToManyField(to='UserInfo', through='ProjectUser', through_fields=('project','user')) """ 项目参与者 """ class ProjectUser(models.Model): # user = models.ForeignKey(verbose_name='参与者', to='UserInfo', related_name="a") project = models.ForeignKey(verbose_name='项目', to='Project', on_delete=models.CASCADE) user = models.ForeignKey(verbose_name='参与者', to='UserInfo', on_delete=models.CASCADE) star = models.BooleanField(verbose_name='星标', default=False) # invitee = models.ForeignKey(verbose_name='邀请者', to='UserInfo', related_name="b") create_datetime = models.DateTimeField(verbose_name='加入时间', auto_now_add=True) ``` #### 2. 离线脚本 ## 七、 day7 ### 今日概要 - 展示项目 - 星标项目 - 添加项目:颜色选色 - 项目切换 & 项目管理菜单处置 - wiki管理 ### 今日详情 #### 1. 展示项目 ``` 1. 从数据库中获取两部分数据 我创建的所有项目:已星标、未星标 我参与的所有项目:已星标、未星标 2. 提取已星标项目 列表 = 循环 [我创建的所有项目] + [我参与的所有项目] 把已星标的数据提取 得到三个列表:星标、我创建、我参与 ``` #### 2. 星标 & 移除星标 ##### 2.1 星标 ``` 我创建的项目:Project的star=True 我参与的项目:ProjectUser的Project的star=True ``` ##### 2.2 移除星标 ``` 我创建的项目:Project的star=False 我参与的项目:ProjectUser的Project的star=False ``` #### 3. 选择颜色 ##### 3.1 部分样式应用BootStrap ```python class BootStrapForm(object): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for name, field in self.fields.items(): field.widget.attrs['class'] = 'form-control' field.widget.attrs['placeholder'] = '请输入{}'.format(field.label) ``` ```python class ProjectModelForm(BootStrapForm, forms.ModelForm): # desc = forms.CharField(widget=forms.Textarea()) # color字段不应用BootStrapForm样式 bootstrap_class_exclude = ['color'] class Meta: model = models.Project fields = "__all__" widgets = { 'desc': forms.Textarea } ``` ##### 3.2 自定制颜色选择插件 #### 4. 切换菜单 ``` 1. 数据库中获取 我创建的: 我参与的: 2. 循环显示 3. 当前页面需要显示 / 其他页面也需要显示 [inclusion_tag] ``` #### 5. 项目管理 ``` /manage/项目ID/dashboard /manage/项目ID/issues /manage/项目ID/statistics /manage/项目ID/file /manage/项目ID/wiki /manage/项目ID/setting ``` ##### 5.1 进入项目展示菜单