Django实战(18):提交订单

前面的内容已经基本上涵盖了Django开发的主要方面,我们从需求和界面设计出发,创建模型修改模型,并通过scaffold作为开发的起点;在scaffold的基础上重新定制模板,并且通过Model类和Form类对用户输入的数据进行校验。我们也涉及到了单元测试。为了提高开发用户界面的效率,更好地实现模板,我们还讨论了对静态资源(css,js,image等)的管理,并通过模板继承的方式实现了整个站点的统一布局。作为web应用必不可少的部分,我们还演示了如何使用会话(session)。最后,我们还在这些基础上增加了RESTful web service将jquery集成到Django,并实现了ajax

有了这些基础,可以应付Django开发中的绝大多数问题。

 

下面我们继续实现depot购物车的web应用。本节要实现提交订单功能。现在买方已经可以挑选需要的产品放入购物车,但是还不能进行购买。我们希望实现这样的功能:

买方点击”结算“按钮,然后输入姓名、地址和email信息,就向卖方发出了一张订单,该订单包含上述买方信息和其选购的所有条目。首先还是实现Model类。我们要增加一个订单类(Order),并修改原来的条目类(LineItem,增加到Order的外键(即LineItem到Order的many-to-one关联)。如下:

 

[python] view plaincopy
  1. class Order(models.Model):
  2. name = models.CharField(max_length=50)
  3. address = models.TextField()
  4. email = models.EmailField()
  5. class LineItem(models.Model):
  6. product = models.ForeignKey(Product)
  7. order = models.ForeignKey(Order)
  8. unit_price = models.DecimalField(max_digits=8,decimal_places=2)
  9. quantity = models.IntegerField()

要注意,因为LineItem引用了Order,所以在定义模型类的顺序上要将Order放在前面。

 

前面介绍过修改模型类之后应该如何处理,这里就不再重复了。

然后祭出scaffold,快速生成一系列”丑陋“的界面。该工具还不够成熟,在生成之前,一定要备份depotapp/urls.py 、views.py 和 forms.py,之后手工合并,切记!

之后将产品目录界面(depot/templates/depotapp/store.html)中的”结算“标签的链接改为映射到生成的create_order视图函数:

 

  1. <aclass="btn success"href="{% url depotapp.views.create_order %}">结算</a>

两 个界面就链接起来了。但是自动生成的订单界面并没有将session中的条目保存到数据库,也没有清空购物车,并且提交订单后没有返回到产品目录界面,所 以还要对其进行修改。主要的修改在create_order视图函数中进行。为了方便对比,将生成的原始视图函数列出如下:

 

 

[python] view plaincopy
  1. def create_order(request):
  2. form = OrderForm(request.POST orNone)
  3. if form.is_valid():
  4. form.save()
  5. form = OrderForm()
  6. t = get_template('depotapp/create_order.html')
  7. c = RequestContext(request,locals())
  8. return HttpResponse(t.render(c))

关于事务处理

 

”保存订单“和”保存订单条目“应该形成一个事务。Django的事务处理可以通过middleware自动添加,也可以手工添加。手工添加的方式更加灵活,通过在view函数前增加修饰符(decorator)来实现,有三种修饰符可以选择:

 

  1. @transaction.autocommit     在 save() 或 delete() 时自动提交事务。
  2. @transaction.commit_on_success   当整个view成功后提交事务,否则回滚( TransactionMiddleware采用的就是这种机制)
  3. @transaction.commit_manually  需要手动调用commit或rollback。

 

我们暂时不想使用middleware的方式,所以用@transaction.commit_on_success来实现事务管理。这需要引用transaction模块:from django.db import transaction

最终修改的create_order视图函数如下:

 

[python] view plaincopy
  1. @transaction.commit_on_success
  2. def create_order(request):
  3. form = OrderForm(request.POST orNone)
  4. if form.is_valid():
  5. order = form.save()
  6. for item in request.session['cart'].items:
  7. item.order = order
  8. item.save()
  9. clean_cart(request)
  10. return store_view(request)
  11. t = get_template('depotapp/create_order.html')
  12. c = RequestContext(request,locals())
  13. return HttpResponse(t.render(c))

 

posted @ 2012-02-19 23:03  心内求法  阅读(6946)  评论(4编辑  收藏  举报