1、父模板和缓存的演示
2、首页的开发
index.html显示
{% extends 'base.html' %}
{% load static %}
{% load cache %}
{% block title %}天天生鲜-首页{% endblock %}
{% 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 %}
{% cache 3600 body %}
{% block body %}
<div class="navbar_con">
<div class="navbar">
<h1 class="fl">全部商品分类</h1>
<ul class="navlist fl">
<li><a href="{% url 'goods:index' %}">首页</a></li>
<li class="interval">|</li>
<li><a href="javascript:alert('待开发!');">手机生鲜</a></li>
<li class="interval">|</li>
<li><a href="javascript:alert('待开发!');">抽奖</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 GoodsBanner %}
<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 PromotionBanner %}
<a href="{{ banner.url }}"><img src="{{ banner.image.url }}" alt=""></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.tltle_banner %}
<a href="{% url 'goods:detail' banner.sku.id %}">{{ banner.sku.name }}</a>
{% endfor %}
</div>
<a href="{% url 'goods:list' type.id 1 %}" class="goods_more fr" id="fruit_more">查看更多 ></a>
</div>
<div class="goods_con clearfix">
<div class="goods_banner fl"><img src="{{ type.image.url }}" alt=""></div>
<ul class="goods_list fl">
{% for banner in type.img_banner %}
<li>
<h4><a href="#">{{ banner.sku.name }}</a></h4>
<a href="{% url 'goods:detail' banner.sku.id %}"><img src="{{ banner.sku.image.url }}" alt=""></a>
<div class="prize">¥ {{ banner.sku.price }}</div>
</li>
{% endfor %}
</ul>
</div>
</div>
{% endfor %}
{% endblock %}
{% endcache %}
detail.html显示
{% extends 'base_detail_list.html' %}
{% load static %}
{% block title %}天天生鲜-商品详情{% endblock %}
{% block main_content %}
<div class="breadcrumb">
<a href="{% url 'goods:index' %}">全部分类</a>
<span>></span>
<a href="{% url 'goods:index' %}">{{ sku.type.name }}</a>
<span>></span>
<a href="#">商品详情</a>
</div>
<div class="goods_detail_con clearfix">
<div class="goods_detail_pic fl"><img src="{{ sku.image.url }}" alt=""></div>
<div class="goods_detail_list fr">
<h3>{{ sku.name }}</h3>
<p>{{ sku.desc }}</p>
<div class="prize_bar">
<span class="show_pirze">¥<em>{{ sku.price }}</em></span>
<span class="show_unit">单 位:{{ sku.unite }}</span>
</div>
<div class="goods_num clearfix">
<div class="num_name fl">数 量:</div>
<div class="num_add fl">
<input type="text" class="num_show fl" value="1">
<a href="javascript:;" class="add fr">+</a>
<a href="javascript:;" class="minus fr">-</a>
</div>
</div>
<div>
<p>其他规格:</p>
<ul>
{% for sku in same_spu_skus %}
<li><a href="{% url 'goods:detail' sku.id %}">{{ sku.name }}</a></li>
{% endfor %}
</ul>
</div>
<div class="total">总价:<em>16.80元</em></div>
<div class="operate_btn">
<a href="javascript:;" class="buy_btn">立即购买</a>
<a href="javascript:;" sku_id="{{ sku.id }}" class="add_cart" id="add_cart">加入购物车</a>
</div>
</div>
</div>
<div class="main_wrap clearfix">
<div class="l_wrap fl clearfix">
<div class="new_goods">
<h3>新品推荐</h3>
<ul>
{% for sku in new_skus %}
<li>
<a href="{% url 'goods:detail' sku.id %}"><img src="{{ sku.image.url }}" alt=""></a>
<h4><a href="#">{{ sku.name }}</a></h4>
<div class="prize">¥{{ sku.price }}</div>
</li>
{% endfor %}
</ul>
</div>
</div>
<div class="r_wrap fr clearfix">
<ul class="detail_tab clearfix">
<li class="active">商品介绍</li>
<li>评论</li>
</ul>
<div class="tab_content">
<dl>
<dt>商品详情:</dt>
<dd>{{ sku.goods.detail|safe }}
</dd>
</dl>
</div>
<div class="tab_content">
<dl>
{% for order in sku_order %}
<dt>评论时间:{{ order.update_time }} 用户名:{{ order.order.user.username }}</dt>
<dd>评论内容:{{ order.comment }}</dd>
{% endfor %}
</dl>
</div>
</div>
</div>
{% endblock %}
{% block bottom %}
<div class="add_jump"></div>
{% csrf_token %}
{% endblock %}
{% block bottomfiles %}
<script type="text/javascript" src="{% static 'js/jquery-1.12.4.min.js' %}"></script>
<script type="text/javascript">
update_goods_amount();
function update_goods_amount() {
// 获取商品的数量和价格
var price = $('.show_pirze').children('em').text();
var count = $('.num_show').val();
// 计算商品的总价
price = parseFloat(price);
count = parseInt(count);
var amount = price * count;
$('.total').children('em').text(amount.toFixed(2) + '元');
}
// 增加商品的数量
$('.add').click(function () {
// 获取商品原油的数目
var count = $('.num_show').val();
count = parseInt(count) + 1;
$('.num_show').val(count);
update_goods_amount();
});
// 减少商品的数量
$('.minus').click(function () {
// 获取商品原油的数目
var count = $('.num_show').val();
count = parseInt(count) - 1;
if (count <= 0) {
count = 1;
}
$('.num_show').val(count);
update_goods_amount();
});
// 手动输入商品的数量
$('.num_show').blur(function () {
// 获取商品原油的数目
var count = $(this).val();
// 校验count是否合法
if (isNaN(count) || count.trim().length == 0 || parseInt(count) <= 0) {
count = 1
}
// 重新设置商品的数目
$(this).val(parseInt(count));
update_goods_amount();
});
// 获取add_cart div元素左上角坐标
var $add_x = $('#add_cart').offset().top;
var $add_y = $('#add_cart').offset().left;
// 获取show_count div元素左上角坐标
var $to_x = $('#show_count').offset().top;
var $to_y = $('#show_count').offset().left;
$('#add_cart').click(function () {
// 获取商品的id和数量
var sku_id = $(this).attr('sku_id');
var count = $('.num_show').val();
var scrf = $('input[name="csrfmiddlewaretoken"]').val();
// 发起请求
$.ajax({
type: 'post',
url: "{% url 'cart:add' %}",
data: {
sku_id: sku_id,
count: count,
csrfmiddlewaretoken: scrf,
},
success: function (data) {
if (data.res === 5) {
$(".add_jump").css({'left': $add_y + 80, 'top': $add_x + 10, 'display': 'block'});
$(".add_jump").stop().animate({
'left': $to_y + 7,
'top': $to_x + 7
},
"fast", function () {
$(".add_jump").fadeOut('fast', function () {
$('#show_count').html(data.total_count);
});
});
} else {
alert(data.errmsg)
}
}
});
})
</script>
{% endblock %}
list.html显示
{% extends 'base_detail_list.html' %}
{% block title %}天天生鲜-商品列表{% endblock %}
{% block main_content %}
<div class="breadcrumb">
<a href="#">全部分类</a>
<span>></span>
<a href="#">{{ type.name }}</a>
</div>
<div class="main_wrap clearfix">
<div class="l_wrap fl clearfix">
<div class="new_goods">
<h3>新品推荐</h3>
<ul>
{% for sku in new_skus %}
<li>
<a href="{% url 'goods:detail' sku.id %}"><img src="{{ sku.image.url }}" alt=""></a>
<h4><a href="{% url 'goods:detail' sku.id %}">{{ sku.name }}</a></h4>
<div class="prize">¥{{ sku.price }}</div>
</li>
{% endfor %}
</ul>
</div>
</div>
<div class="r_wrap fr clearfix">
<div class="sort_bar">
<a href="{% url 'goods:list' type.id 1 %}" {% if sort == 'default' %}class="active" {% endif %}>默认</a>
<a href="{% url 'goods:list' type.id 1 %}?sort=price" {% if sort == 'price' %}class="active" {% endif %}>价格</a>
<a href="{% url 'goods:list' type.id 1 %}?sort=hot" {% if sort == 'hot' %}class="active" {% endif %} >人气</a>
</div>
<ul class="goods_type_list clearfix">
{% for sku in skus_page %}
<li>
<a href="{% url 'goods:detail' sku.id %}"><img src="{{ sku.image.url }}"></a>
<h4><a href="{% url 'goods:detail' sku.id %}">大兴大棚草莓</a></h4>
<div class="operate">
<span class="prize">¥{{ sku.price }}</span>
<span class="unit">{{ sku.price }}/{{ sku.unite }}</span>
<a href="{% url 'goods:detail' sku.id %}" class="add_goods" title="加入购物车"></a>
</div>
</li>
{% endfor %}
</ul>
<div class="pagenation">
{% if skus_page.has_previous %}
<a href="{% url 'goods:list' type.id skus_page.previous_page_number %}?sort={{ sort }}">上一页</a>
{% endif %}
{% for page in skus_page.paginator.page_range %}
{% if page == skus_page.number %}
<a href="{% url 'goods:list' type.id page %}" class="active">{{ page }}</a>
{% else %}
<a href="{% url 'goods:list' type.id page %}">{{ page }}</a>
{% endif %}
{% endfor %}
{% if skus_page.has_next %}
<a href="{% url 'goods:list' type.id skus_page.next_page_number %}?sort={{ sort }}">下一页></a>
{% endif %}
</div>
</div>
</div>
{% endblock %}
search.html显示
{% extends 'base_detail_list.html' %}
{% block title %}天天生鲜-商品搜索结果页面{% endblock %}
{% block main_content %}
<div class="breadcrumb">
<a href="#">{{ query }}</a>
<span>></span>
<a href="#">搜索结果如下:</a>
</div>
<div class="main_wrap clearfix">
<ul class="goods_type_list clearfix">
{% for item in page %}
<li>
<a href="{% url 'goods:detail' item.object.id %}"><img src="{{ item.object.image.url }}"></a>
<h4><a href="{% url 'goods:detail' item.object.id %}">{{ item.object.name }}</a></h4>
<div class="operate">
<span class="prize">¥{{ item.object.price }}</span>
<span class="unit">{{ item.object.price }}/{{ sku.unite }}</span>
<a href="{% url 'goods:detail' item.object.id %}" class="add_goods" title="加入购物车"></a>
</div>
</li>
{% endfor %}
</ul>
{# <div class="pagenation">#}
{# {% if skus_page.has_previous %}#}
{# <a href="{% url 'goods:list' type.id skus_page.previous_page_number %}?sort={{ sort }}">上一页</a>#}
{# {% endif %}#}
{# {% for page in skus_page.paginator.page_range %}#}
{# {% if page == skus_page.number %}#}
{# <a href="{% url 'goods:list' type.id page %}" class="active">{{ page }}</a>#}
{# {% else %}#}
{# <a href="{% url 'goods:list' type.id page %}">{{ page }}</a>#}
{# {% endif %}#}
{# {% endfor %}#}
{# {% if skus_page.has_next %}#}
{# <a href="{% url 'goods:list' type.id skus_page.next_page_number %}?sort={{ sort }}">下一页></a>#}
{# {% endif %}#}
{# </div>#}
</div>
{% endblock %}
base.py编写
from django.db import models
class BaseModel(models.Model):
'''模型抽象基类'''
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now_add=True, verbose_name='更新时间')
delflag = models.BooleanField(default=False, verbose_name='删除标识')
class Meta:
abstract = True
goods.views.py编写
from django.shortcuts import render, redirect, reverse
from django.core.paginator import Paginator
from django.views import View
from goods.models import *
from order.models import OrderGoods
from django_redis import get_redis_connection
# Create your views here.
class IndexView(View):
def get(self, request):
# 获取商品种类
types = GoodsType.objects.all()
# 获取首页轮播商品信息
GoodsBanner = IndexGoodsBanner.objects.all().order_by('index')
# 获取首页活动信息
PromotionBanner = IndexPromotionBanner.objects.all().order_by('index')
# 获取首页分类商品展示信息
for type in types:
type.img_banner = IndexTypeGoodsBanner.objects.filter(
type=type, display_type=1).order_by('index')
type.tltle_banner = IndexTypeGoodsBanner.objects.filter(
type=type, display_type=0).order_by('index')
# 获取购物车商品数量
cart_count = 0
if request.user.is_authenticated:
coon = get_redis_connection('default')
cart_key = 'cart_%d' % request.user.id
cart_count = coon.hlen(cart_key)
# 模板上下文
context = {
'types': types,
'GoodsBanner': GoodsBanner,
'PromotionBanner': PromotionBanner,
'cart_count': cart_count,
}
return render(request, 'index.html', context)
class DetailView(View):
def get(self, request, pk):
# 查询商品id是否存在
try:
sku = GoodsSKU.objects.get(pk=pk)
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')[0:2]
# 获取同一商品spu的其他规格商品
same_spu_skus = GoodsSKU.objects.filter(goods=sku.goods).exclude(pk=pk)
# 获取购物车商品数量
cart_count = 0
if request.user.is_authenticated:
coon = get_redis_connection('default')
cart_key = 'cart_%d' % request.user.id
cart_count = coon.hlen(cart_key)
# 添加用户的历史浏览记录
coon = get_redis_connection('default')
history_key = 'history_%d' % request.user.id
# 移除之前的该商品id
coon.lrem(history_key, 0, pk)
# 把goods_id左侧插入redis列表
coon.lpush(history_key, pk)
# 取用户保存的最新5条信息
coon.ltrim(history_key, 0, 4)
context = {
'sku': sku,
'types': types,
'sku_order': sku_orders,
'new_skus': new_skus,
'cart_count': cart_count,
'same_spu_skus': same_spu_skus
}
return render(request, 'detail.html', context)
class ListView(View):
def get(self, request, type_id, page):
# 获取种类信息
try:
type = GoodsType.objects.get(pk=type_id)
except GoodsType.DoesNotExist:
return redirect(reverse('goods:index'))
types = GoodsType.objects.all()
sort = request.GET.get('sort', 'default')
if sort == 'price':
skus = GoodsSKU.objects.filter(type=type).order_by('price')
elif sort == 'hot':
skus = GoodsSKU.objects.filter(type=type).order_by('sales')
else:
skus = GoodsSKU.objects.filter(type=type).order_by('-id')
paginator = Paginator(skus, 8)
# 对页码进行容错处理
try:
page = int(page)
except Exception:
page = 1
if page > paginator.num_pages:
page = paginator.num_pages
skus_page = paginator.page(page)
# todo 页码的控制
# 1 当总页数小于5页,页面上显示所有页面
# 2 如果当前页是前三页 显示前5页的页码
# 3 如果当前页是后三页码 显示后5页
# 4 其他情况 显示当前页的前两页 当前页 当前页的后两页
num_pages = paginator.num_pages
if num_pages < 5:
pages = range(1, num_pages + 1)
elif page <= 3:
pages = range(1, 6)
elif num_pages - page <= 2:
pages = range(num_pages - 4, num_pages + 1)
else:
pages = range(page - 2, page + 3)
# 获取新品信息
new_skus = GoodsSKU.objects.filter(
type=type).order_by('-create_time')[0:2]
# 获取购物车商品数量
cart_count = 0
if request.user.is_authenticated:
coon = get_redis_connection('default')
cart_key = 'cart_%d' % request.user.id
cart_count = coon.hlen(cart_key)
context = {
'type': type,
'types': types,
'skus_page': skus_page,
'new_skus': new_skus,
'cart_count': cart_count,
'sort': sort,
'pages': pages
}
return render(request, 'list.html', context)
search_index.py编写
# 定义索引类
from haystack import indexes
from goods.models import GoodsSKU
class GoodsSKUIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
def get_model(self):
return GoodsSKU
def index_queryset(self, using=None):
return self.get_model().objects.all()
admin.py编写
from django.contrib import admin
from goods.models import *
# Register your models here.
admin.site.register(GoodsType)
admin.site.register(GoodsSKU)
admin.site.register(Goods)
admin.site.register(GoodsImage)
admin.site.register(IndexGoodsBanner)
admin.site.register(IndexTypeGoodsBanner)
admin.site.register(IndexPromotionBanner)
admins.py编写
import xadmin
from .models import *
class GoodsTypeAdmin(object):
list_display = ['id', 'name', 'logo', 'image']
list_display_links = ['id', 'name']
search_fields = ['name', 'create_time', 'update_time']
list_filter = ['create_time', 'update_time', 'delflag']
class GoodsSKUAdmin(object):
list_display = ['id', 'name', 'detail']
list_display_links = ['id', 'name']
search_fields = ['name', 'create_time', 'update_time']
list_filter = ['create_time', 'update_time', 'delflag']
class GoodsAdmin(object):
list_display = ['id', 'type', 'goods', 'name', 'price', 'unite']
list_display_links = ['id', 'name']
search_fields = ['name', 'create_time', 'update_time']
list_filter = ['create_time', 'update_time', 'delflag']
class GoodsImageAdmin(object):
list_display = ['id', 'sku', 'image']
list_display_links = ['id', 'sku']
search_fields = ['name', 'create_time', 'update_time']
list_filter = ['create_time', 'update_time', 'delflag']
xadmin.site.register(GoodsType, GoodsTypeAdmin)
xadmin.site.register(GoodsSKU, GoodsSKUAdmin)
xadmin.site.register(Goods, GoodsSKUAdmin)
xadmin.site.register(GoodsImage, GoodsImageAdmin)
xadmin.site.register(IndexGoodsBanner)
xadmin.site.register(IndexTypeGoodsBanner)
xadmin.site.register(IndexPromotionBanner)
urls.py编写
扫描二维码关注公众号,回复:
11515357 查看本文章
from django.urls import path, re_path
from . import views
app_name = 'goods'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
re_path(r'^goods/(?P<pk>\d+)$', views.DetailView.as_view(), name='detail'),
re_path(r'^list/(?P<type_id>\d+)/(?P<page>\d+)$', views.ListView.as_view(), name='list')
]