您的位置:首页 > 编程语言 > Go语言

(转)Django ====> 实战学习篇十二 提交订单;自定义many-to-many关系,实现Atom订阅

2012-11-27 15:00 791 查看
原文转载地址:http://blog.csdn.net/thinkinside/article/details/7240914

源代码下载地址:留言写下邮箱地址,一天内会发送给你全部源代码

小结:

通过对实战系列文章进行总结,前边的内容已经基本涵盖了django开发的主要内容:

从需求界面设计开始,创建模型,修改模板,通过scaffold作为开发的起点;

在其基础之上重新定制模板,然后通过对model和form的两个类对用户输入数据进行校验;

涉及到了单元测试???为了提高用户界面开发的效率,更好的实现模板,讨论了对静态资源的管理(css,js,image等);

并且通过模板继承的方式实现了整个站点的统一布局;

作为web应用必不可少的session,演示了如何实现会话;

最后,在这些的基础之上增加了RESTful web service,将jquery集成到django,并且实现了ajax;

有了这些就足以应对django的开发绝大数问题了。

提交订单功能实现:

功能:买方点击“结算”,输入姓名地址等信息,发给卖方一张订单,订单包含买方信息和购物车条目;

model类实现:即增加一个订单类(Order),修改原来的条目(Lineitem),增加到Order的外键,如下:外键就是一个manytoone的one小条目:

class Order(models.Model):
name = models.CharField(max_length=50)
address = models.TextField()
email = models.EmailField()

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


通过scaffold生成一系列丑陋的界面:生成之前一定要备份depotapp下的form urls views ,生成之后进行手工合并,切记。

将模板中的结算标签链接改为映射到生成create_order视图函数:

<a class="btn success" href="{% url depotapp.views.create_order %}">结算</a>
depot/templates/depotapp/store.html


这样两个界面已经链接起来了,自动生成的订单有一下几点:

没有将session中的条目保存到数据库中

也没有清空购物车

没有提交之后跳转回产品目录界面

上边提到的问题都需要解决,主要的修改在creat_order视图函数中,原始视图函数如下:

def create_order(request):
form = OrderForm(request.POST or None)
if form.is_valid():
form.save()
form = OrderForm()

t = get_template('depotapp/create_order.html')
c = RequestContext(request,locals())
return HttpResponse(t.render(c))


关于事务处理:保存订单和保存订单条目应该形成一个事务,事务处理可以通过middleware添加,也可以手工添加,手工添加方式更加灵活,通过在view函数前增加修饰符来实现,三种修饰符可以选择:

@transaction.autocommint  在save()或者delete()的时候自动提交事务
@transaction.commit_on_success 整个view成功后提交事务,否则回滚
@transaction.commit_manually 手动调用commit或rollback


暂时不使用middleware的方式,所以用 @transaction.commit_on_success 实现事务处理,需要引用transaction模块,fromdjango.db import transaction

最终修改的提交订单creat_order view函数如下:

@transaction.commit_on_success
def create_order(request):
form = OrderForm(request.POST or None)
if form.is_valid():
order = form.save()
for item in request.session['cart'].items:
item.order = order
item.save()
clean_cart(request)
return store_view(request)

t = get_template('depotapp/create_order.html')
c = RequestContext(request,locals())
return HttpResponse(t.render(c))


自定义many-to-many关系,实现Atom订阅:

在django中,many-to-many关系表是自己建立的,如果要指定一个自己的model类作为关系对象,只需要在制定的对端model类中增加一个ManyToManyField属性,并且制定through参数;

比如现在我们已经有了两个manytoone关系:order---lineitem , product---lineitem,要通过从product直接获取关系的order只需要增加一行:

orders = models.ManyToManyField(Order, through='LineItem')


通过product直接找到包含该产品的订单:

[shishang@shishang depot]$ python manage.py shell
Python 2.7.3 (default, Jul 24 2012, 10:05:39)
[GCC 4.7.0 20120507 (Red Hat 4.7.0-5)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from depotapp.models import Product
>>> p = Product(id=1)
>>> p
<Product: >
>>> p.orders
<django.db.models.fields.related.ManyRelatedManager object at 0x932278c>
>>> p.orders.all()
[<Order: 石尚>, <Order: shishang>]


实现这个关系的主要目的是我们要针对每个产品生成一个“订阅”,用于查看谁买了该商品,采用Atom作为格式的标准,生成的Atom发布格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
<id>tag:localhost,2005:/products/3/who_bought</id>
<link type="text/html" href="http://localhost:3000/depotapp" rel="alternate"/>
<link type="application/atom+xml" href="http://localhost:8000/depotapp/product/3/who_bought" rel="self"/>
<title>谁购买了《黄瓜的黄 西瓜的西》</title>
<updated>2012-01-02 12:02:02</updated>
<entry>
<id>tag:localhost,2005:Order/1</id>
<published>2012-01-02 12:02:02</published>
<updated>2012-01-02 12:02:02</updated>
<link rel="alternate" type="text/html" href="http://localhost:8000/orders/1"/>
<title>订单1</title>
<summary type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<p>我住在北京</p>
</div>
</summary>
<author>
<name>我是买家</name>
<email>wanghaikuo@gmail.com</email>
</author>
</entry>
<entry>
<id>tag:localhost,2005:Order/3</id>
<published>2012-01-02 12:02:02</published>
<updated>2012-01-02 12:02:02</updated>
<link rel="alternate" type="text/html" href="http://localhost:8000/orders/3"/>
<title>订单3</title>
<summary type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<p>我住在哪里?</p>
</div>
</summary>
<author>
<name>我是买家2</name>
<email>2222b@baidu.com</email>
</author>
</entry>
</feed>


Atom 是XML为格式的,可以借助RESTful实现,但是不是一个好主意,应为RESTful有自身的xml格式,与Atom的格式完全不同,如果使用RESTful就要对其进行定制,实现一个自己的render,这需要深入了解该框架的大量细节,为了简单起见,考虑使用django模板实现;

首先设计url,加入urlpatterns:

(r'product/(?P<id>[^/]+)/who_bought', atom_of_order),


视图函数中实现atom_of_order:

def atom_of_order(request,id):
product = Product.objects.get(id = id)
t = get_template('depotapp/atom_order.xml')
c=RequestContext(request,locals())
return HttpResponse(t.render(c), mimetype='application/atom+xml')

mimetype指定了mimetype使浏览器知道返回的是xml而不是html


最后实现模板:/depot/templates/depotapp/atom_order.xml:

<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
<id>tag:localhost,2005:/product/{{product.id}/who_bought</id>
<link type="text/html" href="{% url depotapp.views.store_view %}" rel="alternate"/>
<link type="application/atom+xml" href="{% url depotapp.views.atom_of_order product.id %}" rel="self"/>
<title>谁购买了《{{product.title}}》</title>
<updated>2012-01-02 12:02:02</updated>
{% for order in product.orders.all %}
<entry>
<id>tag:localhost,2005:order/{{order.id}}</id>
<published>2012-01-02 12:02:02</published>
<updated>2012-01-02 12:02:02</updated>
<link rel="alternate" type="text/html" href="{% url depotapp.views.atom_of_order order.id %}"/>
<title>订单{{order.id}}</title>
<summary type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<p>{{order.address}}</p>
</div>
</summary>
<author>
<name>{{order.name}}</name>
<email>{{order.email}}</email>
</author>
</entry>
{% endfor %}
</feed>


用模板实现Atom发布,其实很简单。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: