1.创建工程:
Django-admin startproject 工程名
2.配置templates的,在55行的TEMPLATES:
'DIRS': [os.path.join(BASE_DIR,'templates')],
3.配置static,在末尾
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
开始在templates导入登陆、注册和首页的html,并且配置视图和路由
然后在models里创建用户表的模板,在创建用户表时候,我们会添加一个照片字段,name照片字段需要在settings里配置,然后将创建好的模型进行数据迁移
在注册和登录使用post方法,加入{% csrf_token %}来防止跨域问题
开始写注册和登录的视图,并且配置路由
#--------------------------注册
def register(request):
if request.method=='POST':
#取前端的注册数据
username=request.POST.get('user')
#将取到的数据和数据库中存在的用户名进行比较,如果用户名存在,则不能注册
user=User.objects.filter(name=username).first
if user:#如果查到用户名,说明存在
警告信息
else:
User.object.create(添加的数据)
# ---------------------------------------登录页面
①取前端数据
②取数据库的数据和前端数据进行比较
③根据不同的错误进行提升
④如果登录成功,在html页面写入跳转的首页地址:/index,注意要加/
⑤创建cookie和session
def login(request):
if request.method == 'POST':#判断前端是否使用post请求发送数据
email = request.POST.get('email')#获取前端数据
password = request.POST.get('password')
error_msg = '' # 设置一个标记信息,反馈用户输入账号密码的可能出错提示
if email: #如果用户输入了邮箱,开始判断
user = LoginUser.objects.get(email=email)#从数据库查是否有存在的游戏
#如果查询的数据库邮箱,将输入密码加密与数据库密码对比
if user.password == setPassword(password):
# 密码成功跳转网页,并且设置cookie和session
response = HttpResponseRedirect('/index/')#cookie需要response对象
response.set_cookie('email', email)l#设置cookie
request.set_session['email']=账户名#设置session
return response#返回响应
else:#如果密码错误,提示
error_msg = '密码错误!请重新输入!'
else:#没输入邮箱而点击了登录
error_msg = '请输入账户后再登录!'
return render(request, 'login.html', locals())
接着写一个登录装饰器,作用是来获取用户存入的cookie和session信息,以此为依据,在用户进入其他页面时候,每次使用装饰器进行判断,如果用户是登录进来的,则可以访问,如果用户是直接输入的网址进入,则会返回至登录页面
def LoginVaild(func):
#1.当我们在首页时,想要获取用户的用户名怎么获取?需要cookie,因此我们需要将用户登录的账户存入到 cookie和session中,因此上述登录的⑤为加入cookie
#2.取出cookie和session获取的用户名进行比较,成功跳转,失败则返回登录
def inner(request.*args,**kwargs):
username=request.COOKIES.get('username')
session_username=request.session.get('username')
if username and session_username and username==session_username:
return func(request,*args,**kwargs)
else:
return HttpResponseRedirect('/login/')
return inner
最后写一个登出页面,目的是为了删除cookie和session的存储信息,使用户退出后,不可直接进入页面,与上一步相连
def logout(request):
# 删除cookie和session
response = HttpResponseRedirect('/login/') # 返回登录页
response.delete_cookie('email')#删除指定cookie
del request.session['email']#删除session
return response
密码加密:如果我们为了提高安全性,我们可以使用密码加密功能,在视图中写函数,在注册的时候,将密码加密再存入数据库,登录的时候先获取前端密码,将密码加密再和数据库的密码去比较
# -------------------密码加密
def setPassword(password):
md5 = hashlib.md5()
md5.update(password.encode())
result = md5.hexdigest()
return result
先将其他页面共有的公共部分提取出来写到新的网页base.html,并配置路由和视图,然后将可能会与其他不同的部分写一个块镶嵌在可能会写的某处
{% block 块名 %}
{% endblock %}
将其页面与base.html页面相同的部分删除,然后继承base.html页面,并在个性化的位置写入自己的代码
{% extends 'base.html' %}
{% block 块名 %}
个性化内容
{% endblock %}
原理: 物品的上架下架实际上就是物品状态的改变,因此在模型中设置一个物品状态字段goods_status=models.IntegerFiled(choice=((1,'下架'),(0,'上架')))
{% block 块名 %}
{% for i in 数据库取出的多条数据 %}
<tr>
<td>{
{ i.num }}td>
<td>{
{ i.name}}td>
...
{% if i.status = 0 %}
<button>下架button>
<button>修改button>
{% else %}
<button>上架button>
<button>修改button>
{% endif %}
tr>
{% endfor %}
{% endblock %}
此时数据全部呈现在该网页,如果数据多会使用户非常体验差,因此我们需要开始写分页功能
分页需要将数据库查询到的数据分为多页,用户点击下一页,路由发生变化,分页的路由设置为此格式: /goods_list/状态/页数
我们将urls.py里的路由改一下,在用户点击商品详情页的时候,默认显示上架或下架的第一页,所以我们需要使用正则表达式进行路由匹配
path('/goods_list',views.goods_list), #不输页面默认第一页
re_path('/goods_list/(?P[0,1])/(?P\d+)' ,views.goods_list),# 匹配页码数,后台拿到数据开始处理
然后开始写视图页面
#传入url写的组匹配参数
def goods_list(request,type=0,page=1):
status = int(status)
if status == 0: # 查找上架的商品
page = int(page)
goods_obj =Goods.objects.filter(goods_status=0).order_by('goods_number')
else: # 查找下架的商品
page = int(page)
goods_obj = Goods.objects.filter(goods_status=1).order_by('goods_number')
goods_all = Paginator(goods_obj, 6)#六条数据显示一页
goods_list = goods_all.page(page)#可以有的页数的数据 表示的当前对象
然后开始在html页面,配置分页的标签,将视图的数据传入
{% for one in goods_all.page_range %}
<li>
{% if status == '0' %}
<a href="/goods_list/1/{
{ one }}">{
{ one }}a>
{% else %}
<a href="/goods_list/0/{
{ one }}">{
{ one }}a>
{% endif %}
li>
{% endfor %}
将base页面的在售和下架商品页面跳转设置为**/goods_list/状态/1/**
开始写上架和下架按钮
原理: 上架和下架其实就是将数据库中的商品的状态goods_status由0→1或者由1→0的过程
开始写视图中的上架下架函数,并且配置路由
re_path('goods_status/(?P/w+/(?P\d+)' , goods_status),
def goods_status(request,status,id):
id = int(id)
goods = Goods.objects.get(id=id)
if status== "up":
#上架
goods.goods_status = 1
else:
# 下架
goods.goods_status = 0
goods.save()
return HttpResponseRedirect("/goods_list/1/1/")
将上下架的html修改
<button>修改状态button>
{% if one.goods_status == 1 %}
<a href="/goods_status/down/{
{ one.id }}" type="button">下架a>
{% else%}
<a href="/goods_status/up/{
{ one.id }}" type="button">上架a>
{% endif %}
如果我们将数据从数据库提前查出来,然后再填入到页面上:①会加快查询速率②可以使我们在任何想使用此数据的页面快速拿到数据而不需要构建页面
将原来的goods_list视图修改,使一次性拿到数据,并构建路由
## 提供数据的api接口,返回的是一个 json对象
def goods_list_api(request):
#将查询到的数据,打包为一个列表,返回成json数据
res = []
for one in Goods.objects.filter.all():
res.append({
"goods_number":one.goods_number,
"goods_name":one.goods_name,
...
})
result = {
'data':res, }
return JsonResponse(result)
上面返回的json数据,其实就是接口,我们拿到接口数据后,把这些数据填入到网页中,有两种方法:ajax和vue。
无论使用ajax或者vue我们都需要再创建一个视图,一个视图是负责加载原先的html页面的视图,另一个视图负责执行ajax的方法,也就是拿取数据。配置路由,因为跳转需要状态和页数参数,因此需要给视图传入参数。
urls.py
re_path('goods_list_api/, goods_list_api), # 接口取商品数据
path('goods_list_api_vue/', goods_list_api_vue),
views.py
def goods_list_api_vue(request, status=0, page=1):
return render(request, 'goods_list_api_vue.html', locals()
{% verbatim %} {% endverbatim %}
范围内可以使Django语法失效{% extends "base.html" %}
{% block title %}
{% endblock %}
{% block style %}
<script src="/static/js/vue.min.js">script>
<script src="/static/js/vue-resource.js">script>
{% endblock %}
{% block content %}
{% verbatim %}
<div id="content">
<table class="table">
<thead>
<tr>
<th>商品名称th>
<th>商品价格th>
<th>商品数量th>
tr>
thead>
<tbody>
<tr v-for="one in goods_list">
<td>{
{ one.goods_name }}td>
<td>{
{ one.goods_price }}td>
<td>{
{ one.goods_count }}td>
tr>
tbody>
table>
div>
{% endverbatim %}
{% endblock %}
{% block script %}
<script>
Vue.use(VueResource); // 申明 使用 vue_resource
var vue = new Vue(
{
// vue 只能进行静态数据的绑定,构建一堆静态数据
// 完成发送一个get请求,从api接口中获取数据,渲染到指定页面上面
el: "#content",
data: {
//定义一个数据名字,方便上边取这里的数据
goods_list:'',
},
created:function () {
// 发送请求
url = '/goods_list_api/' ;
this.$http.get(url).then(
function (data) {
//相当于ajax的success
// 绑定数据
this.goods_list =data['data']['data']; // 将api返回的商品种类绑定到 goods_list 里面
},
function (err) {
// 相对于 ajax 中的 error
console.log(err)
}
)
}
}
)
script>
{% endblock %}