templates下创建每个应用单独的文件夹,将html文件放入
父模板留空给子模板写不同代码片
{% block 模板名 %}
{% endblock 模板名 %}
继承父模板
{% extends 父模板名 %}
包含相同代码片模板
{% include 'common/status.html' %}
加载静态文件
{% load staticfiles %}
静态文件写入方式:
{% static ‘路径/文件名‘ %}
该路径以static文件为相对路径
如果定义的方法是针对表数据操作,需要定义在自定义管理类中
例如:插入数据、查询表中的数据
如果定义的方法针对是行数据进行操作,需要定义在模型类中
例如:修改某一行数据的某个字段数据
在模型管理类中写方法可以直接用self;
在模型类中写方法,需要self.objects;
两者都可以用 模型类.objects。
表级操作用的是模型管理器对象;
行级操作用的是那一行数据对象(例如:self.get(user_id = XX)获取到的对象)。
模型管理类
- self.all()
模型类
- self.objects.all()
- user = User()
user.objects.all()
出错点:
模型类要重新写objects = 管理类(),objects记得写s,
提示错误信息,User没有objects
页面 user/register
method=“post” action=“{% url ‘/user/register_handle‘ %}”
views.py中导入 from .functions import *
functions中导入 from utils.wrapper import *
视图中只写大概的逻辑判断(根据信息匹配成功与否判断是否提交),具体的函数另外同级创建一个文件functions.py处理,使views保持整洁,逻辑易读。
该文件主要对该视图内需要里获取的参数进行判断,只对users来使用,并把判断结果返回给视图。
该文件夹下的模块的函数可以对全局使用
在functions.py中写函数进行判断后,此时需要用到django的原生函数post获取数据,我们在项目下再创建一个文件夹utils工具,在utils下创建wrapper.py,在该文件内对post等原生函数进行封装,方便调用。
举例:
def post(request, param):
return request.POST.get(param, "").strip()
获取页面用户输入数据,需要表单中的input标签的name属性,去html文件中进行name属性的命名修改。
models中管理类中写入方法对数据库表进行操
- 注册功能用到了查询和插入数据两项
- 方法的参数为request或者是已经处理过的数据
- 查询该用户是否存在于数据库中(参数为用户名)
若通过校验,获取数据,存入数据库
若没有通过校验:
messages也是基于cookie和session的封装
从一个页面(视图)跳转到另一个页面(视图)时,如果需要传递参数,可以用get,在URL后面加上?xx=xx,
但是这里传递错误消息,内容较长,用这种方式不合理,就需要一个可以在视图间进行数据传输的工具。
这个模块是进行视图之间通信,数据传输所用,相当于一个队列,可以放入数据,取出数据,一次性使用。
添加信息
messages.add_message(request, message.INFO, "数据内容")
取出信息
mess = messages.get_messages(request)
这里mess并不是一个队列,但是是 可以迭代的,可通过for循环取出
这里mess并不是一个队列,但是是可以迭代的,可通过for循环取出
值得注意的是,取出的数据是先进先出,取出,并不能确定哪条数据归属于哪个内容下的错误提示,
所以要在wrapper.py中对这两个原生接口进行封装:
user/register/当点击注册时在前端页面显示
- 将错误提示消息放在register视图中取出,记为mess;
- 在index.html中显示错误提示消息的地方添加一样的标签,更改class,并写入{% mess.key %},会自动寻找字典中值而添加。
- 修改样式,和前端的提示信息css样式一致,更改display:block为显示;
- 修改js中焦点触发事件,在触发焦点时,后台错误提示消息的标签隐藏。
js发送ajax请求后台判断用户名是否存在,返回结果给js进行异步判断,注册页面在用户输入用户名时可实时显示用户名是否存在
不能进行用户是否存在验证,不安全
在该视图中写入主要逻辑:
如果验证通过,回到xx页面;(先返回首页,后面写中间件处理过后,再判断session中是否有pre_url,如果有,返回pre_url,没有则返回主页)
验证不通过,重回登录页面,并提示错误消息
response.set_cookie[key] = value
request.get_cookie[key]
response.delete_cookie[key] 如果key不存在什么也不发生
request.session[key] = value
request.session.get(key,"") 获取session,key不存在默认为空
request.session[key] 获取session,key不存在会报错
del request.session[key]
request.session.flush()
需求:
若已登录,可以进入用户中心、订单、地址、页面;
若未登录,点击这些链接,回到登录页面。
这里使用装饰器
def permission_verfy(view_func):
def wraper(request,*args,**kwargs):
if get_session(request, 'username'):
return view_func(request,*args,**keargs)
else:
return redirect(首页url)
return wrapper
方法一:
模板包含的时候可以通过with传递参数
{% include 'user/left_menu.html' with flag="order" %}
在通用模板left_menu.html中,进行判断
{% if flag="order" %}class="active"{% endif %}
方法二(根据列表自动生成菜单栏):
使用过滤器:
{% with menus=flag|creat_meau %}
(将参数flag传入过滤器函数creat_meau,函数返回结果赋给menus)
在过滤器中设置列表,列表中字典根据键值对存储主要参数,
对于特殊样式,action键可以通过三步运算判断
flag = "order" and "active" or ""
在left_menu.html中for循环自动生成菜单栏,
这里为/goods/detail/?id=xxx
根据商品id动态生成商品详细页面
在商品详情url的视图中,通过utl中传入的参数,get(request,”id”)获取该商品对象,在html中写入数据.
带参数的?url
{% url "goods:detail" %}?id={{ goods.id }}
或 正则提取url
{% url "goods:detail" goods.id %}
js就够了,不需要ajax,让后台来做
我们把user_id,添加到session或者cookie中,可以直接获取
1. 当用户登录成功,设置cookie,user_id
2. 在商品详细页面的视图中,获取user_id判断用户是否登录,如果用户已登录,获取goods_id,将它们存入数据库;
3. 在存入数据库时,进行判断:
如果用户存在:
获取用户的浏览商品record_goods_list,并按更新时间排序
1 如果该商品存在:
直接save,可以更新时间
2 如果商品不存在:
判断商品数量:
如果商品数量<5:直接存入数据库;
否则:获取更新时间最早的一条数据对象,record_goods_list[0],对其进行更新覆盖。
可以正则匹配两个参数,param1为商品分类id,param2为商品排序方式
^"/goods/detail/(\d)/(\w+)"/$
视图获取商品
goods = Goods.objects.filter(分类字段_id=param1).order_by(param2)
页码用?在url中传入参数
from django.core.paginator import Paginator
paginator = Paginator(所有商品对象,每页放置商品的个数)
page_now = get(request,"page","1") # 给默认页码为1
goods_now = paginator.page(page_now)
---常用属性---
paginator属性:
paginator.page_range 页码范围,可以在html中for循环生成页码
goods_now的属性、方法:
goods_now.number 当前页码
has_next() 是否有下一页
has_previous() 是否有上一页
next_page_number() 返回下一页页码
previous_page_number() 返回上一页页码
ajax向后台传入数据(添加商品数量,商品id),配制添加购物车url和视图,返回json数据(现有购物车数量),异步更新购物车数量标签。
js如何获取商品id?
在detail页面中添加一个隐藏域,js可以通过标签获取val。
type="hidden" value={{ goods.id }} class="xx">
1 如果用户未登录,跳转至登录页面
2 如果已登录,
判断该用户是否在购物车表中
(1)存在:获取用户id的所有商品对象
判断该商品是否存在:
如果存在,更新数量
如果不存在,直接存入
(2)不存在该用户
直接存入
type='hidden' name='csrfmiddlewaretoken' value='MErcUv3Df23t84YsP4skrRbIWCAtVwpe' />
$.ajax({
url:"请求的url",
data:{json数据},
dataType:"json", // 默认为json数据格式
async:false, // 设置同步
type:"get", // 默认为get请求方式
}).done(function(data){
获得从后台返回的json数据
}).fail(function(){
alert("服务器超时,请重试!");
})
$.ajax({
url:"请求的url",
data:{"csrfmiddlewaretoken":xxxxxxxx},
dataType:"json", // 默认为json数据格式
async:false, // 设置同步
type:"post", // 默认为get请求方式
}).done(function(data){
获得从后台返回的json数据
}).fail(function(){
alert("服务器超时,请重试!");
})
a. 为购物车HTML页面添加form,提交地址为提交订单页面,这时就要换到order应用下操作了。
b. js写入表单提交事件,判断是否选中商品,若选中,则提交表单,未选中,提示用户。
request.POST.getlist("标签name属性")