项目进行第三天,现在似乎才有了眉目,逻辑也开始贯通了起来,建议上一篇直接忽视。
四个大模块:首页,闪购,购物车,我的。四个模块都有自己相对应的前端页面和css,js等,其中,为了方便开发及利用好bootstrap,特意定制一个base。HTML,目的在于美观四个模块。
第一部分:首页
前端:继承base页面,利用swiper,和其他js完成。
后端:models 中进行相关的定义,基础数据,轮播,导航,便利店等需要的模型进行定义,生成相对应的数据表,数据库中插入数据。至于四个模块点击哪个哪个模块的页面变黄色,则是在他们各自的HTML页面中引入了相关de的css 样式。下面以cart(购物车模块)为例:
{% extends 'base/base_main.html' %}
{% load static %}
{% block css %}
{{ block.super }}
<link rel="stylesheet" href="{% static 'axf/cart/css/cart.css' %}">
{% endblock %}
{% block content %}
第二部分:闪购模块
前端:前端页面上一篇也有叙述,一句话也是不停的分块划分,数据库中怼入数据。
进阶:在右上的全部类型和综合排序中加入具体分类。LI中两个span。几个小分类则是DIV 中放了几个a标签。
1:需要遮罩层,并作开关控制。2:上下箭头的图标引言。 3:告诉后端用户选择了那种排序。
后端:(需要拿到用户点击了哪个选项或分类)
1-保持一二级数据的分类(层级关系)。 2:根据排序策略,对相应的字段做排序。 3:返回结果给前端。
商品排序策略:div-div-a-button*3,在markert.js中进行相应的二级分类,排序按钮和遮罩层。
$(function () {
//二级分类按钮
var type_icon_is_down = true;
$("#all_type").click(function () {
//
type_icon_is_down = type_icon_toggle(type_icon_is_down);
$("#type_containor").toggle();
})
$("#type_containor").click(function () {
$(this).toggle();
type_icon_is_down = type_icon_toggle(type_icon_is_down);
})
// 排序按钮
//添加点击事件
$("#all_sorted").click(function () {
//点击就会出现小分类,toggle不带参数时,与show()和hide()的作用一样,
// 切换元素的可见状态,如果元素是可见的,则切换为隐藏状态;
// 如果元素是隐藏的则切换为可见状态,
$("#sort_containor").toggle();
})
//遮罩层部分
$("#sort_containor").click(function () {
$(this).toggle();
})
views.py中与前端进行约定:0 表示综合排序,1 表示价格最低, 2 表示销量优先。
获取参数:排序按钮中多加一个占位,对应的url也要加一个反向解析的参数。同时base_main中相关的地方也需要加入参数。
在前端传进数据时,进行判断,确定显示状态(带绿否),紧跟着views中进行约定-拿数据-拿商品-根据用户的用户的选择id,进行相关排序。
def market(req, type_id, sub_type_id, sort_type):
# 拿全部的分类数据
all_types = GoodsType.objects.all()
# 变成
sort_type = int(sort_type)
# 拿商品
goods = Goods.objects.filter(categoryid=type_id)
# 如果二级分类的id不得0 那就需要在原有数据集goods的基础上 找对应二级分类对应的数据
if int(sub_type_id) != 0:
goods = goods.filter(childcid=sub_type_id)
# 记得先拿完数据再做排序,前面还是进行了约定012-DEFAULT_SORT等。
if sort_type == DEFAULT_SORT:
pass
#一些套路
elif sort_type == PRICE_SORT:
goods = goods.order_by("price")
else:
# 销量(productnum)最多,用降序排列
goods = goods.order_by("-productnum")
# 通过查询出来的数据集找到选中的那个分类数据
select_type = all_types.get(typeid=type_id)
# 拿到二级分类数据
all_sub_type = select_type.childtypenames
type_name_id_list = all_sub_type.split("#") #将子分类数据切分
# name_ids = i.split(":")
# sub_types.append(name_ids)
sub_types = [ i.split(':') for i in type_name_id_list]
# print(sub_types)
"""
0 表示综合排序
1 表示价格最低
2 表示销量优先
"""
data = {
'title': '闪购',
'types': all_types,
'goods': goods,
'selected_typeid': type_id,
'sub_types': sub_types,
#二级分类的id
'select_sub_type_id': sub_type_id,
#用户选择的,排序是转了int,此处仍需转回来
'select_sort_type': str(sort_type)
}
return render(req, 'market/market.html', data)
第三部分:用户体系(我的模块)。
(注册,登陆,激活三个页面。)前端页面搭建不做介绍,同意继承base_main.html。
进阶:用户在点击注册或未登录及完成登陆后的退出时,可以执行相关操作。在完成登陆后,用户名,用户头像都得到显示。
一、注册
前端:用户提交相关数据-进行校验-对密码做加密(使用md5.js,并一定要在自己的js之前引用。
注意:<form action=" " method="post" enctype="multipart/form-data"> .........</form>
前端js做校验:
$(function () {
$("#my_form").submit(function () {
//拿用户名的数据
var u_name = $("#u_name").val();
var $pwd = $("#u_pwd");
var $confirm = $("#u_confirm_pwd");
if (u_name.length <= 4){
alert("用户名过短");
return false;
}
if ($pwd.val() == $confirm.val() && $pwd.val().length>=4){
//将密码做加密
var enc_data = md5($pwd.val());
$pwd.val(enc_data);
$confirm.val(enc_data);
} else {
alert("密码不符合规范");
return false;
}
});
})
后端:1-校验用户输入的数据,执行相关操作,若没有就进行创建(生成验证邮件--激活API(时的is_active属性变为True,即注册成功))
备注:一般来讲,为了更好的管理项目,通常在views中只写返回的页面。可以在新建一个py文件,用来存放其他的API。我的叫apis_v1.py。
1- models中自定义用户模型,继承自AbstractUser。并创建一个地址模型。具体上一节有提及。
2-在自定义模型完成后,需要去settings.py中进行修改AUTH_USER_MODEL="app 名字"和MEDIA_ROOT=os.path.join(BASE_DIR,'存放的文件名'。
3-在apis_v1.py中使用类视图的方式来写一个注册的API,并为其创建一个urls_apis的py文件。
class RegisterAPI(View):
def post(self,req):
#解析参数
params=req.POST
u_name=params.get("u_name")
pwd = param.get("pwd")
confirm_pwd = param.get("confirm_pwd")
email = param.get("email")
icon = req.FILES['icon']
# 对数据做校验
if len(u_name) <= 4:
return HttpResponse("账号名过短")
if pwd and len(pwd) > 0 and pwd == confirm_pwd:
if MyUser.objects.filter(username=u_name).exists():
return HttpResponse("用户已存在")
else:
# 创建用户
user = MyUser.objects.create_user(
username=u_name,
password=pwd,
email=email,
is_active=False,
icon=icon
)
#生成验证连接 发送邮件
token = send_verify_mail(email, req.get_host())
# 记录邮件和随机字符的验证邮箱
cache.set(token, user.id, settings.EMAIL_TOKEN_MAX_AGE)
#完成后重定向到登陆页面。
return redirect(reverse("axf:login_view"))
完成后再urls_api.py中写入子路由:
url(r"^register$", RegisterAPI.as_view(), name="api_register"),
同时,跟路由中也需要进行api_v1的路由:
url(r"^axf/api/v1/", include("axf.urls_apis_v1", namespace="axf_api"))
注:不管是邮箱(验证)还是获得随机字符,都建议再创建一个py文件,叫做my_utils.py,专门用来存放各种方法,在使用时直接调用就好。
二、登陆也是如此,详细过程改日再补。