说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!
接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/88842059
目录
一丶Windows环境下安装FastDFS_Client
1.在windows环境下直接使用pip install fdfs-client-py进行安装则会出现以下提示
2.在windows环境下需进行如下安装
- step1 下载fdfs_client包https://pan.baidu.com/s/11Rd6q3vr7vH3Lr1_8JMfSw,提取码u1d7
- step2 将解压之后的fdfs_client文件夹copy到python解释器下的Lib目录中
- step3 进入fdfs_client目录,编辑storage_client.py文件,将第12行代码注释(避免提示ImportError: No module named sendfile错误信息)
- step4 安装mutagen
- step5 安装requests
- step6 在解释器目录下新建logs文件夹,用于存放fdfs客户端日志文件
- step7 修改fdfs配置文件client.conf,需要注意的是base_path的路径是在以client.conf为起始路径进行查找的
- step8 回到虚拟机ubuntu(192.168.1.10),开启fdfs服务以及nginx服务
- step9 进行上传文件测试,打开cmd命令窗口,进行python2环境(博主将一个水果图片直接放在D盘中然后进行此图片上传操作),配置文件路径以及要上传的文件路径均为绝对路径
from fdfs_client.client import Fdfs_client
client = Fdfs_client(r"D:\Python27\Lib\fdfs_client\client.conf")
client.upload_by_filename(r"D:\goods.jpg")
- step10 上传成功后,返回文件id,在windows浏览器中直接访问ubuntu电脑的ip(也就是nginx服务器的ip端口,然后nginx再去到fdfs系统中获取对应文件id的文件,最后返回给浏览器,最后浏览器将该文件渲染出来,最终显示出图片)http://192.168.1.10:8888/group1//M00/00/00/wKgBClygfSuAO8GOAAAX1PFRdzg942.jpg,如下图可以看见响应报头中的server为在ubuntu中安装的nginx版本
- step11 同样的在ubuntu系统中访问该上传成功的文件id,一样成功的在浏览器中显示出来(这里的IP就要写本地的IP)
二丶Django二次开发对接FastDFS
1.项目中使用上传图片使用图片流程图
2.更改django默认上传文件的存储方式 ,django站点管理中进行文件的上传默认使用的是FileSystemStorage类,这个类在本地文件系统上实现了基本的文件存储功能,它继承自Storage类 ,并且提供父类的所有公共方法的实现,所以可以定义一个类来继承Storage类,重写这个类中方法来实现更改django的默认存储方式,可以参考django的API文档
3.编写一个自定义存储系统,
- step1 自定义的存储系统必须为
Django.core.files.storage.Storage
的一个子类
from django.core.files.storage import Storage
class MyStorage(Storage):
...
- step2 在你的存储类中,除了其他自定义的方法外,还必须实现
_open()打开文件
以及_save()保存文件
方法,如果你的类提供了本地文件存储,它必须重载path()
方法 - step3 在项目utils目录下创建一个fdfs的python包,并在这个包下创建storage.py模块,在这个模块中实现自定义存储系统
- step4 在storage.py中定义一个类继承与storage的子类Stroage,实现_open()以及_save()方法
- step5 导入Fdfs_client类,将client.conf配置文件拷贝到utils/fdfs目录下
- step6 修改client.conf配置文件中
base_path=D:\Python27\logs
- step7 因为项目中场景不使用_open方法,只是用_save方法,所以在_save进行编写,创建Fdfs_client对象
client = Fdfs_client(r"./utils/fdfs/client.conf")
- step8 上传文件到FastDFS系统中,upload_by_buffer方法是上传文件内容,而不是文件名了
res = client.upload_by_buffer(content.read())
- step9 判断是否上传成功
# 上传成功返回的字段数据
"""
dict
{
'Group name': group_name,
'Remote file_id': remote_file_id,
'Status': 'Upload successed.',
'Local file name': '',
'Uploaded size': upload_size,
'Storage IP': storage_ip
}
"""
if res.get("Status") != "Upload successed.":
# 表示上传失败
raise
- step10 上传成功获取文件id,并返回
filename = res.get("Remote file_id")
return filename
- step11 重写exists方法调用_save方法之前会去调用exists方法,判断文件在系统中是够存在
def exists(self, name):
"""如果提供的名称所引用的文件在文件系统中存在,则返回True,否则如果这个名称可用于新文件,返回False"""
# 因为在django中不存在文件名情况,所以直接返回false
return False
4.在django admin后台管理页面测试文件存储类
- step1 在settings配置文件中设置django文件存储类为上面定义的类
DEFAULT_FILE_STORAGE = "utils.fdfs.storage.FDFSStorage"
- step2 在df_goods/admin中注册商品类型模型类
from django.contrib import admin
from df_goods.models import GoodsType
# 注册商品类型模型类
admin.site.register(GoodsType)
- step3 创建超级管理员
- step4 在浏览器输入http://127.0.0.1:8000/admin/ 进入后台管理页面
- step5 在商品种类栏点击增加(标识标识的是商品分类中对应分类标签中的class的值)
- step6 点击保存后,提示保存成功
- step7 进入新鲜水果后,出现错误提示,必须保证有一个url方法
- step8 在FDFSStorage类中定义url方法,直接返回name
def url(self, name):
return name
- step9 刷新报错页面,显示出filename的值(也就是上传文件到FastDFS成功后返回的文件id的值)
- step10 在浏览器中访问http://192.168.1.10:8888/group1/M00/00/00/wKgBClygnuOATdepAAAgnaeGwNQ6841857,则出现下载,因为在获取Remote file_id的值的时候,并没有后缀名,导致出现下载
- step11 新建一个html文件,创建img标签,src就等于http://192.168.1.10:8888/group1/M00/00/00/wKgBClygnuOATdepAAAgnaeGwNQ6841857
- step12 直接打开该html文件,成功将图片显示出来
- step13 修改url方法返回参数
def url(self, name):
return "http://192.168.1.10:8888/"+name
5.优化自定义文件存储类
- step1 在settings配置文件中设置client.conf的路径以及nginx服务器的ip和port
# 设置fdfs使用client.conf配置文件的路径
FDFS_CLIENT_CONF_PATH = r"./utils/fdfs/client.conf"
# 设置fdfs存储系统上的ngin服务器的ip和端口
FDFS_URL = r"http://192.168.1.10:8888/"
- step2 在FDFSStorage类中定义魔法方法,使client.conf的路径以及nginx服务器的ip和port动态生成,增强存储类的灵活性
def __init__(self, client_conf=None, base_url=None):
if client_conf is None:
client_conf = settings.FDFS_CLIENT_CONF_PATH
if base_url is None:
base_url = settings.FDFS_URL
self.client_conf = client_conf
self.base_url = base_url
- step3 将以下两处进行替换
client = Fdfs_client(self.client_conf)
return self.base_url+name
三丶天天生鲜首页
1.定义类视图显示首页页面
- step1 在df_goods/views中定义IndexView类视图,并在这个类中定义get方法,用于显示首页
# http://127.0.0.1:8000
class IndexView(View):
'''首页'''
def get(self, request):
'''显示首页'''
return render(request, 'index.html')
- step2 在df_goods/urls中导入类视图,并调用其父类的as_view方法
url(r"^$", IndexView.as_view(), name="index")
- step3 进入http://127.0.0.1:8000/项目首页地址,成功显示首页页面
- step4 将df_goods/models中的IndexPromotionBanner首页促销活动模型类的url字段的类型修改为CharField类型,因为URLField类型,在admin中注册后,在django管理后台进行添加时,会去解析URL链接地址是否有效,并且该字段是必须填写的,所以修改为CharField类型,就可填可不填,并且不用去解析
url = models.CharField(max_length=256, verbose_name='活动链接')
2.首页内容获取与展示
- step1 在IndexView类视图get方法中,获取商品的种类信息
types = GoodsType.objects.all()
- step2 获取首页页面幻灯片中的商品信息,以index字段(展示顺序)进行排序
goods_banners = IndexGoodsBanner.objects.all().order_by('index')
- step3 获取首页促销活动信息,以以index字段(展示顺序)进行排序
promotion_banners = IndexPromotionBanner.objects.all().order_by('index')
- step4 获取首页中分类商品展示信息(types),遍历商品种类信息,获取每个商品种类(type)为GoodsType对象,然后在数据库商品分类表(IndexTypeGoodsBanner)中根据type字段(商品类型)以及display_type(展示类型)查询数据,并按照表index字段(展示顺序)进行排序显示,display_type=1表示图片展示类型,display_type=2表示文字展示类型;然后给每个商品种类对象添加image_banners属性以及title_banners属性
for type in types: # GoodsType
# 获取type种类首页分类商品的图片展示信息
image_banners = IndexTypeGoodsBanner.objects.filter(type=type, display_type=1).order_by('index')
# 获取type种类首页分类商品的文字展示信息
title_banners = IndexTypeGoodsBanner.objects.filter(type=type, display_type=0).order_by('index')
# 动态给type增加属性,分别保存首页分类商品的图片展示信息和文字展示信息
type.image_banners = image_banners
type.title_banners = title_banners
- step5 获取用户购物车商品数量信息,这里先设置为0,表示默认没有
cart_count = 0 # 默认设置为0
- step6 构造上下文响应数据,并返回给模板文件
context = {'types':types,
'goods_banners':goods_banners,
'promotion_banners':promotion_banners,
'cart_count':cart_count}
# 使用模板
return render(request, 'index.html', context
- step7 在index.html模板文件中,进行填坑数据处理,{{forloop.counter}}在for循环遍历是从1开始累加
商品种类
<ul class="subnav fl">
{% for type in types %}
<li><a href="#model0{{ forloop.counter }}" class="{{ type.logo }}">{{ type.name }}</a></li>
{# <li><a href="#model02" class="seafood">海鲜水产</a></li>#}
{% endfor %}
</ul>
幻灯片
{% for banner in goods_banners %}
<li><a href="#" ><img src="{{ banner.image.url }}" alt="幻灯片"></a>/li>
{% endfor %}
促销活动
{% for banner in promotion_banners %}
<a href="{{ banner.url }}"><img src="{{ banner.image.url }}"></a>
{#<a href="#"><img src="{% static 'images/adv02.jpg' %}"></a>#}
{% endfor %}
分类商品
<ul class="subnav fl">
{% for type in types %}
<li><a href="#model0{{ forloop.counter }}" class="{{ type.logo }}">{{ type.name }}</a></li>
{# <li><a href="#model02" class="seafood">海鲜水产</a></li>#}
{% endfor %}
</ul>
<div class="slide fl">
<ul class="slide_pics">
{% for banner in goods_banners %}
<li><a href="#" ><img src="{{ banner.image.url }}" alt="幻灯片"></a>/li>
{% endfor %}
{# <li><a href="#" ><img src="../static/images/slide02.jpg" alt="幻灯片"></li>#}
</ul>
<div class="prev"></div>
<div class="next"></div>
<ul class="points"></ul>
</div>
<div class="adv fl">
{% for banner in promotion_banners %}
<a href="{{ banner.url }}"><img src="{{ banner.image.url }}"></a>
{# <a href="#"><img src="{% static 'images/adv02.jpg' %}"></a>#}
{% endfor %}
</div>
- step8 刷新首页http://127.0.0.1:8000/页面后,只显示了商品分类信息,幻灯片和商品促销以及分类商品均为空白,这是因为数据库中并没有数据,而显示了商品分类信息,是因为博主前面注册了商品类型模型类(GoodsType)并在django管理后台进行了商品类型的添加,所以数据库中df_goods_type表有数据
3.数据准备
- step1 在df_goods/admin中注册模型类
- step2 进入http://127.0.0.1:8000/admin/django后台管理页面
- step3 点击商品SPU栏的增加,进行数据库df_goods表数据的添加,添加后进行保存即可
- step4 保存成功后进入商品SPU栏后,则显示添加后的数据
- step5 当添加商品SPU数据后,再对商品栏(df_goods_sku表)进行数据添加操作
- step6 点击保存,结果报错了,根据报错提示没有找到文件的位置,异常目录为tracker_client.py,说明tracker服务器没有找到,于是博主立马知道了,因为博主在写博客分为两个时间,一个是在家,另一个是在公司,即IP端不同,此时在django后台添加数据是在公司的IP网段下,而client.conf中的配置为家里的IP段配置,所以添加数据报错了
- step7 修改ubuntu中fdfs目录下的storage.conf,mod_fastdfs.conf以及windows项目中fdfs目录下的client.conf配置文件里面的tracker_server的ip为公司环境IP后,刷新提交页面,添加记录成功
- step8 添加操作都是体力活啊,这里就不一一进行演示了,博主花了大半会儿功夫将主页需要的数据添加完毕,添加6个表的数据
- step9 此时添加完主页必有的表字段数据后,刷新主页面
- step10 在数据库中表示数相关的表数据
- 说明:由于数据太多只截取前面两条数据
商品SPU
商品
商品种类
首页幻灯片商品
主页促销活动商品
主页分类展示商品
4.首页获取购物车商品数目
- step1 分析存储购物车记录
1.什么时候添加购物车数目
当用户点击商品加入购物车时,需要添加购物车数目
2.什么时候需要获取购物车记录
当用户使用购物车记录时和用户访问购物车页面数据时
3.使用什么来数据库来存储购物车的记录
使用redis数据库进行存储,因为加入购物车是高频的
4.以哪种数据格式进行存储
使用hash(属性:值的关系进行购物车数目的存储)
cart_用户id:{'sku_id1':商品数目,'sku_id2':商品数目}
例如:'cart_1':{'1':4,'2',8}
在首页左上方显示的购物车显示的是hash数据中的元素总数,即2(商品id为1的和商品id为2的共两个),大多网站都是显示商品类总数,而不是商品量总数
- step2 在IndexView视图函数中获取用户购物车商品数目
user = request.user # 获取user对象
cart_count = 0 # 默认设置为0
if user.is_authenticated(): # 如果返回True表示用户已登录
# 用户已登录
conn = get_redis_connection('default') # 获取配置中default默认redis连接对象
cart_key = 'cart_%d'%user.id # 设置key
# 通过hlen方法获取购物车商品数目
cart_count = conn.hlen(cart_key)
- step3 在父模板base.html文件中填写购物车数目的坑
<div class="goods_count fl" id="show_count">{{ cart_count }}</div>
- step4 刷新主页,因为还没有编写添加商品到购物车逻辑代码,所以cart_count为0,即在主页显示为0
- step5 登录cdtaogang_2账号(用户id=2),进入redis数据库,选择settings配置文件中配置的第五个数据库,然后使用hmset设置模拟数据 ('cart_2':{'1':4,'2':8}),使用hlen获取元素长度(个数)2,即购物车数目为2
- step6 此时刷新页面,成功显示购物车数目为2
5.将首页页面静态化,把原本动态的页面处理结果保存成html文件,让用户直接访问这个生成出来的静态的html页面
说明:因为网站首页几乎是不变的,当首页需要更改修改数据时,才会发生变化,换句话说就是当后台管理员首页页面对应的数据时,才会生成新的首页静态页面,大多用户浏览网站都是看主页,当很多用户浏览主页时,不管登录与否页面显示的内容都是一样的,每次用户请求主页页面时,都会到数据库去查询数据,并且查询的数据都是一样的,所以将页面进行静态化后,就不用每次用户请求首页数据时都要到数据库进行查询数据,再返回给用户,这样做大大的对减少网站服务器的压力,还利于SEO的优化
- step1 分析静态页面的实现
1.什么时候需要重新生成静态页面(用户未登录的主页页面)
当管理员在后台修改添加以及删除页面对应数据库表中的数据时需要重新生成新的静态页面
2.如何生成
使用celery,在tasks.py文件中异步生成首页静态页面
- step2 在tasks.py文件中定义一个任务函数
@app.task
def generate_static_index_page():
"""生成首页静态页面"""
pass
- step3 获取首页页面上的数据,直接把IndexView类视图get方法中的代码拿过来,因为生成的首页静态页面是用户不登录状态,所以,不需要获取购物车的数目,也不需要返回HttpResponse对象
types = GoodsType.objects.all()
goods_banners = IndexGoodsBanner.objects.all().order_by('index')
promotion_banners = IndexPromotionBanner.objects.all().order_by('index')
for type in types:
image_banners = IndexTypeGoodsBanner.objects.filter(type=type, display_type=1).order_by('index')
title_banners = IndexTypeGoodsBanner.objects.filter(type=type, display_type=0).order_by('index')
type.image_banners = image_banners
type.title_banners = title_banners
context = {'types': types,
'goods_banners': goods_banners,
'promotion_banners': promotion_banners}
- step4 因为是显示用户未登录的首页静态页面,所以必须创建一个新的主页模板文件,创建首页静态页面继承的父模板文件static_base.html以及静态主页模板文件static_index.html,将base.html内容直接拷贝到static_base.html中,再将index.html中的内容全部拷贝到static_index.html中,修改static_index.html模板文件的继承模板文件为static_base.html,然后去除父模板文件static_base.html中的欢迎以及显示用户所在的标签,只留下登录和登出即可
- step5 使用loader方法加载模板文件,再通过模板对象中的render方法渲染出模板文件的内容,最后通过文件读写操作,将模板内容(static_index_html)写入到static目录下的index.html中
# 1.加载模板文件
template = loader.get_template("static_index.html") # 返回模板对象
# 2.渲染模板内容(数据填坑)
static_index_html = template.render(context)
# 3.生成首页静态文件
save_index_static_file = os.path.join(settings.BASE_DIR, 'static/index.html') # 生成首页静态文件的路径
with open(save_index_static_file, "w") as f:
f.write(static_index_html)
- step6 在Terminal终端上新开一个终端,执行celery -A celery_tasks.tasks worker -l info 启动worker,结果报错了提示没有模块名,from df_goods.models import GoodsType, IndexGoodsBanner, IndexTypeGoodsBanner, IndexPromotionBanner导入模块报错,原因是在django配置环境没有初始化的时候,导入会报错,根本找不到,所以需要将这几个模型类放到django.setup()吃实话下面,这样就能找到,不会出现以下错误
- step7 重新执行celery -A celery_tasks.tasks worker -l info,启动2个worker成功
- step8 向worker发出任务,打开IDE下方的Python Console,导入任务函数generate_static_index_page,去调用delay方法,向worker发送任务成功
- step9 回到Terminal中查看celery 日志,显示任务执行成功,时长0.259秒
- step10 查看static目录是否生成了index.html文件
- step11 查看index.html文件内容,该内容已经是对templates/index.html模板进行填坑后的数据了
- step12 在浏览器中直接打开static/index.html静态页面,只显示出商品图片,也是所有填坑数据,所有的静态文件资源路径not found,无法找到
6.配置nginx服务器,让nginx服务器来提交静态页面
- step1 首先想要nginx服务器提交静态页面,那么就需要在nginx所在的服务器中有项目文件,所以拷贝项目到nginx服务器(Ubuntu)桌面上
- step2 其次是添加nginx服务器server配置,添加如下配置
说明:listen 监听80端口,也就是nginx的默认端口号
/static表示 访问请求地址为 nginx服务器IP:listen/static(192.168.4.63:80/static)alias指定文件路径为ubuntu中项目下的static目录,顺便说一下alisa配置端只有location本地,从本地获取路径,而root配置端为http、server、location、if
/表示 访问请求地址为 nginx服务器IP:listen/static(192.168.4.63:80)root指定文件路径为ubuntu中项目下的static目录
index 表示配置网页初始页,后面可以跟多个,会在root目录下去查找,找到匹配的就返回
sudo vi /usr/local/nginx/conf/nginx.conf
之所以配置/static和/这两种路径是因为生成的static目录下的index.html文件内容中,静态资源文件路径都是/static开头的,当在浏览器中输入http://192.168.4.63/(nginx服务器IP) ,就会匹配location / 地址,然后就会将static目录下查找是否存在index.html或者是index.htm文件并且将查找到的文件返回给浏览器,浏览器在对index.html进行解析时,然后发现内容中的所有静态资源需要从192.168.4.63:80/static/xxxxx地址进行获取,匹配location /static地址然后就会从ubuntu桌面项目static目录下获取文件
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location /static {
alias /home/taogang/Desktop/dailyfresh/static/;
}
location / {
root /home/taogang/Desktop/dailyfresh/static/;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
- step3 重启nginx服务
- step4 在浏览器中输入http://192.168.4.63/成功显示出首页静态页面,不输入端口号浏览器默认端口就是80
- step5 查看首页静态页面中静态资源访问地址,验证step2博主说的静态资源访问地址
7.django后台管理更新首页数据时重新生成新的首页静态页面
- step1 在df_goods/admin中定义IndexPromotionBannerAdmin类,该类继承于admin.ModelAdmin,在这个类中重写父类的save_model方法以及delete_model方法用于django后台对表数据进行修改删除时,会调用我们重写父类的方法,在这两个方法中再调用父类的的save_model以及delete_model方法完成数据的更新操作,然后再向worker发出任务,重新从数据库中获取修改后的数据,读写templates目录下已经更新数据后的index.html文件的内容写入到static下的index.html中,显示最新的主页静态页面
class IndexPromotionBannerAdmin(admin.ModelAdmin):
"""重写父类中的save_model方法,该方法在后台管理页面对数据修改时时会调用此方法"""
def save_model(self, request, obj, form, change):
# 调用父类中国的save_model方法让数据完成更新
super(IndexPromotionBannerAdmin, self).save_model(request,obj,form,change)
# 向worker发出任务,重新生成更新数据后的页面
from celery_tasks.tasks import generate_static_index_page
generate_static_index_page.delay()
def delete_model(self, request, obj):
"""对数据进行删除时会调用"""
super(IndexPromotionBannerAdmin, self).delete_model(request, obj)
# 向worker发出任务,重新生成更新数据后的页面
from celery_tasks.tasks import generate_static_index_page
generate_static_index_page.delay(
# 注册首页促销活动模型类
admin.site.register(IndexPromotionBanner, IndexPromotionBannerAdmin) # 将管理类添加进去
- step2 因为首页静态页面是从nginx服务器中(ubuntu)本地项目static目录下的index.html,所以在windows项目这边需要将tasks.py文件中broker设置为nginx服务器的中的redis数据库作为中间人
app = Celery("celery_tasks.tasks", broker="redis://192.168.1.8:6379/4")
- step3 在ubuntu中配置redis可任意ip连接,注释掉bind即可
- step4 测试在windows电脑上远程ubuntu电脑上的redis数据库
- step5 在nginx服务器中(ubuntu)中启动worker
- step6 然后在django后台修改数据,点击保存时即worker显示接收到任务,最后访问192.168.1.8(nginx服务器IP),查看静态页面是否更新,博主这里就修改主页中促销商品的显示顺序,index展示顺序,
- step7 刷新主页静态页面http://192.168.1.8/,结果页面没人任何数据,原因是在ubuntu中的项目配置的mysql数据库为本地,所以没说任何数据,之前在django管理页面添加数据为windows本地项目,所以需要在windows msyql中新建个用户用于ubuntu项目中进行访问数据,需要注意的是windows关闭防火墙
grant all privileges on dailyfresh.* to "taogang"@"%" identified by "123456"
- step8 修改ubuntu项目中的settings配置文件mysql项
- step9 重新刷新http://192.168.1.8/主页静态页面后,成功显示出数据
- step10 修改IndexPromotionBannerAdmin类为BaseModelAdmin,并定义其他模型管理类,继承于BaseModelAdmin,当管理员在后台对其他表数据进行修改时也同样调用我们重写的方法对数据进行更新,然后向worker发出任务,完成首页静态页面数据的更新
class BaseModelAdmin(admin.ModelAdmin):
"""重写父类中的save_model方法,该方法在后台管理页面对数据修改时时会调用此方法"""
def save_model(self, request, obj, form, change):
print "11111111111"
# 调用父类中国的save_model方法让数据完成更新
super(BaseModelAdmin, self).save_model(request,obj,form,change)
# 向worker发出任务,重新生成更新数据后的页面
from celery_tasks.tasks import generate_static_index_page
generate_static_index_page.delay()
def delete_model(self, request, obj):
"""对数据进行删除时会调用"""
super(BaseModelAdmin, self).delete_model(request, obj)
# 向worker发出任务,重新生成更新数据后的页面
from celery_tasks.tasks import generate_static_index_page
generate_static_index_page.delay()
class GoodsTypeAdmin(BaseModelAdmin):
pass
class GoodsSKUAdmin(BaseModelAdmin):
pass
class GoodsAdmin(BaseModelAdmin):
pass
class IndexGoodsBannerAdmin(BaseModelAdmin):
pass
class IndexPromotionBannerAdmin(BaseModelAdmin):
pass
class IndexTypeGoodsBannerAdmin(BaseModelAdmin):
pass
# 注册商品类型模型类
admin.site.register(GoodsType, GoodsTypeAdmin)
# 注册商品SKU模型类
admin.site.register(GoodsSKU, GoodsSKUAdmin)
# 注册商品SPU模型类
admin.site.register(Goods, GoodsAdmin)
# 注册首页幻灯片展示模型类
admin.site.register(IndexGoodsBanner, IndexGoodsBannerAdmin)
# 注册首页促销活动模型类
admin.site.register(IndexPromotionBanner, IndexPromotionBannerAdmin)
# 注册分类商品展示模型类
admin.site.register(IndexTypeGoodsBanner, IndexTypeGoodsBannerAdmin)
8.关于静态页面与django类视图IndexView调度说明
- step1 前面所有的访问操作都是192.168.1.8(主页静态页面,通过Ubuntu nginx服务器返回)以及127.0.0.1:8000(主页动态页面,通过windows django服务器返回),即问题是当用户访问时网站主页时,怎么区分给用户访问静态主页还是动态主页且用户只能输入一个IP地址,不可能一个网站有两个域名IP吧,所以我们设定用户请求的网站地址为192.168.1.8,当用户直接在浏览器中输入http://192.168.1.8/时,就相当于访问 / 就向ngin服务器获取静态主页,当用户输入http://192.168.1.8/index时,就想当于访问 /index 就向django服务器获取类视图中返回的动态主面,因此就可以来判断用户请求的是静态主页还是动态主页,那么为了完成用户请求地址的判断,则需要使用调度服务器(另一个nginx服务器作为请求地址的调度),示意图如下
- step2 修改IndexView的url路由
url(r"^/index$", IndexView.as_view(), name="index"), # 首页
9.设置以及获取首页的缓存数据
- step1 分析
1.把首页用到的数据存放到缓存中
2.当用户请求首页页面数据时,就到redis数据中获取缓存数据
3.如果数据获取不到时,再去数据进行查询,这样做就减少了数据库的查询操作
- step2 在IndexView视图函数中先去获取获取缓存数据,当返回的数据为空时, 则对数据库进行查询操作,并设置缓存数据
def get(self, request):
'''显示首页'''
# 先从缓存中获取主页数据
context = cache.get("index_page_data")
if context is None:
"""缓存中没有数据就去数据库查询获取并设置"""
print("设置主页缓存数据")
# 获取商品的种类信息
types = GoodsType.objects.all()
# 获取首页轮播商品信息
goods_banners = IndexGoodsBanner.objects.all().order_by('index')
# 获取首页促销活动信息
promotion_banners = IndexPromotionBanner.objects.all().order_by('index')
# 获取首页分类商品展示信息
for type in types: # GoodsType
# 获取type种类首页分类商品的图片展示信息
image_banners = IndexTypeGoodsBanner.objects.filter(type=type, display_type=1).order_by('index')
# 获取type种类首页分类商品的文字展示信息
title_banners = IndexTypeGoodsBanner.objects.filter(type=type, display_type=0).order_by('index')
# 动态给type增加属性,分别保存首页分类商品的图片展示信息和文字展示信息
type.image_banners = image_banners
type.title_banners = title_banners
context = {'types': types,
'goods_banners': goods_banners,
'promotion_banners': promotion_banners}
# 设置首页数据的缓存
cache.set("index_page_data", context, 3600)
- step3 使用字段对象中的update方法,向content字段中设置购物车,这个方法是当字典中有这个cart_count键时,则不进行修改,没有这个键则进行添加操作
context.update(cart_count=cart_count)
- step4 当第一次访问http://127.0.0.1:8000/index主页页面时,查看django服务运行日志,成功打印出设置主页缓存数据,第二次访问则没有打印
- step5 查看redis数据
10.更新首页缓存数据
- step1 分析
什么时候需要更新首页中的缓存数据
当后台管理员对主页表数据进行修改时,需要更新主页缓存数据
- step2 在df_goods/admin中BaseModelAdmin中,进行缓存数据的清除
# 清除缓存数据
cache.delete("index_page_data")