Home >  > 京东python开发(四)

京东python开发(四)

0

一、数据库中添加目录

(一)修改model

之前的数据库设计中没有考虑商品分类,所以需要新增一个Category的数据库。这个操作本来很简单,就是修改model,然后migrate即可。
但是由于原来数据库中已经存在了数据,所以我做migrate的时候,又提示什么字段不能使用默认值0,报了很多出错的信息,后来我直接将\coupon\migrations下面刚刚生成的py文件都删除了,再来做migrate,不过一下又说某个字段已经建立,一下又说Category表格已经存在,最后又出现如下错误:

django.db.utils.IntegrityError: (1452, 'Cannot add or update a child row: a fore
ign key constraint fails (`jd2`.`#sql-19fc_273`, CONSTRAINT `coupon_goods_catego
ry_id_15d33dd64cbe0dd0_fk_coupon_category_id` FOREIGN KEY (`category_id`) REFERE
NCES `coupon_category` (`id`))')

先不管它,继续。

2018-Aug-05 补记:

第二天给数据表添加新字段,执行python manage.py migrate还是出错,提示category已经存在,不能重复建立,我将建立category的sql命令删除,又提示不能resolve category,后来没办法,我只好将原先建立的数据表删除,然后将migrations文件夹下面,除了__init__.py之外的所有文件全部删除(__pycache__文件夹不要删除,不过里面的相关文件也要删除),

然后再重新执行makemigrations 和migrate命令。没想到还是出错:

后来问了别人,才知道要在数据库中,将migration表的相关记录也删除才行。就是下面这张表,找到app中名称 为你的app名称的记录,删除就可以了。

(二) save 和create
save的时候,建立用create

name = single['cidname']
cid = single['cid']
nameid = Category.objects.create(name=name,namecid=cid)

(三)foreign key的问题

后来我向商品数据表中的商品类别插入商品分类ID的时候,又出现了如下错误:

ValueError: Cannot assign "6144": "Goods.category" must be a "Category" instance.

这里找到解决方案

you need to change your model structure, so you will be rather doing:

scripter = Scripter.objects.get(name="joshua")
book = Book.objects.Create(script_title="some title",scripter=scripter)

按上面的方法修改,又出现了如下的错误:

coupon.models.MultipleObjectsReturned: get() returned more than one Category --
it returned 4!

原来是目录名称重复了,因为我是根据目录的id查找的,返回了4条目录的记录。

(四)文章表中存储文章分类
在文章数据表中,存储是商品分类的ID,我专门进后台发文章测试了一下。

二、修改首页逻辑
将views.py中首页的逻辑由函数改成class。

from django.views.generic import View

class IndexView(View):
    """
    首页
    """
    def get(self, request):
        coupon_list = Goods.objects.all()
        return render(request, 'coupon/index.html', {'coupon_list':coupon_list})

修改urls.py中的配置

url(r'^$', IndexView.as_view(), name='index'),

三、修改一个小按钮

仿的前端页面,有一个按钮,原来是红色的,到了我的网站就变成浅色了。

后来通过将style.css中的

background: url("pic/coupon-btn.png") no-repeat scroll 0 0;

直接改成:

background: #ED145B;

终于显示成红色了。或者直接改成red也行。

四、搜索功能
将category的代码改成以下这样:

def categorylist(request,c_id):
    # 搜索功能
    search_keywords = request.GET.get('keywords', '')
    if search_keywords:
        # icontains是包含的意思(不区分大小写)
        categorylist = all_products.filter(name__icontains=search_keywords)
    else:
        categorylist = all_products.filter(category_id=c_id)
    return render(request, 'coupon/category.html', {'categorylist': categorylist})

再在urls.py中,将原来的代码

url(r'^category/(?P<c_id>\d+)/$',views.categorylist),

改成:

url(r'^category/(.*)',views.categorylist),

然后在模板文件中,将搜索的链接改成

<a href="category/?keywords=秋装" target="_blank">

就可以了。这样不论是点击搜索,还是点击文章的目录,都可以正常跳转了。

五、顶部搜索框
原来想用JS来解决,可是用的别人的JS的代码,有各种问题,包括:
1、在首页可以搜索,在商品详情页、列表页无法搜索。
2、在chrome、IE浏览器下面可以正常搜索,在firefox浏览器下无法使用,点击搜索出现出错页面。
3、修改代码后,在IE浏览器下,跳转网址中出现已经注释过的代码中的跳转网址。

最后,不使用JS,AJAX,直接使用django内置功能完成搜索功能,目前只搜索商品标题。当然,以后有需要,可以使用django-haystack,它支持全文检索、按搜索相关度排序、关键字高亮等功能。

前端测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" type="text/css" media="screen" href="https://cdn.bootcss.com/ionicons/2.0.1/css/ionicons.min.css">
</head>
<body>
<form role="search" method="get" id="searchform" action="{% url 'coupon:search' %}">
  <input type="search" name="q" placeholder="搜索" required>
  <button type="submit"><span class="ion-ios-search-strong"></span></button>
</form>
</body>
</html>

它是长成这样的:

views.py的代码:

def search(request):
    q = request.GET.get('q')
    error_msg = ''

    if not q:
        error_msg = '请输入关键词'
        return render(request, 'coupon/category.html', {'error_msg': error_msg})
    else:
        categorylist = all_products.filter(name__icontains=q)
    return render(request, 'coupon/category.html', {'error_msg': error_msg,
                                               'categorylist': categorylist})

urls.py的代码:

url(r'^search/$', views.search, name='search'),

经测试,在各个页面均测试正常。

六、json loads错误问题
今天执行获取百度相关词的时候,出错了如下的错误:

json.decoder.JSONDecodeError: Invalid \escape: line 1 column 900 (char 899)

经过排查,是某字段中含有“\”符号,导致json loads的时候出错。

于是加了一段代码,直接将“\”给替换掉,暂时解决。

content = content.replace('\\', '')

七、分页功能
使用的是django pure pagination,差一点就没有调试成功了。
其实也很简单,先pip安装,然后在settings.py中添加INSTALLED_APPS,然后再修改views.py

def categorylist(request,c_id):
    #产品列表页
    list_categories = all_categories
    list_product = all_products
    try:
        page = request.GET.get('page', 1)
    except PageNotAnInteger:
        page = 1

    # Provide Paginator with the request object for complete querystring generation
    p = Paginator(list_product,16, request=request)   #这个list_product是全部的商品
    products = p.page(page)                #这个products是传到列表页的
    return render(request, 'coupon/category.html', {'products': products,
                                                     'list_categories':list_categories
                                                    })

最开始的时候,我的这行代码'products': products,写成了'list_product': products,结果前端显示不出来。

然后在前端的页面中,需要这样调用:

 {% for categoryproduct in products.object_list %}

因为前面传过来的是products,所以这里直接抄这行代码就可以了。

然后就是修改下面的分页按钮,结果将代码copy到我的模板文件,浏览时报错:

Exception Value: Invalid block tag: 'trans', expected 'elif', 'else' or 'endif'

原来是要加上{% load i18n %}这段代码才行。

最后没搞出来,直接拿别人的来用了(只要views传过来是products,这里的代码什么都不用改):

<div class="pageturn">
            <ul class="pagelist">
            {% if products.has_previous %}
			<li class="long"><a href="?{{ products.previous_page_number.querystring }}" >上一页</a></li>
            {% endif %}
            {% for page in products.pages %}
            {% if page %}
            {% ifequal page products.number %}
            <li class="active"><a href="?{{ page.querystring }}">{{ page }}</a></li>
            {% else %}
			<li><a href="?{{ page.querystring }}">{{ page }}</a></li>
            {% endifequal %}
			{% else %}
            <li class="none"><a href="">...</a></li>
            {% endif %}
            {% endfor %}
            {% if products.has_next %}
            <li class="long"><a href="?{{ products.next_page_number.querystring }}">下一页</a></li>
            {% endif %}
            </ul>
         </div>

相应的css代码:

	  .pageturn {
		clear: both;
		height: 30px;
		margin: 50px auto;
		display: table;
		text-align: center;
	}

	.pageturn .pagelist {
		display: table-cell;
		vertical-align: middle;
		overflow: hidden;
	}

	.pageturn li {
		width: 30px;
		height: 30px;
		line-height: 30px;
		margin-left: 10px;
		float: left;
		text-align: center;		
	}

	.pageturn li:first-child {
		margin-left: 0;
	}

	.pageturn li:hover a, .pageturn .active a {
		background: #f5114a;
		color: #fff;
		border-color: #eaeaea;
	}

	.pageturn a {
		border: 1px solid #eaeaea;
		display: block;
		height: 28px;
		color: #6c6c6c;
	}

	.pageturn .long {
		width: 100px;
	}

	.pageturn .none a {
		border: 0;
	}

	.pageright {
		float: right;
		width: auto;
		display: inline;
		clear: none;
		margin-top: 10px;
	}

2018-Aug-12:

今天终于将此网站全部开发完成,可以布署上线了。

八、优化搜索页面

搜索页面是套用的产品列表页,搜索结果中也会显示这样的东西:

这里的链接又是根据某一目录排序的,这样对搜索结果其实是不适用的,因为根据某一产品关键字搜索出来的东西很可能属于不同的分类。所以通过以下代码将这部分内容在搜索结果页面隐藏:

       {% ifequal display 1 %}
        <a href="/category/{{c_id}}_1/">
            <li class="yes">券后价最低</li>
        </a>
        <a href="/category/{{c_id}}_2/">
            <li class="yes">优惠最多</li>
        </a>
        <a href="/category/{{c_id}}_3/">
            <li class="yes">销量</li>
        </a>
        {% endifequal %}

即在列表页传一个display=1的参数,这个参数等于1的时候,才会显示if代码块中包含的内容,这样就达到了在搜索结果页面隐藏这部分内容的目的。

九、优化产品列表页面
原来的www.xx.com/list/和www.xx.com/list/1/写了两个函数,而且配置了两条url。

    url(r'^category/(?P<c_id>\d+)/$',views.listdetail),
    url(r'^category/(.*)',views.categorylist),

views.py

def categorylist(request,c_id):
    #产品列表页
    list_categories = all_categories
    list_product = all_products
    sort = request.GET.get('sort', "")
    if sort:
        if sort == "price":
            list_product = all_products.order_by("coupon_price")
        elif sort == "99":
            list_product = all_products.filter(coupon_price__lte=20)
        elif sort == "sales":
            list_product = sale_product
        else:
            sort == "coupon"
            list_product = all_products.order_by("-coupon_amount")
     #分页
    try:
        page = request.GET.get('page', 1)
    except PageNotAnInteger:
        page = 1

    # Provide Paginator with the request object for complete querystring generation
    p = Paginator(list_product,16, request=request)
    products = p.page(page)
    return render(request, 'coupon/category.html', {'products': products,
                                                     'list_categories':list_categories
                                                    })


def listdetail(request,c_id):
    #带分类ID的列表页
    list_categories = all_categories[:14]
    #通过分类ID取得该分类下的所有产品
    list_product = all_products.filter(category_id=int(c_id)).order_by('-add_time')
    sort = request.GET.get('sort', "")
    if sort:
        if sort == "price":
            list_product = list_product.order_by("coupon_price")
        elif sort == "sales":
            list_product = list_product.order_by("sale_amount")
        else:
            sort == "coupon"
            list_product = list_product.order_by("-coupon_amount")
    #分页
    try:
        page = request.GET.get('page', 1)
    except PageNotAnInteger:
        page = 1
    p = Paginator(list_product, 16, request=request)
    products = p.page(page)
    return render(request, 'coupon/category.html', {'products': products,
                                                    'list_categories':list_categories
                                                    })

今天将它优化了一下,合并成了一个函数。

def categorylist(request,c_id,sort):
    """
    产品列表页
    """
    list_categories = all_categories
    display = 1
    #设定一个变量,控制相关html的显示
    if c_id == "0":
    #直接list列表,不带分类ID
        if sort == "0":
        #默认按时间排序
            list_product = all_products
        elif sort == "1":
        #按券后价最低排序
            list_product = all_products.order_by("coupon_price")
        elif sort == "2":
        #按优惠最多排序
            list_product = all_products.order_by("-coupon_amount")
        elif sort == "3":
        #按销量排序排序
            list_product = all_products.order_by("-sale_amount")
        else:       
            return render(request, 'coupon/404.html')   
    else:
    #带分类ID的列表页
        list_categories = all_categories[:14]
        list_product = all_products.filter(category_id=int(c_id)).order_by('-add_time')
        if sort == "0":
            pass
        elif sort == "1":
            list_product = list_product.order_by("coupon_price")
        elif sort == "2":
            list_product = list_product.order_by("-coupon_amount")
        elif sort == "3":
            list_product = list_product.order_by("-sale_amount")
        else:
            return render(request, 'coupon/404.html')
    # 分页
    try:
        page = request.GET.get('page', 1)
    except PageNotAnInteger:
        page = 1
    p = Paginator(list_product, 16, request=request)
    products = p.page(page)
    return render(request, 'coupon/category.html', {'products': products,
                                                    'list_categories': list_categories,
                                                    'c_id':c_id,
                                                    'display':display
                                                    })
本文暂无标签

发表评论

*

*