Django框架实现可运营电商网站(一)-- 后台部分

文章目录


0 业务准备工作

0.1 产品需求描述

完成一个电商网站的项目

0.2 业务主体描述

  • 买家
  • 店铺
  • 商品
  • 订单

关系拓扑图
在这里插入图片描述

0.3 业务逻辑描述

业务点

卖家注册
买家注册
	买家可以注册店铺,但是一个买家只能有一个店铺
	买家可以浏览所有的商品
		可以按照商品的类型进行浏览
		也可以进入店铺进行浏览
	
买家可以下单购物,(当前只支持支付宝)
买家购买步骤
	1、买家浏览商品
	2、买家将商品添加到购物车
	3、进行结算
	4、生成订单
	5、买家确认下单
	6、买家确认支付
	7、卖家确认发货
	8、交易完成
	9、期间买家可以发起退款
		1、买家发起
		2、卖家通过
		3、退款发起

购买过程当中的业务实体描述
	购物车
		多样不定量商品的统计
	订单
		多样不定量商品的统计
	二者都需要管理用户、商品、商铺三项

卖家管理商品步骤
	1、卖家可以选择进货(这里以上次作为代替)
	2、卖家可以对商品进行上架、下架、删除、定价
	3、卖家可以对订单进行发货和拒收
	4、卖家可以对商品的销售进行图表统计
	统计内容:每周、月、年销量

当然我要做的是一个个人电商网站,所以卖家就我一个,不过道理都是一样的,只不过是数据库中卖家数量是一条还是多条的问题。

1、项目准备工作

1.1、创建项目(可用pycharm,也可使用命令,这里用命令行来演示)

通过cmd进入虚拟环境(详情参照django第一期)
创建项目命令

django-admin startproject EarphoneMall

1.2、pycharm操作

通过pycharm自带的工具创建app

  • 这里补充一下:manage.py是每个Django项目中自动生成的一个用于管理项目的脚本文件,需要通过python命令执行。manage.py接受的是Django提供的内置命令。

在这里插入图片描述
因为项目主要分为前台和后台,所以app也分为后台app也就是店铺后台,和前台app也就是买家浏览购买页面。

#安装店铺 app 
startapp Shops
#安装前台app    
startapp Buyers

在这里插入图片描述

1.3、配置子url、app静态文件夹、app网页文件夹

在配置app静态文件夹、app网页文件夹一定要加入区分文件夹
在这里插入图片描述
在主urls中添加子urls

from django.contrib import admin
from django.urls import path,include  #注意这里导入了include

urlpatterns = [
    path('admin/', admin.site.urls),  
    path('shops/',include('Shops.urls')),
    path('buyers/',include('Buyers.urls')),
]

在两个子路由中填写

from django.urls import path

urlpatterns = [

]

1.4、配置项目

在settings.py中修改配置

1.4.1、安装app (修改)

在这里插入图片描述

1.4.2、修改数据库(修改)

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'EarphoneMall',
        'PORT': 3306,
        'USER': 'root',
        'PASSWORD': '1234',
        'HOST': 'localhost'
    }
}

由于django默认使用旧版本的mysql,而我安装的是最新版,所以需要在主项目文件夹下的__init__.py添加语句:

-语句生效前提是,已经安装pymysql。

import pymysql
pymysql.install_as_MySQLdb()

配置中设置了数据库名称为EarphoneMall,所以我们还需要在本机mysql创建数据库EarphoneMall
在这里插入图片描述

1.4.3、配置静态文件路径(在最后增加)

STATIC_URL = '/static/'

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

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

2、后台app样式制作

2.1、后台前端样式

这里我提供一个后台模板给大家:
链接:https://pan.baidu.com/s/1-p5LvDOn3ZscMOw3Hhr3AQ
提取码:duz4

2.1.1 后台模板

将后台模板拖入到项目中,如果pycharm拖不进去,直接到项目文件夹下复制粘贴

  • HTML放在templates下的shops中
  • 其他样式文件放在static下的shops中
    在这里插入图片描述

2.1.2 修改HTNL中的链接路径

因为原模板中html和样式在同一根目录下,现在被拆开了,所以需要到html中修改路径

  • 小技巧:在pycharm中可以使用ctrl+r进行替换
    在这里插入图片描述
    依次类推替换所有HTML

2.1.3 前端页面展示

修改后台视图文件和子路由,使前端页面可以在网页中展示

  • 视图函数(views):
from django.shortcuts import render
def index(request):
    return render(request,'shops/index.html',locals())

def login(request):
    return render(request, 'shops/login.html', locals())

def goodsAdd(request):
    return render(request, 'shops/goods_add.html', locals())

def goodsList(request):
    return render(request, 'shops/goods_list.html', locals())
  • 子路由(urls)
from django.urls import path,re_path
from Shops.views import *

urlpatterns = [
    re_path('^$',index),
    path('index/',index),
    path('goodsadd/',goodsAdd),
    path('goodslist/',goodsList),
    path('login/',login)
]

然后就可以运行程序输入路由查看效果了:
在这里插入图片描述

3、建立后台app模型

3.1 建模

我这里要做的是一个耳机的电商网站,耳机电商网站的后台应该需要有以下几个表:

  • 卖家信息表(sellers):姓名、手机号、邮箱、密码、昵称、头像。
  • 耳机分类表(types):类型名称、描述。
  • 耳机详情表(goods):名称、编号、现售价、原价、库存、概述、详情(富文本)、类型(types)、所属卖家(seller)。
  • 耳机图片表(images):图片路径、图片名称、对应商品(goods)。

按照上面在后台(shops)app中的models.py文件中进行建模

#coding:utf-8
from django.db import models
from ckeditor_uploader.fields import RichTextUploadingField


class Seller(models.Model):  #卖家信息表
    username = models.CharField(max_length = 32)
    phone = models.CharField(max_length=32)
    email = models.EmailField()
    password = models.CharField(max_length=32)
    nickname = models.CharField(max_length = 32)
    photo = models.ImageField(upload_to = "image")


class Types(models.Model):  #耳机分类表
    label =  models.CharField(max_length = 32)
    description = models.TextField()

class Goods(models.Model):  #商品
    goods_name = models.CharField(max_length=32)
    goods_id = models.CharField(max_length = 32)
    goods_price = models.FloatField() #原价
    goods_now_price = models.FloatField() #当前价格
    goods_num = models.IntegerField() #库存
    goods_description = models.TextField() #概述
    goods_content = RichTextUploadingField() #详情
    types = models.ForeignKey(Types,on_delete = True) #一个分类会有多个商品
    seller = models.ForeignKey(Seller, on_delete=True) #一家店铺会有多个商品

class Image(models.Model):  #商品展示托盘
    img_path = models.ImageField(upload_to = "image")
    img_label = models.CharField(max_length = 32)
    goods = models.ForeignKey(Goods, on_delete=True)  # 一个商品多张图片

# Create your models here.

模型建立完毕就可以通过pycharm自带的启动manage.py工具同步数据库。
在这里插入图片描述
一共三个命令:

#检查代码
check
#生成表
makemigrations
#同步字段
migrate

下图红圈为命令,篮圈代表成功。
在这里插入图片描述

3.2 查看表

pycharm提供了完整的生产系统,所以你还可以通过pycharm查看数据库:
第一步:打开数据库管理页面
在这里插入图片描述
第二步:在弹出页面添加数据库,我们使用的是mysql,以后可以点击最右边的database来直接打开管理页面
在这里插入图片描述
第三步:绑定数据库
在这里插入图片描述
这样就可以在右侧查看到数据库中的表了,而且pycharm同样提供了对数据库的图形化增删改查
在这里插入图片描述

4 后台登录页

因为为个人商城,所以后台商户就一个,这里就不制作注册页面了,注册页面的做法和后面要说的数据添加页完全一致,有兴趣做注册逻辑的可以去参考。
所以我直接通过pycharm的数据库管理工具,写入本人的信息,方便在制作登陆时使用。

!!!注意:这里密码是通过md5加密的!!!在这里插入图片描述
登陆页面很简单,注意这里需要进行cookie和session的设置,session可以很方便的在做商品函数的时候辨别这是哪个商家的商品,而cookie可以做到设定要求内免密登陆。

4.1 修改html页面登陆表单(login.html)

模板的登录页是login.html,登录页里只有一个登陆表单,作为一个登陆表单,首先在需要设置form的提交请求方式为post,然后需要给每个表单添加name属性,以便提交到后天进行获取,最后还需要submit按钮,来提交表单(模板默认已经做好了)
在这里插入图片描述

4.2 添加密码加密函数

这是一个默认的规定,注册用户的时候,需要对用户密码进行哈希加密,所以存在数据库中的用户密码也是加过密的,哈希加密是不可逆加密,这样才能保证用户数据的安全。所以在登陆时,需要匹配数据库中的密码,数据库密码加密,而用户登陆输入的密码没有加密,所以需要对用户登陆时的密码也进行加密。

在后台视图函数(views.py)中编写加密函数.

import hashlib

#加密函数
def lockpw(pw):  
    md5 = hashlib.md5()
    md5.update(pw.encode())
    result = md5.hexdigest()
    return result

4.3 登录页函数

登录页的逻辑就是获取页面提交的用户名密码,然后在数据库进行匹配,如果匹配成功,则登陆成功。登陆成功下发cookie和session。
首先在开头导入所有的数据库表,以便后来使用:

from Shops.models import *

登陆成功需要跳转,所以需要导入包HttpResponseRedirect,视图文件第一行后面加入HttpResponseRedirect即可

from django.shortcuts import render,HttpResponseRedirect  

登陆函数如下:

#登录页函数
def login(request):
    result = {'status':'error','data':''}  #状态标记,用来返回给前端页面登陆不成功的原因
    if request.method == 'POST' and request.POST: #如果请求方式为POST且有请求内容
        username = request.POST.get('username') #username是前台页面input标签中name属性所写内容
        db_user = Seller.objects.filter(username=username).first() #使用filter的方法取出数据库中字段与前台输入相符的人
        if db_user:  #如果在数据库中取到了,说明有此用户
            db_password = db_user.password  #取该用户储存在数据库的密码
            password = lockpw(request.POST.get('password')) #取该用户页面输入的密码并加密
            if db_password == password:
                #这里要给返回值设置cookie和session,所以需要把返回值先赋值
                response = HttpResponseRedirect('/shops/') #登陆成功跳转至首页
                response.set_cookie('username',db_user.username,max_age=3600) #设置寿命为1小时的cookie
                 request.session['nickname'] = db_user.nickname #设置session
                return response
            else: #如果密码不一致
                result['data'] = '密码错误'
        else: #如果取出的用户为空
            result['data'] = '该商家不存在'
    return render(request,'shops/login.html',locals())

4.4 完善登录页

为了防止csrf,需要在form便签下添加csrf防御
还需要添加一个登陆状体提醒标签,也就是显示函数中result字典中data存储的状态
在这里插入图片描述
效果如下:
在这里插入图片描述

4.5 给其他页面设置cookie验证

首先很多网站在你没有登陆的时候是无法访问的,在你点击之后会直接跳转到登录页,只有验证cookie后,或者再次登陆后才可以访问,而cookie的意义就是可以使浏览器在你设定的时间里记住登陆信息,再次访问的时候就不需要重复登陆了。

而我们做的后台系统肯定是不能然外人进行访问的,所以为了完成这个效果,需要在视图文件中写一个验证cookie的函数,并作为装饰器作用于其他页面。如果想详细了解这里可以看我之前的文章(Python全栈日记-Django(四)

4.5.1 编写cookie验证函数

在后台的视图文件中(写在所有页面函数的上面,因为其他页面需要使用此装饰器):

#cookie验证装饰器
def cookieVerify(fun):
    def inner(request,*args,**kwargs):
        username = request.COOKIES.get("username") #获取cookies中的username
        session = request.session.get("nickname")  # 获取session中的nickname
        db_user = Seller.objects.filter(username=username).first()
         if db_user and db_user.nickname == session:  # 校验session和cookies
            return fun(request, *args, **kwargs) #通过按照原函数返回
        else: 
            return HttpResponseRedirect("/shops/login/") #校验失败跳转至登录页
    return inner 

4.5.2 给其他添加装饰器

对于后台管理系统来说,所有的页面都需要登陆后才能访问,所以需要在每个页面的函数之前都添加cookies验证装饰器
在这里插入图片描述
这样就无法越过登陆直接进入主页等页面了,因为我们cookie设置了1小时的有效,所以可以在无痕模式下尝试。

4.6 session的作用

当我们登陆网页后,经常能在首页看到,“欢迎xxx”的字样,这个就可以通过session来完成。
例如我们模板首页也有这样的一个欢迎信息:时间先不管,到后面做首页的时候做成动态的。
在这里插入图片描述
在后台首页页面(index.html)中找到:欢迎管理员 test
修改test为 request.session.nickname :
在这里插入图片描述
效果如下:
在这里插入图片描述

5、后台登出页

既然有登入,那肯定有登出,模板也给提供了登出按钮
在这里插入图片描述
登出的逻辑很简单,点击退出按钮后删除cookie和session,然后跳转至登陆页面。

5.1 在视图文件中编写:

#登出函数
def loginout(request):
    response = HttpResponseRedirect('/shops/login/')
    response.delete_cookie('username')
    del request.session['nickname']
    return response

5.2 添加路由(urls.py

在这里插入图片描述

5.3 修改按钮路径

既然指定了路由,那就需要在前端页面中将退出按钮绑定在该路由上:
在这里插入图片描述
这样登出逻辑就做好了。

6 商品添加页

模板已经提供了商品添加页(goods_add.html),但是由于字段与我们使用的不同,所以需要先对页面进行修改。

6.1 商品分类添加

6.1.1页面样式

在添加商品之前,首先要添加商品分类
复制模板的商品添加页,然后修改成分类添加页面:
在这里插入图片描述

6.1.2 视图函数

增加视图函数:

#商品类型添加页
@cookieVerify
def goodsTypeAdd(request):
    return render(request, 'shops/goodstype_add.html', locals())

6.1.3 增加路由

在urls文件中增加路由
在这里插入图片描述

6.1.4 增加入口

然后在首页添加商品类型添加的入口按钮
在这里插入图片描述

6.1.5 启动项目查看样式

在这里插入图片描述

6.1.6 修改视图函数增加接收数据逻辑

前台添加商品类型后,需要通过视图函数进行接收并存入数据库

#商品类型添加页
@cookieVerify
def goodsTypeAdd(request):
    if request.method == 'POST' and request.POST:
        types = Types()
        types.label = request.POST.get('typelabel')
        types.description = request.POST.get('typedescription')
        types.save()
    return render(request, 'shops/goodstype_add.html', locals())

6.1.7 添加分类

在页面中添加分类
在这里插入图片描述
添加后查看数据库:
在这里插入图片描述

6.2 页面细节修改

6.2.1 添加csrf防御

在这里插入图片描述

6.2.2 修改所有字段

修改页面上的字段,这里有四个特殊字段,先按照正常修改,后面在做细节调整

  • 图片:多文件
  • 分类:选项
  • 详情:富文本
  • 商家:即当前登陆用户,所以隐藏的

注意把input标签的name属性做修改,修改为自己熟悉的单词,方便后面视图函数获取。
在这里插入图片描述
修改过后:
在这里插入图片描述

6.2.3 图片表单

通常商品的展示图都是多张图片,所以我们要修改图片的input标签为多文件上传标签
给input标签添加属性multiple
在这里插入图片描述
这里form表单有个限制,如果想上传多张图片还需要给form标签添加属性

enctype="multipart/form-data"

也就是:
在这里插入图片描述

6.2.4 商品类别

在6.1中我们添加了分类,现在需要将分类用选项的方式进行选择,也就是使用select和option标签。
而对于多个option标签自己写就很费劲了,通过for循环标签就会简单很多
首先,在商品添加视图函数中取出类型表中所有数据:

#商品添加页
@cookieVerify
def goodsAdd(request):
    types = Types.objects.all()
    return render(request, 'shops/goods_add.html', locals())

然后修改前端页面的标签:
在这里插入图片描述
效果如下:
在这里插入图片描述

6.2.5 商品详情

商品详情以我们常见的淘宝或者京东,都是以富文本的形式展现在页面上,就是图片+文字,大部分淘宝甚至只有图片,想要在数据库中存储这样的信息,必须用到富文本。

(1)富文本编辑器

文章添加需要使用富文本编辑器,富文本编辑器支持图片添加,字体样式等功能。
在这里插入图片描述
要想使用富文本编辑器首先需要安装ckeditor模块,cmd中输入命令进行安装:

pip install django-ckeditor

然后配置setting文件:

[1]加载app

注意有两个app
在这里插入图片描述

[2]在setting文件最后添加两行代码,用于处理上传的文件的位置
CKEDITOR_UPLOAD_PATH = "static/upload"
CKEDITOR_IMAGE_BACKEND = "pillow"
[3]配置路由(url文件)

在主路由中加载ckeditor的子路由

path('ckeditor/',include('ckeditor_uploader.urls')),

如图:
在这里插入图片描述

[4]修改models中数据库字段

修改models中数据库字段,不用重新同步,因为字段名字虽然改变,但是实际上还是字符串:
我们在写字段的时候就是使用的富文本,所以这里不用改了
首先导入富文本的包:
在这里插入图片描述
修改字段:
在这里插入图片描述

[5]收集静态文件

再给前端使用之前还得先将ckeditor的静态文件收集到项目的静态文件中:

在setting中,修改配置,注释掉之前的静态文件设置(包括meida配置),添加收集配置:

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

STATIC_ROOT = os.path.join(BASE_DIR,'static')  #收集专用配置

在项目中使用cmd输入命令或者pycharm点击tools-run manage.py输入命令进行收集:

python manage.py collectstatic

收集完成,改回配置:

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR,'static'),
)
# STATIC_ROOT = os.path.join(BASE_DIR,'static')  #注释了备用

收集完成后会在项目根目录的static文件夹中显示所有app中的static文件内容,这也是我们设置区分文件的目的。
在这里插入图片描述

(2)前端页面修改

首先在head标签中导入富文本的js文件

<script src="/static/ckeditor/ckeditor/ckeditor.js"></script>

修改商品详情标签为,添加name属性方便给textarea添加富文本样式。
注意我蓝色框中对样式的修改
在这里插入图片描述
页面样式为:
在这里插入图片描述
这里我对样式进行了精简,舍去了不用的功能,详情参见我的另一篇博客(https://blog.csdn.net/weixin_39561473/article/details/87297223)
精简后富文本样式为:
在这里插入图片描述

6.2.6 商品所属卖家

商品必须要和卖家挂钩,但是手动输入费力还容易出错,所以这里可以设置一个隐藏的input标签,在提交的时候会默认提交当前的登陆用户,登陆用户就是商品所属的商家。
同首页显示登陆用户一样,这里也直接从session中获取登陆的商家
在这里插入图片描述

6.2.7 修改提交按钮

模板默认增加按钮使用的是button标签,这里要修改为input标签,类型为submit
在这里插入图片描述
这样页面部分就全部做完了,接下来是添加商品的逻辑部分:

6.3 商品添加页视图逻辑

前台都搭建好了,接下来就是在视图文件里修改添加页的视图函数,
这个视图文件分为两部分,一部分是收集前台关于商品表的字段信息,而另一部分是收集商品图片表的字段信息。
注意点:

  • 类型和商户都是外键,所以需要通过用户输入的先获取到类型表和商户表所对应的信息,然后再保存到商品表中
  • 图片是文件类型,而且是多张图片,所以在获取的时候需要获取文件并以列表的形式获取。
  • 图片是由二进制编码写成,所以我们需要将图片转为二进制然后写入我们的静态文件夹中。
  • 图片存在数据库中的只是一个指向静态文件的地址。
  • 图片地址使用了拼接,所以需要导入os包和配置文件的媒体路径MEDIA_ROOT

6.3.1 导包

在这里插入图片描述

6.3.2 写入数据库逻辑

#商品添加页
@cookieVerify
def goodsAdd(request):
    types = Types.objects.all()

    if request.method == 'POST' and request.POST:
        g = Goods() #实例化数据表
        g.goods_name = request.POST.get('goodsname')
        g.goods_id = request.POST.get('goodsid')
        g.goods_price = request.POST.get('goodsprice')
        g.goods_now_price = request.POST.get('goodsnowprice')
        g.goods_num = request.POST.get('goodsnum')
        g.goods_description = request.POST.get('goodsdescription')
        g.goods_content = request.POST.get('goodscontent')
        g.types = Types.objects.get(id=int(request.POST.get('goodstypes')))
        g.seller = Seller.objects.get(nickname=request.POST.get('seller'))
        g.save() #保存数据信息

        for i in request.FILES.getlist('goodsimages'):  #把图片循环出来
            img = Image() #实例化图片表
            img.img_path = 'shops/images/goods/'+i.name #name是文件名,内置方法
            img.img_label = request.POST.get('goodsname')
            img.goods = g
            img.save()

            path = os.path.join(MEDIA_ROOT,'shops/images/goods/{}'.format(i.name)).replace('\\','/')
            with open(path, "wb")  as f:  #wb是以二进制打开
                for j in i.chunks():  #解析图片为2进制文件,全部内容写入到静态文件夹。
                    f.write(j)

    return render(request,'shops/goods_add.html',locals())

6.3.3 尝试添加数据

富文本可以采用从淘宝详情直接复制粘贴的方式
在这里插入图片描述
最后我添加了一共19个商品,逻辑没啥问题

7 商品列表页与详情页

列表页的功能是展示所有的商品
详情页的功能是展示每个商品的详细信息

7.1 列表页

7.1.1 数据提取

首先在列表的视图函数中把商品数据信息提取出来,提供给前端页面使用:

#商品列表页
@cookieVerify
def goodsList(request):
    goods = Goods.objects.all()
    return render(request, 'shops/goods_list.html', locals())

7.1.2 页面展示

在goods_list.html中 修改模板样式为自己可用,并利用for循环标签将数据循环出来。
在这里插入图片描述
最后效果如下:
在这里插入图片描述

7.1.3 操作设置-编辑

有时候我们需要修改现价,这时候就需要用到编辑按钮,那编辑按钮是如何实现的呢?
编辑按钮实际上还是在添加页进行访问,当时要做一个判断,判断目前是添加操作还是修改操作

(1)修改页视图函数

既然要做判断,那就需要做标记,所以给添加页视图函数和修改操作函数添加一个共同的变量,赋予不同的值,以作判断使用。
而且,修改需要将之前填写好的信息再次显示在输入框中,这样就涉及到了一个判断修改的是哪个商品,所以需要用到正则表达式进行匹配。
而关于数据修改后保存入数据库的操作和添加页完全一致。
在这里插入图片描述

(2)添加urls

添加正则。用来匹配所修改商品的id
在这里插入图片描述

(3)修改 商品列表页 编辑按钮的链接地址

需要将编辑按钮链接到商品修改页的url上
在这里插入图片描述

(4)修改 商品添加页 的样式

首先需要将视图函数从数据库取出的数据放入每个input标签的的value中
在这里插入图片描述
然后对按钮文字进行判断,如果dotype(视图函数中的区分变量)为change则按钮为修改
在这里插入图片描述
点击编辑按钮就会和之前不同了,这样就成功了
在这里插入图片描述

7.1.3 操作设置-删除

还有一个操作按钮是删除

(1)编写视图函数

和编辑一样,你首先要确定删除的是哪个商品,这里也需要使用正则,也需要传递参数给函数

#商品删除
@cookieVerify
def goodsDel(request,id):
    goods = Goods.objects.get(id=int(id))
    imgs = goods.image_set.all()  #获取商品的所有照片
    for i in imgs:  #删除存在静态文件夹中的图片
        os.remove(os.path.join(MEDIA_ROOT,str(i.img_path).replace('\\','/')))
    imgs.delete() #先删除外键表
    goods.delete()  # 再删除主键表数据
    return HttpResponseRedirect("/shops/goodslist/") #跳转到商品列表页
(2)增加路由

在这里插入图片描述

(3)修改 商品列表页 删除按钮的链接地址

在这里插入图片描述
这样,商品删除功能就实现了。(删除一时爽,重新添加火葬场)

7.2 商品详情页

首先复制商品详情页,删除列表内容,制作详情页

7.2.1 列表页视图函数

#商品详情页
@cookieVerify
def goodsDetails(request,id):
    goods = Goods.objects.get(id=int(id)) #获取商品信息
    goodsImage = Image.objects.filter(goods=int(id)) #获取商品图片
    return render(request,'shops/goods_details.html',locals())

7.2.2 列表页路由

在这里插入图片描述

7.2.3 修改列表页链接

修改列表页商品名称的链接,点击名称进入详情页
在这里插入图片描述

7.2.4 修改详情页样式

详情页为了好看这里我导入了jQuery和bootstrap
在这里插入图片描述
最终样式如下:
在这里插入图片描述

项目后台动态展示

在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值