首页访问次数多 不经常更改可以进行页面静态化
把原本动态的页面处理结果保存成html文件,让用户直接访问这个生成出来的静态的html页面
在celery_tasks.tasks.py再定义一个任务函数 使用首页的view函数进行修改
from django.template import loader, RequestContext
from goods.models import GoodsType,IndexGoodsBanner,IndexPromotionBanner,IndexTypeGoodsBanner
from django_redis import get_redis_connection
@app.task
def generate_static_index_html():
'''产生首页静态页面'''
# 获取商品的种类信息
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}
# 使用模板
# 1.加载模板文件,返回模板对象
temp = loader.get_template('static_index.html')
# 2.模板渲染
static_index_html = temp.render(context)
# 生成首页对应静态文件
save_path = os.path.join(settings.BASE_DIR, 'static/index.html')
with open(save_path, 'w') as f:
f.write(static_index_html)
新建模板文件static_base.html去除登录后相关内容
并新建static_index.html使其继承static_base.html 内容与index文件一样
仍需将项目文件放置在celery所在服务器中并进行重新启动celery
celery -A celery_tasks.tasks worker -l info
在djanggo执行
可以在celery所在服务器生成静态文件
sudo vi ./conf/nginx.conf
新添加一个server端口不与之前的重复
添加保存后重启nginx即可
参考文档https://doc.codingdict.com/django/ref/contrib/admin/index.html#modeladmin-methods
goods/admin.py
from django.contrib import admin
from django.core.cache import cache
from goods.models import GoodsType,IndexPromotionBanner,IndexGoodsBanner,IndexTypeGoodsBanner
# Register your models here.
class BaseModelAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
'''新增或更新表中的数据时调用'''
super().save_model(request, obj, form, change)
# 发出任务,让celery worker重新生成首页静态页
from celery_tasks.tasks import generate_static_index_html
generate_static_index_html.delay()
# 清除首页的缓存数据
cache.delete('index_page_data')
def delete_model(self, request, obj):
'''删除表中的数据时调用'''
super().delete_model(request, obj)
# 发出任务,让celery worker重新生成首页静态页
from celery_tasks.tasks import generate_static_index_html
generate_static_index_html.delay()
# 清除首页的缓存数据
cache.delete('index_page_data')
class GoodsTypeAdmin(BaseModelAdmin):
pass
class IndexGoodsBannerAdmin(BaseModelAdmin):
pass
class IndexTypeGoodsBannerAdmin(BaseModelAdmin):
pass
class IndexPromotionBannerAdmin(BaseModelAdmin):
pass
admin.site.register(GoodsType, GoodsTypeAdmin)
admin.site.register(IndexGoodsBanner, IndexGoodsBannerAdmin)
admin.site.register(IndexTypeGoodsBanner, IndexTypeGoodsBannerAdmin)
admin.site.register(IndexPromotionBanner, IndexPromotionBannerAdmin)
将处理计算的结果先临时保存起来,下次使用的时候可以先直接使用,如果没有这个备份的数据,重新进行计算处理
将缓存数据保存在内存中 (本项目中保存在redis中,获取速度快)
cache
修改了数据库的数据,直接删除缓存
缓存要设置有效期
django文档:
https://doc.codingdict.com/django/topics/cache.html
站点级别缓存,将整个网站进行缓存,占用空间大
单个view缓存,页面在不同时间可能会有区别 不太合适
模板片段缓存,最后使用模板 不太合适
使用底层API缓存
from django.core.cache import cache
# http://127.0.0.1:8000
class IndexView(View):
'''首页'''
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}
# 以上内容每个用户都一样 可以设置缓存
# key value timeout
cache.set('index_page_data', context, 3600)
# 获取用户购物车中商品的数目
user = request.user
cart_count = 0
if user.is_authenticated():
# 用户已登录
conn = get_redis_connection('default')
cart_key = 'cart_%d'%user.id
cart_count = conn.hlen(cart_key)
# 组织模板上下文
context.update(cart_count=cart_count)
# 使用模板
return render(request, 'index.html', context)
修改模板文件
{% extends 'base.html' %}
{% load staticfiles %}
{% block title %}天天生鲜-首页{% endblock title %}
{% block topfiles %}
<script type="text/javascript" src="{% static 'js/jquery-1.12.4.min.js' %}">script>
<script type="text/javascript" src="{% static 'js/jquery-ui.min.js' %}">script>
<script type="text/javascript" src="{% static 'js/slide.js' %}">script>
{% endblock topfiles %}
{% block body %}
<div class="navbar_con">
<div class="navbar">
<h1 class="fl">全部商品分类h1>
<ul class="navlist fl">
<li><a href="">首页a>li>
<li class="interval">|li>
<li><a href="">手机生鲜a>li>
<li class="interval">|li>
<li><a href="">抽奖a>li>
ul>
div>
div>
<div class="center_con clearfix">
<ul class="subnav fl">
{% for type in types %}
<li><a href="#model0{
{ forloop.counter }}" class="{
{ type.logo }}">{
{ type.name }}a>li>
{% endfor %}
ul>
<div class="slide fl">
<ul class="slide_pics">
{% for banner in goods_banners %}
<li><a href="{% url 'goods:detail' banner.sku.id %}"><img src="{
{ banner.image.url }}" alt="幻灯片">a>li>
{% endfor %}
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>
{% endfor %}
div>
div>
{% for type in types %}
<div class="list_model">
<div class="list_title clearfix">
<h3 class="fl" id="model0{
{ forloop.counter }}">{
{ type.name }}h3>
<div class="subtitle fl">
<span>|span>
{% for banner in type.title_banners %}
<a href="{% url 'goods:detail' banner.sku.id %}">{
{ banner.sku.name }}a>
{% endfor %}
div>
<a href="#" class="goods_more fr" id="fruit_more">查看更多 >a>
div>
<div class="goods_con clearfix">
<div class="goods_banner fl"><img src="{
{ type.image.url }}">div>
<ul class="goods_list fl">
{% for banner in type.image_banners %}
<li>
<h4><a href="{% url 'goods:detail' banner.sku.id %}">{
{ banner.sku.name }}a>h4>
<a href="{% url 'goods:detail' banner.sku.id %}"><img src="{
{ banner.sku.image.url }}">a>
<div class="prize">¥ {
{ banner.sku.price }}div>
li>
{% endfor %}
ul>
div>
div>
{% endfor %}
{% endblock body %}
创建视图函数
goods/view.py
# http://127.0.0.1:8000
class IndexView(View):
'''首页'''
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}
# 以上内容每个用户都一样 可以设置缓存
# key value timeout
cache.set('index_page_data', context, 3600)
# 获取用户购物车中商品的数目
user = request.user
cart_count = 0
if user.is_authenticated():
# 用户已登录
conn = get_redis_connection('default')
cart_key = 'cart_%d'%user.id
cart_count = conn.hlen(cart_key)
# 组织模板上下文
context.update(cart_count=cart_count)
# 使用模板
return render(request, 'index.html', context)
参考命令:redisdoc.com
修改模板文件
{% extends 'base_user_center.html' %}
{% block right_content %}
<div class="right_content clearfix">
<div class="info_con clearfix">
<h3 class="common_title2">基本信息h3>
<ul class="user_info_list">
<li><span>用户名:span>{
{ user.username }}li>
{% if address %}
<li><span>联系方式:span>{
{ address.phone }}li>
<li><span>联系地址:span>{
{ address.addr }}li>
{% else %}
<li><span>联系方式:span>无默认li>
<li><span>联系地址:span>无默认li>
{% endif %}
ul>
div>
<h3 class="common_title2">最近浏览h3>
<div class="has_view_list">
<ul class="goods_type_list clearfix">
{% for goods in goods_li %}
<li>
<a href="{% url 'goods:detail' goods.id %}"><img src="{
{ goods.image.url }}">a>
<h4><a href="{% url 'goods:detail' goods.id %}">{
{ goods.name }}a>h4>
<div class="operate">
<span class="prize">¥{
{ goods.price }}span>
<span class="unit">{
{ goods.price }}/{
{ goods.unite }}span>
<a href="#" class="add_goods" title="加入购物车">a>
div>
li>
{% empty %}
无历史浏览记录
{% endfor %}
ul>
div>
div>
{% endblock right_content %}
view.py
# /goods/商品id
class DetailView(View):
'''详情页'''
def get(self, request, goods_id):
'''显示详情页'''
try:
sku = GoodsSKU.objects.get(id=goods_id)
except GoodsSKU.DoesNotExist:
# 商品不存在
return redirect(reverse('goods:index'))
# 获取商品的分类信息
types = GoodsType.objects.all()
# 获取商品的评论信息
sku_orders = OrderGoods.objects.filter(sku=sku).exclude(comment='')
# 获取新品信息
new_skus = GoodsSKU.objects.filter(type=sku.type).order_by('-create_time')[:2]
# 获取同一个SPU的其他规格商品
same_spu_skus = GoodsSKU.objects.filter(goods=sku.goods).exclude(id=goods_id)
# 获取用户购物车中商品的数目
user = request.user
cart_count = 0
if user.is_authenticated():
# 用户已登录
conn = get_redis_connection('default')
cart_key = 'cart_%d' % user.id
cart_count = conn.hlen(cart_key)
# 添加用户的历史记录
conn = get_redis_connection('default')
history_key = 'history_%d'%user.id
# 移除列表中的goods_id
conn.lrem(history_key, 0, goods_id)
# 把goods_id插入到列表的左侧
conn.lpush(history_key, goods_id)
# 只保存用户最新浏览的5条信息
conn.ltrim(history_key, 0, 4)
# 组织模板上下文
context = {
'sku':sku, 'types':types,
'sku_orders':sku_orders,
'new_skus':new_skus,
'same_spu_skus':same_spu_skus,
'cart_count':cart_count}
# 使用模板
return render(request, 'detail.html', context)