Django實戰(13):在session中保存購物車


現在,我們有了一個產品目錄界面,用戶如果看到滿意的產品,就可以將其放入購物車。下面就讓我們來實現購物車的功能。

 

首先要做一下簡單的分析和設計。購物車應該顯示一系列產品的清單,其中列出了買方選中的產品。但是這個清單沒有必要馬上保存到數據庫,因為直到付款之前,用戶隨時都有可能改變主意。我們只需要在用戶的session中記錄這些產品就可以了。

購物車中的條目
購物車中的條目與產品(Product)很 類似,但是我們沒有必要將這些信息再重復記錄一次,而只需要讓條目關聯到產品即可。此外在條目中還會記錄一些產品中沒有的信息,比如數量。最后,我們想要 在條目中記錄一下單價——雖然產品中包含了價格信息,但是有時候可能會有一些折扣,所以需要記錄下來用戶購買時的價格。基於這些分析,我們設計了條目這一 模型類:

 

 
class LineItem(models.Model):
    product = models.ForeignKey(Product)
    unit_price = models.DecimalField(max_digits=8,decimal_places=2)
    quantity = models.IntegerField()

 


購物車
購物車是這些條目的容器。我們希望實現一個“聰明的”購物車,它可以有自己的一些行為:比如,如果放入已經有的產品,就更改該產品的數量而不是再增加一個 條目;能夠查詢當前購物車中的產品數量,等等。所以購物車也應該是一個模型類。但是與LineItem不同,購物車並不需要記錄到數據庫中,就好像超市並 不關注顧客使用了哪量購物車而只關注他買了什么商品一樣。所以購物車不應該繼承自models.Model,而僅僅應該是一個普通類:

    class Cart(object):
    def __init__(self, *args, **kwargs):
    self.items = []
    self.total_price = 0
    def add_product(self,product):
    self.total_price += product.price
    for item inself.items:
    if item.product.id == product.id:
    item.quantity += 1
    return
    self.items.append(LineItem(product=product,unit_price=product.price,quantity=1))

 


在我們設計模型的同時,界面設計師也為我們設計好了購物車的界面:

 

接下來就可以實現url映射,view函數和模板。首先我們希望購物車的url為”http://localhost:8000/depotapp/cart/view/“,這需要在depotapp/urls.py的urlpatterns中增加一行:

    (r'cart/view/', view_cart),

 

然后在depotapp/views.py中定義視圖函數。注意購物車是保存在session中的,需要通過request.session.get獲取:

 

    def view_cart(request):
    cart = request.session.get("cart",None)
    t = get_template('depotapp/view_cart.html')
    ifnot cart:
    cart = Cart()
    request.session["cart"] = cart
    c = RequestContext(request,locals())
    return HttpResponse(t.render(c))

 

最后實現模板界面:

    {% extends "base.html" %}
    {% block title %} 我的購物車{% endblock %}
    {% block pagename %} 我的購物車  {% endblock %}
    {% block content %}
    <divclass="row">
    <divclass="span10">
    <tableclass="condensed-table">
    <thead>
    <tr>
    <thclass="header">數量</th>
    <thclass="yellow header">名稱</th>
    <thclass="blue header">單價</th>
    <thclass="green header">小計</th>
    </tr>
    </thead>
    <tbody>
    {% for item in cart.items %}
    <tr>
    <th>{{item.quantity}}</th>
    <td>{{item.product.title}}</td>
    <td>{{item.unit_price}}</td>
    <td>{% widthratio item.quantity 1 item.unit_price %} </td>
    </tr>
    {% endfor %}
    <tr>
    <th></th>
    <td></td>
    <th>總計:</th>
    <th>{{cart.total_price}}</th>
    </tr>
    </tbody>
    </table>
    </div>
    <divclass="span4">
    <p><aclass="btn primary span2"href="#">繼續購物</a></a></p>
    <p><aclass="btn danger span2"href="#">清空購物車</a></p>
    <p><aclass="btn success span2"href="#">結算</a></p>
    </div>
    </div>
    {% endblock %}

 

這里面有一個技巧。因為Django模板的設計理念是”業務邏輯應該和表現邏輯相對分開“,所以在Django模板中不建議執行過多的代碼。在計算 條目小計的時候,使用的是Django模板的widthratio標簽。該標簽的原意是按比例計算寬度:根據當前值(this_value)和最大值 (max_value)之間的比例,以及最大寬度(max_width)計算出當前的寬度(this_width),即{% widthratio this_value max_value max_width %} = max_width * this_value / max_value。但是如果我們設定max_value=1,就可以通過width ratio在Django模板中進行乘法計算了。同理還可以進行除法計算。而總計價格的計算是通過模型(Cart)類實現的。

為Django增加session支持

好了,我們已經做了大量的工作,現在讓我們欣賞一下自己的作品。但是啟動server並訪問http://localhost:8000 /depotapp/cart/view/時,卻提示”找不到django_session表“。這是因為Django對session的支持是通過內置 的django.contrib.sessions應用實現的,該應用會將session數據保存在數據庫中。但是創建project是Django並沒 有默認安裝該app——Django不會瞞着你做任何事情。所以如果我們”顯式地“決定要使用session,需要更改project的設置,在 depot/settings.py的INSTALLED_APPS中去掉session的注釋:

 

    INSTALLED_APPS = (
    #'django.contrib.auth',
    #'django.contrib.contenttypes',
    'django.contrib.sessions',
    #'django.contrib.sites',
    #'django.contrib.messages',
    #'django.contrib.staticfiles',
    # Uncomment the next line to enable the admin:
    # 'django.contrib.admin',
    # Uncomment the next line to enable admin documentation:
    # 'django.contrib.admindocs',
    'depot.depotapp',
    'django-groundwork',
    )

 


然后還要同步一下數據庫:

 

$ python manage.py syncdb
Creating tables ...
Creating table django_session
Installing custom SQL ...
Installing indexes ...
No fixtures found.

這是再啟動服務器,就可以看到我們實現的購物車了。但是這個購物車能看不能用,無法將商品加入購物車,也無法從中去掉商品。下一節,讓我們繼續完善購物車的功能。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM