Django搭建电商网站之电商项目开始与建模_后台注册登录退出(一)

Django电商项目

一般电商网站的主要对象间的关系及流程图

在这里插入图片描述

根据此流程图进行项目功能的划分:

电商项目我们划分为两个部分:

  • 前台消费的部分,负责展示,出售商品
  • 后台管理部分,负责商品上架,下架管理

项目被分为2个部分,一部分是前台(Buyer),一部分是后台(Store)

数据库建模
进行版本迭代的建模
首先进行后台的开发

卖家:

字段说明
username用户名
password密码
nickname昵称
phone电话
email邮箱
picture头像
address地址
card_id身份证

店铺类型:

字段说明
store_type类型名称
type_description类型描述

店铺:

字段说明
store_name店铺描述
store_address店铺地址
store_description店铺描述
store_logo店铺logo
store_phone店铺电话
store_money店铺注册资金
user_id店铺主人
type 多对多店铺类型

商品:

字段说明
goods_name商品名称
goods_price商品价格
goods_image商品图片
goods_number商品数量库存
goods_description商品的描述
goods_under商品的状态
goods_date出厂日期
goods_safeDate保质期
store_id多对多商品店铺

商品图片:

字段说明
img_address图片地址
img_description图片描述
goods_id多对一商品id

一、环境配置

1、创建Django项目

django-admin startproject DjangoShop

2、创建App(Store店铺)

python manage.py startapp Store

3、创建App下模板目录及静态文件目录

在这里插入图片描述

4、创建主static目录用于收集静态文件

在项目根目录下创建static主目录,用于收集独立App中的静态文件

5、setting文件设置

  • 安装App
  • 进行settings配置

    INSTALLED_APPS = [
    ‘django.contrib.admin’,
    ‘django.contrib.auth’,
    ‘django.contrib.contenttypes’,
    ‘django.contrib.sessions’,
    ‘django.contrib.messages’,
    ‘django.contrib.staticfiles’,
    ‘Store’
    ]

STATIC_ROOT = os.path.join(BASE_DIR,“static”)

  • STATICFILES_DIRS = (
    os.path.join(BASE_DIR,‘static’),
    )

  • MEDIA_URL = ‘/media/’

  • MEDIA_ROOT = os.path.join(BASE_DIR,‘static’)

  • STATIC_ROOT = os.path.join(BASE_DIR,‘static’)

收集静态文件时注释STATICFILES_DIRS、MEDIA_URL、MEDIA_ROOT

STATIC_URL = '/static/'
# STATICFILES_DIRS = (
#     os.path.join(BASE_DIR,"static"),
# )
#
# MEDIA_URL = "/media/"
# MEDIA_ROOT = os.path.join(BASE_DIR,"static")

收集完成取消上述三个注释,再注释STATIC_ROOT

二、创建数据模型类

1、创建模型

from django.db import models

# Create your models here.
# 定义卖家模型类
class Seller(models.Model):
    username = models.CharField(max_length=32,verbose_name="用户名")
    password = models.CharField(max_length=32,verbose_name="密码")
    nickname = models.CharField(max_length=32,verbose_name="昵称",null=True,blank=True)
    phone = models.CharField(max_length=32,verbose_name="手机",null=True,blank=True)
    email = models.EmailField(verbose_name="邮箱",null=True,blank=True)
    picture = models.ImageField(upload_to="store/images",verbose_name="头像",null=True,blank=True)
    address = models.CharField(max_length=32,verbose_name="地址",null=True,blank=True)

    card_id = models.CharField(max_length=32,verbose_name="身份证",null=True,blank=True)

# 定义店铺类型类
class StoreType(models.Model):
    store_type = models.CharField(max_length=32,verbose_name="类型名称")
    type_description = models.TextField(verbose_name="类型描述")

# 定义店铺类
class Store(models.Model):
    store_name = models.CharField(max_length=32,verbose_name="店铺名称")
    store_address = models.CharField(max_length=32,verbose_name="店铺地址")
    store_description = models.TextField(verbose_name="店铺描述")
    store_logo = models.ImageField(upload_to="store/images",verbose_name="店铺logo")
    store_phone = models.CharField(max_length=32,verbose_name="店铺电话")
    store_money = models.FloatField(verbose_name="店铺注册资金")

    user_id = models.IntegerField(verbose_name="店铺主人")
    type = models.ManyToManyField(to=StoreType,verbose_name="店铺类型")

# 定义商品类
class Goods(models.Model):
    goods_name = models.CharField(max_length=32,verbose_name="商品名称")
    goods_price = models.FloatField(verbose_name="商品价格")
    goods_image = models.ImageField(upload_to="store/images",verbose_name="商品图片")
    goods_number = models.IntegerField(verbose_name="商品库存")
    goods_description = models.TextField(verbose_name="商品描述")
    goods_date = models.DateField(verbose_name="出厂日期")
    goods_safeDate = models.IntegerField(verbose_name="保质期")

    store_id = models.ManyToManyField(to=Store,verbose_name="商品店铺")

# 定义商品图片类
class GoodsImg(models.Model):
    img_address = models.ImageField(upload_to="store/images",verbose_name="图片地址")
    img_description = models.TextField(verbose_name="图片描述")
    goods_id = models.ForeignKey(to=Goods,on_delete=models.CASCADE,verbose_name="商品id")

    

2、同步数据库

校验配置

python manage.py check

生成数据库语句

python manage.py makemigrations

同步数据库

python manage.py migrate

收集静态文件
python manage.py collectstatic(收集完成注意恢复配置,并注释STATIC_ROOT)

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR,'static'),
)

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'static')

# STATIC_ROOT = os.path.join(BASE_DIR,'static')

三、创建登录注册功能

1、编写注册登录功能

将模板中的注册HTML文件复制到App下templates-store下

在这里插入图片描述

编写简单视图显示页面

在这里插入图片描述

创建独立url

在这里插入图片描述

填写主url

在这里插入图片描述

更改原html文档,将所有css,js导入路径更改为/static/store/…,在访问网页

改动HTML布局

<!DOCTYPE html>
<html lang="en">

<head>

  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <meta name="author" content="">

  <title>SB Admin 2 - Register</title>

  <!-- Custom fonts for this template-->
  <link href="/static/store/vendor/fontawesome-free/css/all.min.css" rel="stylesheet" type="text/css">
  <link href="https://fonts.googleapis.com/css?family=Nunito:200,200i,300,300i,400,400i,600,600i,700,700i,800,800i,900,900i" rel="stylesheet">

  <!-- Custom styles for this template-->
  <link href="/static/store/css/sb-admin-2.min.css" rel="stylesheet">

</head>

<body class="bg-gradient-primary">

  <div class="container">

    <div class="card o-hidden border-0 shadow-lg my-5">
      <div class="card-body p-0">
        <!-- Nested Row within Card Body -->
        <div class="row">
          <div class="col-lg-5 d-none d-lg-block bg-register-image"></div>
          <div class="col-lg-7">
            <div class="p-5">
              <div class="text-center">
                <h1 class="h4 text-gray-900 mb-4">注册用户</h1>
              </div>
              <form class="user" method="post">
					{% csrf_token %}
                <div class="form-group">
                  <input type="text" class="form-control form-control-user" name="username" placeholder="用户名">
                </div>
                <div class="form-group">
                  <input type="password" class="form-control form-control-user" name="password" placeholder="密码">
                </div>
                <div class="form-group">
                  <input type="submit" class="btn btn-primary btn-user btn-block" value="注册">
                </div>
{#                <a href="login.html" class="btn btn-primary btn-user btn-block">#}
{#                  Register Account#}
{#                </a>#}
                <hr>
{#                <a href="index.html" class="btn btn-google btn-user btn-block">#}
{#                  <i class="fab fa-google fa-fw"></i> Register with Google#}
{#                </a>#}
{#                <a href="index.html" class="btn btn-facebook btn-user btn-block">#}
{#                  <i class="fab fa-facebook-f fa-fw"></i> Register with Facebook#}
{#                </a>#}
              </form>
              <hr>
              <div class="text-center">
                <a class="small" href="forgot-password.html">忘记密码?</a>
              </div>
              <div class="text-center">
                <a class="small" href="login.html">已经有账户了? 登录!</a>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

  </div>

  <!-- Bootstrap core JavaScript-->
  <script src="/static/store/vendor/jquery/jquery.min.js"></script>
  <script src="/static/store/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>

  <!-- Core plugin JavaScript-->
  <script src="/static/store/vendor/jquery-easing/jquery.easing.min.js"></script>

  <!-- Custom scripts for all pages-->
  <script src="/static/store/js/sb-admin-2.min.js"></script>

</body>

</html>

效果:

在这里插入图片描述

复制register文档做登录页面并编写完整注册视图函数:
指出注册页面
保存注册数据

这里使用的hashlib模块,对前端传过来的密码进行加密在保存到数据库中,保证安全

import hashlib

from django.shortcuts import render
from django.http import HttpResponseRedirect

from Store.models import *

# Create your views here.
# 密码加密功能
def setPassword(password):
    md5 = hashlib.md5()
    md5.update(password.encode())
    result = md5.hexdigest()
    return result

# 注册功能
def register(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username and password:
            seller = Seller()
            seller.username = username
            seller.password = setPassword(password)
            seller.nickname = username
            seller.save()
            return HttpResponseRedirect("/Store/login/")
    return render(request,"store/register.html")


# 登录功能
def login(request):
    return render(request,"store/login.html")

测试注册功能

在这里插入图片描述

2、完善登录功能

登录页面:
参照csdn登陆策略
在登陆页面下发cookie,在登陆请求校验cookie

在这里插入图片描述
在登陆的表单当中嵌套大量的隐藏域表单

在登录页面下发cookie,在登录请求校验cookie。如果登录成功,则跳转到首页;否则跳转登录页面

先布局index首页(复制模板当中的index页面并修改样式路径)–前端登录页面

在这里插入图片描述

完善登录视图,这里注意cookie的使用:

# 登录功能
def login(request):
    """
    登录功能:进入登录页面是下发cookie,验证是正常方式请求登录
    登录成功再次下发一个cookie,验证用户
    """
    # 进入登录页面下发来源合法的cookie
    response = render(request,"store/login.html")
    response.set_cookie("login_from","legitimate")
    # 判断用户请求的方式
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username and password: # 用户和密码都存在
            seller = Seller.objects.filter(username=username).first() # 数据库查询该用户
            if seller:
                # 将前端获取到的密码加密,同数据库进行验证
                web_password = setPassword(password)
                # 校验登录页面的cookie
                cookies = request.COOKIES.get("login_from")
                if web_password == seller.password and cookies == "legitimate":
                    # 登录成功,则跳转到首页并下发cookie和session
                    response = HttpResponseRedirect('/Store/index/')
                    response.set_cookie("username",seller.username)
                    request.session["username"] = seller.username
                    return response
    return response

# 首页
def index(request):
    return render(request,"store/index.html",locals())

效果图:

在这里插入图片描述

做个装饰器,给首页添加校验功能,没有cookie不能直接登录首页,只有用户登录成功才能进入首页

# 用户登录校验装饰器
def loginValid(fun):
    def inner(request,*args,**kwargs):
        # 获取成功登录后的cookie和session
        c_user = request.COOKIES.get("username")
        s_user = request.session.get("username")
        # 如果cookie和session都存在并且值都相同
        if c_user and s_user and c_user == s_user:
            # 通过c_user查询数据库
            seller = Seller.objects.filter(username=c_user).first()
            # 如果有这个用户,则返回函数,这里只index
            if seller:
                return fun(request,*args,**kwargs)
        # 否则重定向到登录页面
        return HttpResponseRedirect("/Store/login/")
    return inner


# 首页
@loginValid
def index(request):
    return render(request,"store/index.html",locals())

现在直接进入index首页会自动跳转至登录页面

3、前后端用户名重复校验

后端(针对登录功能)

# 登录功能
def login(request):
    """
    登录功能:进入登录页面是下发cookie,验证是正常方式请求登录
    登录成功再次下发一个cookie,验证用户
    """
    # 后端校验
    result = {"status":"error","data":""}
    # 进入登录页面下发来源合法的cookie
    response = render(request,"store/login.html")
    response.set_cookie("login_from","legitimate")
    # 判断用户请求的方式
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username and password: # 用户和密码都存在
            seller = Seller.objects.filter(username=username).first() # 数据库查询该用户
            if seller:
                # 将前端获取到的密码加密,同数据库进行验证
                web_password = setPassword(password)
                # 校验登录页面的cookie
                cookies = request.COOKIES.get("login_from")
                if web_password == seller.password and cookies == "legitimate":
                    # 登录成功,则跳转到首页并下发cookie和session
                    response = HttpResponseRedirect('/Store/index/')
                    response.set_cookie("username",seller.username)
                    request.session["username"] = seller.username
                    result["status"] = "success"
                    result["data"] = "登录成功"
                    return response
                else:
                    result["data"] = "密码错误"
                    response = render(request, "store/login.html", locals())
            else:
                result["data"] = "用户名不存在"
                response = render(request, "store/login.html", locals())
        else:
            result["data"] = "用户名或密码不能为空"
            response = render(request, "store/login.html",locals())
    return response

效果图:

在这里插入图片描述

前端ajax校验(针对注册功能)

def ajax_regValid(request):
    # ajax前端注册校验
    result = {"status": "error", "data": ""}
    username = request.POST.get("username")
    if username:
        user = Seller.objects.filter(username=username).first() # 数据库查询该用户
        if user:
            result["data"] = "用户名已存在"
        else:
            result["status"] = "success"
            result["data"] = "用户名可以使用"
    else:
        result["data"] = "用户名不能为空"
    return JsonResponse(result)

注册页面添加如下内容:
如果不满足条件则直接将注册按钮置为灰色(失效状态),判断成功则可以正常点击

<script>
      $("#username").blur(
          function () {
              var username = $("#username").val();
              var csrfmiddlewaretoken = '{{ csrf_token }}';
              var url = "/Store/ajax/";
              send_data = {
                  "username":username,
                  "csrfmiddlewaretoken":csrfmiddlewaretoken
              };
              $.ajax(
                  {
                      url: url,
                      type: "post",
                      data: send_data,
                      success: function (data) {
                          var status = data.status;
                          $("#sign").text(data.data);
                          if(status == "error"){
                              $("#submit").attr("disabled",true)
                          }else {
                              $("#submit").attr("disabled",false)
                          }
                          {#alert(data.data)#}
                          {#console.log(data)#}
                      },
                      error: function (error) {
                          console.log(error)
                      }
                  }
              )
          }
      )

  </script>

效果图:

在这里插入图片描述

三、编写退出功能(删除cookie)

定义视图函数:

# 退出功能(删除cookie)
def exit(request):
    response = HttpResponseRedirect("/Store/login/")
    for key in request.COOKIES: # 获取当前所有cookie
        response.delete_cookie(key)
    del request.session["username"]
    return response

更改首页logout超链接的href为/Store/exit/

在这里插入图片描述

GitHub项目地址:https://github.com/py304/DjangoShop

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孜孜孜孜不倦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值