用户管理中心
- django写离线脚本
- 非web运行时的一个或者几个py文件
- 探讨业务(表结构)
- 价格策略
- 用户和价格策略的关联关系
- 基于腾讯的对象存储COS存储数据
- 项目参与者
- 价格策略
创建表结构
models.py
class UserInfo(models.Model):
username = models.CharField(verbose_name='用户名', max_length=32, db_index=True) # 创建索引
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, "其他"),
)
category = models.SmallIntegerField(verbose_name="收费类型", choices=category_choices, default=1)
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_choices = (
(1, "未支付"),
(2, "已支付"),
)
status = models.SmallIntegerField(verbose_name="支付状态", choices=status_choices)
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,"#a2b148"),
(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)
class ProjectUser(models.Model):
"""项目参与者"""
user = models.ForeignKey(verbose_name="参与者",to="UserInfo",on_delete=models.CASCADE)
project = models.ForeignKey(verbose_name="项目",to="Project",on_delete=models.CASCADE)
star = models.BooleanField(verbose_name="星标",default=False)
create_datetime = models.DateTimeField(verbose_name="加入时间",auto_now_add=True)
离线脚本创建价格策略[免费版]
scripts/baes.py:
import os
import sys
import django
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(base_dir)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Sass.settings")
django.setup() # os.environ['DJANGO_SETTINGS_MODULE']
scripts/init_price_policy.py
"""价格离线脚本【免费版】"""
import base
from web import models
def run():
exists = models.PricePolicy.objects.filter(category=1,title="个人免费版").exists()
if not exists:
models.PricePolicy.objects.create(
category=1,
title="个人免费版",
price=0,
project_num=3,
project_member=2,
project_space=20,
per_file_size=5
)
if __name__ == '__main__':
run()
运行之后会在数据库添加一行数据
用户注册【改】
- 之前:注册成功只是新建用户
- 现在:新建用户、新建交易记录【免费版】
新建项目
1.项目列表母板 + 样式
- 后台:登录成功才可以访问
- 官网:不管登录都可以访问
2.添加
manage.html
<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %} {% endblock %}</title>
<link rel="stylesheet" href="{% static 'plugin/bootstrap-3.4.1/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'plugin/font-awesome-4.7.0/css/font-awesome.min.css' %}">
<link rel="stylesheet" href="{% static 'css/manage.css' %}">
<style>
.navbar-av {
border-radius: 0;
}
.error-msg{
color: red;
position: absolute;
font-size: 13px;
}
</style>
{% block css %} {% endblock %}
</head>
<body>
<nav class="navbar navbar-av">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{% url 'project_list' %}">Tracer</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="dropdown active">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false"><span class="glyphicon glyphicon-th-list" aria-hidden="true"></span> 项
目<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><a href="#">工作台</a></li>
<li><a href="#">日 历</a></li>
<li><a href="#"><span class="glyphicon glyphicon-bell" aria-hidden="true"></span></a></li>
<li><a href="#"><span class="glyphicon glyphicon-bookmark" aria-hidden="true"></span></a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false"><span class="glyphicon glyphicon-user"
aria-hidden="true"></span> {{ request.tracer.user.username }}<span
class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="{% url 'index' %}">官网首页</a></li>
<li role="separator" class="divider"></li>
<li><a href="{% url 'layout' %}"><span class="glyphicon glyphicon-off"
aria-hidden="true"></span> 退 出</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
{% block content %}{% endblock %}
<script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
<script src="{% static 'plugin/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
{% block js %} {% endblock %}
</body>
</html>
project_list.html
{% extends 'layout/manage.html' %}
{% block css %}
<style>
.project {
margin-top: 10px;
}
</style>
{% endblock %}
{% block content %}
<div class="container-fluid project">
<a class="btn btn-primary" data-toggle="modal" data-target="#addModal"><span
class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span> 新建项目</a>
</div>
<!-- Modal -->
<div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">新建项目</h4>
</div>
<div class="modal-body">
<form id="addForm">
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{{ field }}
<span class="error-msg"></span>
</div>
{% endfor %}
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取 消</button>
<button type="button" class="btn btn-primary" id="btnSubmit">保 存</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block js %}
<script>
$(function (){
bindSubmit();
})
/*
点击提交项目按钮事件
*/
function bindSubmit(){
$("#btnSubmit").click(function (){
$.ajax({
uri:"{% url 'project_list' %}",
type:"POST",
data:$("#addForm").serialize(),
dataType:"JSON",
success:function (res){
console.log(res);
if (res.status){
location.href = location.href;
// location.reload()
}else{
$.each(res.error,function (key,value){
$("#id_"+key).next().text(value[0]);
})
}
}
})
})
}
</script>
{% endblock %}
projectModelForm.py
from web.forms.bootstrap import BootStrapForm
from django import forms
from web import models
from django.core.exceptions import ValidationError
class ProjectModelForm(BootStrapForm, forms.ModelForm):
# desc = forms.CharField(widget=forms.Textarea())
class Meta:
model = models.Project
fields = ["name", "color", "desc"]
widgets = {
"desc":forms.Textarea,
}
def __init__(self,request,*args,**kwargs):
super().__init__(*args,**kwargs)
self.request = request
def clean_name(self):
"""项目校验"""
name = self.cleaned_data["name"]
#1.当前用户是否已经创建过这个项目?
exists = models.Project.objects.filter(name=name,creator=self.request.tracer.user).exists()
if exists:
raise ValidationError("项目名已存在")
#2.当前用户是否还有额度创建项目
# 最多创建多少个项目
#现在已经创建多少项目了
count = models.Project.objects.filter(creator=self.request.tracer.user).count()
if count >= self.request.tracer.price_policy.project_num:
raise ValidationError("项目个数超限,请购买套餐")
return name
project_list视图函数
from django.shortcuts import HttpResponse, redirect, render
from web.forms.project import ProjectModelForm
from django.http import JsonResponse
def project_list(request):
'''项目列表'''
if request.method == "GET":
form = ProjectModelForm(request)
return render(request, "project_list.html", {"form": form})
form = ProjectModelForm(request,data=request.POST)
if form.is_valid():
# 验证通过:项目名、颜色、描述 + 创建者
form.instance.creator = request.tracer.user
# 创建项目
form.save()
return JsonResponse({"status":True})
return JsonResponse({"status": False, "error": form.errors})**