Django实战(19):自定义many-to-many关系,实现Atom订阅
记得有人跟我说过,rails的has_many :through是一个”亮点“,在Django看来,该功能简直不值一提。rails中的many-to-many关联中,还需要你手工创建关联表(写 migration的方式),而has_many :through的”语法“只不过是为了自定义关联关系:通过一个中间的、到两端都是many-to-one的模型类实现多对多关联。
在Django中,many-to-many的中间关系表是自动创建的,如果你要指定一个自己的Model类作为关系对象,只需要在需要获取对端的
Model类中增加一个ManyToManyField属性,并指定though参数。比如现在我们已经有了这样两个many-to-one关
系,LineItem --->Product, LineItem-->Order,
如果需要从Product直接获取关联的Order,只需要增加一行,最终的Product如下:
class Product(models.Model):
title = models.CharField(max_length=,unique=True)
description = models.TextField()
image_url = models.URLField(max_length=)
price = models.DecimalField(max_digits=,decimal_places=)
date_available = models.DateField()
orders = models.ManyToManyField(Order,through='LineItem')
之后就可以通过product对象直接找到包含该产品的订单:
$ python manage.py shell
>>> from depot.depotapp.models import Product
>>> p = Product(id=)
>>> p.orders >>> p.orders.all()
[, ]
实现这个关系的目的是我们要针对每个产品生成一个”订阅“,用于查看谁买了该产品。我们采用Atom作为格式的标准。生成的Atom发布格式如下:
<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
<id>tag:localhost,:/products//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>-- ::</updated>
<entry>
<id>tag:localhost,:Order/</id>
<published>-- ::</published>
<updated>-- ::</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,:Order/</id>
<published>-- ::</published>
<updated>-- ::</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为格式的,我们可以借助Django REST framework来 实现,但是这不是一个好主意,因为REST framework生成的xml有其自身的格式,与Atom的格式完全不同。如果使用REST framework就需要对其进行定制,甚至要实现一个自己的renderer(比如,AtomRenderer),而这需要深入了解该框架的大量细节。 为了简单起见,我们考虑用Django的模板来实现。
首先我们设计url为:http://localhost:8000/depotapp/product/[id]/who_bought,先在depot/depotapp/urls.py中增加urlpatterns:
(r'product/(?P[^/]+)/who_bought$', atom_of_order)
然后在depot/depotapp/views.py中实现视图函数:
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,使浏览器知道返回的是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,:/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>-- ::</updated>
{% for order in product.orders.all %}
<entry>
<id>tag:localhost,:order/{{order.id}}</id>
<published>-- ::</published>
<updated>-- ::</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发布,确实很简单,不是吗?
Django实战(19):自定义many-to-many关系,实现Atom订阅的更多相关文章
- Django关于设置自定义404和安装debug-toolbar的笔记
Django关于设置自定义404和安装debug-toolbar的笔记 关于设置404 先做好404页面,然后在views.py文件中做好映射,最后是在urls.py做好路由,而这个urls.py必须 ...
- 【SpringBoot】单元测试进阶实战、自定义异常处理、t部署war项目到tomcat9和启动原理讲解
========================4.Springboot2.0单元测试进阶实战和自定义异常处理 ============================== 1.@SpringBoot ...
- 第三百一十四节,Django框架,自定义分页
第三百一十四节,Django框架,自定义分页 自定义分页模块 #!/usr/bin/env python #coding:utf-8 from django.utils.safestring impo ...
- [实战]MVC5+EF6+MySql企业网盘实战(19)——BJUI和ztree
写在前面 上周在博客园看到一篇通用权限系统的文章,看到他那个UI不错,这里就研究了一下,将网盘的UI修改为他的那个,感兴趣的可以参考:http://b-jui.com/ 系列文章 [EF]vs15+e ...
- Django(模板语言-自定义filter和simple_tag)
Django(模板语言-自定义filter和simple_tag) filter过滤器的主要形式:变量|函数,意思是将变量交给函数处理,而自定义filter就是自己定义函数,因为用到已有的很少. ...
- 从零开始部署Django生产环境(适用:《跟老齐学Python Django实战》)
<跟老齐学Python Django实战>作为市面上少有的Django通俗实战书籍,给了我学习Django很大的帮助.作为一名新入门的菜鸟,全书我重复练习了至少三遍,每次都有新的收获. 前 ...
- Django中的自定义过滤器
一.为什么要自定义Django中的自定义过滤器:Django中提供了很多内置的过滤器和标签,详见链接django官网,主要有以下几个: autoescape(自动转义)block(模板继承)csrf_ ...
- Django模板之自定义过滤器/标签/组件
自定义步骤: 1. 在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag. 2. 在app应用中创建templatet ...
- 19、Django实战第19天:课程列表页
从今天开始,我们将完成"公开课"课程的相关功能..... 1.把course-list.html复制到templates目录下 2.这个页面的头部.底部与之前定义的base.htm ...
随机推荐
- core EFCore 开始尝试
准备工作: 工程:core + console 引用包: Install-Package Microsoft.EntityFrameworkCore Install-Package Microsoft ...
- 阮一峰:自适应网页设计(Responsive Web Design)别名(响应式web设计)
随着3G的普及,越来越多的人使用手机上网. 移动设备正超过桌面设备,成为访问互联网的最常见终端.于是,网页设计师不得不面对一个难题:如何才能在不同大小的设备上呈现同样的网页? 手机的屏幕比较小,宽度通 ...
- Android 5.0 最应该实现的8个期望
毫无疑问,Android 5 将是令人兴奋的操作系统,因为 Android4.0 至 4.4 版本之间并没有显著的差异,显然谷歌会在 5.0 版本中进行一些较大幅度的革新.那么,代号为“柠檬芝士蛋糕” ...
- 你知道吗?什么是 Responsive JavaScript ?
Responsive Javascript 是什么? 简单来说就是可以根据浏览器的状态做出响应.响应包括对视窗大小的反应,根据你设备是否支持触摸事件或地理定位功能来决定是否显示特定内容,不一而足. 什 ...
- jquery bxslider幻灯片样式改造
找了很多jquery的幻灯片,都觉得不是很好,最后发现bxslider兼容性最好,移动设备支持手动翻动. 但是官方提供的显示效果真的很难看,让人难以接受.最后只能自己DIY了. bxslider官方样 ...
- Hadoop/Spark环境运行过程中可能遇到的问题或注意事项
1.集群启动的时候,从节点的datanode没有启动 问题原因:从节点的tmp/data下的配置文件中的clusterID与主节点的tmp/data下的配置文件中的clusterID不一致,导致集群启 ...
- 【转】C# Graphics类详解
Brush 类 .NET Framework 4 定义用于填充图形形状(如矩形.椭圆.饼形.多边形和封闭路径)的内部的对象. 属于命名空间: System.Drawing 这是一个抽象基类,不能进行 ...
- 63、使用Timer类来实现定时任务
定时任务 定时任务就是让计算机自动的每隔一段时间执行的代码.比如要实现这样的一个功能:让计算机每隔5秒钟,在控制台打印一个www.monkey1024.com可以使用java.util包下的Timer ...
- Dream------spark--spark集群的环境搭建
1.下载安装scala http://www.scala-lang.org/download/2.11.6.html 2.解压下载后的文件,配置环境变量:编辑/etc/profile文件,添加如下 ...
- 20155303 2016-2017-2 《Java程序设计》第三周学习总结
20155303 2016-2017-2 <Java程序设计>第三周学习总结 教材学习内容总结 第四章 学会如何查询Java API文件对于Java的学习很有帮助,可以了解到如何使用各种方 ...