05 商品模块
商品主頁頁面
商品主頁頁面的前端頁面 效果圖如下:
?
后端視圖的業務邏輯處理:
根據前端展示的頁面,后端需要向前端傳送的數據有:
1 后端需要想前端傳送的數據有
2 全部商品額分類信息
3 輪播圖的數據
4 廣告的信息
5 分類商品展示的標題和圖片
6 用戶購物車的信息
視圖 IndexView 函數的代碼如下:
from django.shortcuts import render from django.views.generic import View from .models import GoodsCategory,IndexGoodsBanner,IndexPromotionBanner from .models import IndexCategoryGoodsBannerclass IndexView(View):def get(self,request):# 后端需要想前端傳送的數據有# 全部商品額分類信息# 輪播圖的數據# 廣告的信息# 分類商品展示的標題和圖片# 用戶購物車的信息# 獲取所有的商品分類goods_cate=GoodsCategory.objects.all()# 獲取輪播圖信息index_banner = IndexGoodsBanner.objects.all().order_by("index")# 獲取廣告的信息promotinon_banners=IndexPromotionBanner.objects.all().order_by("index")for category in goods_cate:# 主頁分類商品的標題category_title=IndexCategoryGoodsBanner.objects.filter(category=category,display_type=0)[:4]category.title = category_titlecategory_image=IndexCategoryGoodsBanner.objects.filter(category=category,display_type=1)[:4]category.img = category_image# 先把購物車的數量 設置為0cart_num = 0context = {"goods_cate":goods_cate,"index_banners":index_banner,"promotinon_banners":promotinon_banners,"cart_num":cart_num}return render(request,'index.html',context) View Code?
前端模板商品分類要填充的代碼如下:
<ul class="subnav fl">{% for cate in goods_cate %}<li><a href="#model0{{ forloop.counter }}" class="{{ cate.logo }}">{{ cate.name }}</a></li>{% endfor %} </ul> View Code?
前端模板輪播圖要填充的代碼如下:
<ul class="slide_pics">{% for slide in index_banners %}<li><a href="#"><img src="{{ slide.image.url }}" alt="幻燈片"></a></li>{% endfor %}</ul> View Code?
前端模板活動廣告要填充的代碼如下:
<div class="adv fl">{% for add in promotinon_banners %}<a href="{{ add.url }}"><img src="{{ add.image.url }}"></a>{% endfor %}</div> View Code?
前端模板商品分類展示要填充的代碼如下:
{% for cate in goods_cate %}<div class="list_model"><div class="list_title clearfix"><h3 class="fl" id="model01">{{ cate.name }}</h3><div class="subtitle fl"><span>|</span>{% for title in cate.title %}<a href="#">{{ title.sku.title }}</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="{{ cate.image.url }}"></div><ul class="goods_list fl">{% for img in cate.img %}<li><h4><a href="#">{{ img.sku.name }}</a></h4><a href="#"><img src="{{ img.sku.default_image.url }}"></a><div class="prize">{{ img.sku.price }}</div></li>{% endfor %}</ul></div></div>{% endfor %} View Code可以在前端中判斷用戶是否登陸,如果登陸出現歡迎訪問,沒有則是登陸和注冊
{% if user.is_authenticated %}<div class="login_btn fl">歡迎您:<em>{{ user.username }}</em><span>|</span><a href="{% url 'users:logout' %}">退出</a></div>{% else %}<div class="login_btn fl"><a href="{% url 'users:login' %}">登錄</a><span>|</span><a href="{% url 'users:register' %}">注冊</a></div> {% endif %}在瀏覽器中輸入,就可以顯示后端填充的信息
http://127.0.0.1:8000?頁面靜態化(重點)
把動態模板的頁面渲染一次后,把結果保存下來,存成一個靜態的html文件,就是頁面靜態化,對于不經常變化的動態頁面可以做靜態化處理。
進行靜態化的觸發: 運營人員修改主頁動態數據的時候,進行靜態化處理,就是運營人員修改數據的時候,將生成靜態化的過程交給celery異步完成,不影響任何其他業務。
在celery_tasks/tasks.py中定義生成 靜態化文件的任務
from django.core.mail import send_mail from django.conf import settings from django.template import loader from goods.models import GoodsCategory, IndexGoodsBanner, IndexPromotionBanner from goods.models import IndexCategoryGoodsBanner@app.task def generate_static_index_html():"""生成主頁的靜態html文件"""# 獲取所有的商品分類goods_cate = GoodsCategory.objects.all()# 獲取輪播圖信息index_banner = IndexGoodsBanner.objects.all().order_by("index")# 獲取廣告的信息promotinon_banners = IndexPromotionBanner.objects.all().order_by("index")for category in goods_cate:# 主頁分類商品的標題category_title = IndexCategoryGoodsBanner.objects.filter(category=category, display_type=0)[:4]category.title = category_titlecategory_image = IndexCategoryGoodsBanner.objects.filter(category=category, display_type=1)[:4]category.img = category_image# 先把購物車的數量 設置為0cart_num = 0context = {"goods_cate": goods_cate,"index_banners": index_banner,"promotinon_banners": promotinon_banners,"cart_num": cart_num}# 加載模板template = loader.get_template("static_index.html")# 渲染模板,生成html數據html_data = template.render(context)# 保存產生的靜態html數據file_path = os.path.join(settings.STATICFILES_DIRS[0], "index.html")with open(file_path, "w") as f:f.write(html_data) View Code?對以上的局部代碼進行解釋
from django.template import loader# 加載模板template = loader.get_template("static_index.html")# 渲染模板,生成html數據html_data = template.render(context)# 保存產生的靜態html數據file_path = os.path.join(settings.STATICFILES_DIRS[0], "index.html")with open(file_path, "w") as f:f.write(html_data)把模板渲染過后的數據,寫入到index.html文件中,當瀏覽器訪問主頁的時候就會返回靜態話的文件,減少服務器的壓力。
用于靜態的話的文件是給未登錄的用戶使用的,所以在templates中把index.html文件重新復制一份在當前的目錄下,并命名為static_index.html,
把static_index.html中的判斷用戶是否登陸的代碼刪掉,只留用戶注冊的:
<div class="login_btn fl"><a href="{% url 'users:login' %}">登錄</a><span>|</span><a href="{% url 'users:register' %}">注冊</a> </div>?
?以前的如下所示:
把當前的項目復制到家目錄下(python)
修改nginx的配置文件
sudo vim /usr/local/nginx/conf/nginx.conf?
?
?重啟niginx服務器
sudo /usr/local/nginx/sbin/nginx -s reload開啟celery服務器
cd celery -A celery_tasks.tasks worker --loglevel=info在python manager.py shell 中測試
from celery_tasks.tasks import generate_static_index_html generate_static_index_html.delay()celery會收到任務
?
在python/ttsx/static會生成一個index.html文件
?在瀏覽器中輸入本機的ip地址,會調用靜態化的文件
http://192.168.228.135/?
?
把django中動態處理的頁面和nginx的靜態頁面區分開來,所以把商品頁的路徑改成另外一個:
url(r'^index$',views.IndexView.as_view(),name='index')?
通過改寫admin的管理類調用生成靜態頁面的異步任務
當運營人員對模型類,進行添加和修改的時候就會觸發celery的任務生成靜態的話的文件
通過添加save_model 和delete_model的方法,只要一觸發就會調用celery
在gooods應用中的admin中添加管理器的方法;
from django.contrib import adminfrom goods.models import IndexGoodsBanner, IndexCategoryGoodsBanner, IndexPromotionBanner from goods.models import GoodsCategory from celery_tasks.tasks import generate_static_index_htmlclass BaseModel(admin.ModelAdmin):def save_model(self, request, obj, form, change):obj.save()generate_static_index_html.delay()def delete_model(self, request, obj):"""admin站點在模型刪除數據的時候調用"""# 從數據庫中刪除 obj.delete()# 調用生成靜態頁面的celery異步任務 generate_static_index_html.delay()class IndexPromotionBannerAdmin(BaseModel):pass class GoodsCategoryAdmin(BaseModel):"""商品分類信息的管理類"""# 在這里填充控制amdin站點的展示效果passadmin.site.register(IndexPromotionBanner,IndexPromotionBannerAdmin) admin.site.register(GoodsCategory, GoodsCategoryAdmin) View Code?
在后臺管理頁面把主頁促銷活動的盛夏的順序改為2,保存
一開始的靜態化的順序
觸發celery生成靜態化的順序
使用緩存(重點)
把備份的數據放到內存中,如果下次訪問的時候,如果內存中有就從內存中獲取,如果內存中沒有則django動態的計算數據,然后在設置到緩存中供下次使用
django關于緩存的文檔:http://python.usyiyi.cn/translate/django_182/topics/cache.html
這里我使用的是,訪問緩存
你可以通過 類字典對象django.core.cache.caches.訪問配置在CACHES?設置中的字典類對象
最基本的接口是?set(key,?value,?timeout)?和?get(key):
get(key) 如果沒有取到值則會返回None
from django.core.cache import cache >>> cache.set('my_key', 'hello, world!', 30) >>> cache.get('my_key') 'hello, world!在IndexView的視圖中添加緩存后的代碼如下:
from django.core.cache import cacheclass IndexView(View):def get(self,request):# 后端需要想前端傳送的數據有# 全部商品額分類信息# 輪播圖的數據# 廣告的信息# 分類商品展示的標題和圖片# 用戶購物車的信息# 先從緩存中取數據context=cache.get("index_page_data")if context is None:print("沒有用上緩存的數據,從數據庫中查詢")# 獲取所有的商品分類goods_cate=GoodsCategory.objects.all()# 獲取輪播圖信息index_banner = IndexGoodsBanner.objects.all().order_by("index")# 獲取廣告的信息promotinon_banners=IndexPromotionBanner.objects.all().order_by("index")for category in goods_cate:# 主頁分類商品的標題category_title=IndexCategoryGoodsBanner.objects.filter(category=category,display_type=0)[:4]category.title = category_titlecategory_image=IndexCategoryGoodsBanner.objects.filter(category=category,display_type=1)[:4]category.img = category_imagecontext = {"goods_cate":goods_cate,"index_banners":index_banner,"promotinon_banners":promotinon_banners,}# 把數據放到緩存中cache.set('index_page_data',context,3600)# 先把購物車的數量 設置為0cart_num = 0context.update(cart_num=0)return render(request,'index.html',context) View Code?
在redis中查詢緩存的數據,第一次沒有
在瀏覽器中訪問主頁的視圖:
http://127.0.0.1:8000/index?
在redis中查詢緩存的數據,會發現多了一條緩存數據
設置有效期和admin管理類來維護緩存數據?
1 在更新數據庫的時候把緩存刪掉
cash.delete("index_page_data")2 設置緩存的有效期
cache.set("index_page_data", context, 3600)在admin中添加刪除緩存的方法
from django.core.cache import cacheclass BaseAdmin(admin.ModelAdmin):"""admin站點的模型管理類,可以控制admin站點對于模型的展示修改等操作"""def save_model(self, request, obj, form, change):"""admin站點在模型保存數據的時候調用"""# obj是要保存的模型對象(models里的類的對象)# 將數據保存到數據庫中 obj.save()# 調用生成靜態頁面的celery異步任務 generate_static_index_html.delay()# 清除主頁的緩存數據cache.delete("index_page_data")def delete_model(self, request, obj):"""admin站點在模型刪除數據的時候調用"""# 從數據庫中刪除 obj.delete()# 調用生成靜態頁面的celery異步任務 generate_static_index_html.delay()# 清除主頁的緩存數據cache.delete("index_page_data") View Code判斷用戶是否是登陸的狀態,如果是,則從購物車中獲取數據:
用戶購物車在redis中存入的格式是哈希類型"cart_user_id":{"鍵":"值"},商品的id當成鍵,商品的數量當做值
from django_redis import get_redis_connection # 用戶如果是登陸的情況從redis中獲取購物車的數量if request.user.is_authenticated():redis_con = get_redis_connection("default")# cart是一個字典對象 {"sku_1":"1",'sku_2':'3' ---}cart = redis_con.hgetall('cart_%s' % request.user.id)# 遍歷疊加for count in cart.values():cart_num += int(count)context.update(cart_num=cart_num)?
?把以上的代碼添加到商品主頁的視圖IndexViews中:
class IndexView(View):def get(self,request):# 后端需要想前端傳送的數據有# 全部商品額分類信息# 輪播圖的數據# 廣告的信息# 分類商品展示的標題和圖片# 用戶購物車的信息# 先從緩存中取數據context=cache.get("index_page_data")if context is None:print("沒有用上緩存的數據,從數據庫中查詢")# 獲取所有的商品分類goods_cate=GoodsCategory.objects.all()# 獲取輪播圖信息index_banner = IndexGoodsBanner.objects.all().order_by("index")# 獲取廣告的信息promotinon_banners=IndexPromotionBanner.objects.all().order_by("index")for category in goods_cate:# 主頁分類商品的標題category_title=IndexCategoryGoodsBanner.objects.filter(category=category,display_type=0)[:4]category.title = category_titlecategory_image=IndexCategoryGoodsBanner.objects.filter(category=category,display_type=1)[:4]category.img = category_imagecontext = {"goods_cate":goods_cate,"index_banners":index_banner,"promotinon_banners":promotinon_banners,}# 把數據放到緩存中cache.set('index_page_data',context,3600)# 先把購物車的數量 設置為0cart_num = 0# 用戶如果是登陸的情況從redis中獲取購物車的數量if request.user.is_authenticated():redis_con = get_redis_connection("default")# cart是一個字典對象 {"sku_1":"1",'sku_2':'3' ---}cart = redis_con.hgetall('cart_%s' % request.user.id)# 遍歷疊加for count in cart.values():cart_num += int(count)context.update(cart_num=cart_num)return render(request,'index.html',context) View Code商品詳情頁面視圖
商品詳情頁面的前端頁面:
?
?
根據前端的頁面后端業務邏輯如下:
1 查詢全部商品分類的信息
2 查詢商品表的信息
3 獲取最新的推薦商品2個同類商品
4 獲取其他規格的商品
5 從訂單中獲取評論信息
6 購物車數量
7 設置用戶的瀏覽歷史的記錄
?
對上面的代碼進行解析
添加5條最新的瀏覽歷史記錄
添加商品id的時候,先把購物車中包含本次的商品ID移除? ?(lrem("history_%s" % user_id, 0, sku_id))? 0代表刪除所有??
再把現在的添加進去
通過lrim只保存5條歷史信息
# 瀏覽記錄 # 移除已經存在的本商品瀏覽記錄 redis_conn.lrem("history_%s" % user_id, 0, sku_id) # 添加新的瀏覽記錄 redis_conn.lpush("history_%s" % user_id, sku_id) # 只保存最多5條記錄 redis_conn.ltrim("history_%s" % user_id, 0, 4)?
把所有能改成{%url "goods:detail" sku.id%}都改成這樣的(商品詳情頁)
可以隨便點進一個詳情頁面,然后取uers/info中去查看歷史記錄有沒有設置成功(獲取redis中查看)
為詳情的頁面設置緩存
就添加幾句代碼
class DetailView(View):def get(self, request,sku_id):# 查詢全部商品分類的信息# 查詢商品表的信息# 獲取最新的推薦商品2個同類商品# 獲取其他規格的商品# 從訂單中獲取評論信息# 購物車數量# 設置用戶的瀏覽歷史的記錄context = cache.get("detail_data_%s" % requset.user.id)if context is None:goods_cate =GoodsCategory.objects.all()# 查詢商品的信息try:sku = GoodsSKU.objects.get(id=sku_id)except GoodsSKU.DoesNotExist:# raise Http404('商品不存在')return redirect(reverse("goods:index"))# 獲取最新的推薦商品2個同類商品new_goods = GoodsSKU.objects.filter(category=sku.category).order_by("-create_time")[:2]# 獲取其他規格的商品goods_skus = sku.goods.goodssku_set.exclude(id=sku_id)# 從訂單中獲取評論信息sku_orders=sku.ordergoods_set.all().order_by("-create_time")[:30]if sku_orders:for sku_order in sku_orders:sku_order.create_time = sku_order.create_time.strftime("%Y-%m-%d %H-%M-%S")sku_order.username = sku_order.order.user.usernameelse:sku_orders=[]context = {"goods_cate": goods_cate,"sku": sku,"new_goods": new_goods,"goods_skus": goods_skus,"orders":sku_orders}# 設置緩存cache.set("detail_data_%s" % requset.user.id,context,3600)# 購物車數量cart_num = 0# 如果是登錄的用戶if request.user.is_authenticated():user_id = request.user.id# 從redis中獲取購物車信息redis_conn = get_redis_connection("default")# 如果redis中不存在,會返回0cart = redis_conn.hgetall("cart_%s" % user_id)for val in cart.values():cart_num += int(val)# 瀏覽記錄# 移除已經存在的本商品瀏覽記錄redis_conn.lrem("history_%s" % user_id, 0, sku_id)# 添加新的瀏覽記錄redis_conn.lpush("history_%s" % user_id, sku_id)# 只保存最多5條記錄redis_conn.ltrim("history_%s" % user_id, 0, 4)context.update({"cart_num": cart_num})return render(request,'detail.html',context) View Code?
?
轉載于:https://www.cnblogs.com/aaronthon/p/9347818.html
總結
- 上一篇: 配置防盗链、 访问控制Directory
- 下一篇: http1.1科普