我是Python和Django的新手,我只是按照Django Book上的教程,我根据教程创建了三个模型 - Publisher,Author,Book。现在我想获得所有书籍,并将它们编码为JSON字符串。 首先,我只使用djangoproject.com上找到的方法。这是代码:
from django.core import serializers
def getAllBooks(request):
book_list = Book.objects.all()
return HttpResponse(serializers.serialize("json", book_list), content_type="application/json")
它工作正常,但结果是这样的:
[
{
"pk": 1,
"model": "books.book",
"fields": {
"publisher": 1,
"title": "Book One",
"authors" : [3, 4],
"publication_date": "2013-07-01"
}
},
{
"pk": 2,
"model": "books.book",
"fields": {
"publisher": 3,
"title": "Book Two",
"authors" : [5],
"publication_date": "2013-07-05"
}
}
]
我们可以看到authors
和publisher
仅显示ID。然后我在djangoproject.com上阅读了那篇文章。最后,它引入了一个名为natural_key
的方法。通过使用该方法,authors
字段将如下所示:
....
{
"pk": 1,
"model": "books.book",
"fields": {
"publisher": 1,
"title": "Book One",
"authors" : ["Douglas", "Adams"],
"publication_date": "2013-07-01"
}
},
....
它更好,但仍然不是我想要的。我想要的是这个:
[
{
"publisher":{
"website":"http://www.example.com/",
"city":"SYD",
"name":"Publisher",
"country":"AU",
"state":"NSW",
"address":"1 Avenue"
},
"authors":[
{
"first_name":"Eric",
"last_name":"Qian",
"email":"eric@example.com"
},
{
"first_name":"Eric2",
"last_name":"Qian",
"email":"eric2@example.com"
}
],
"publication_date":"01/07/2013",
"title":"Book One"
}
]
authors
和publisher
字段包含所有数据。我通过向所有模型添加一个名为JSONEncode的方法来实现这一目标:
from django.db import models
# Create your models here.
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
def __unicode__(self):
return self.name
class Meta:
ordering = ['name']
def JSONEncode(self):
#init a dictionary
JSONData = {};
#name
JSONData['name'] = self.name
#address
JSONData['address'] = self.address
#city
JSONData['city'] = self.city
#state_province
JSONData['state'] = self.state_province
#country
JSONData['country'] = self.country
#website
JSONData['website'] = self.website
#return the json data
return JSONData
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField()
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
def JSONEncode(self):
#init a dictionary
JSONData = {};
#first_name
JSONData['first_name'] = self.first_name
#last_name
JSONData['last_name'] = self.last_name
#email
JSONData['email'] = self.email
#return the json data
return JSONData
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
def __unicode__(self):
return self.title
class Meta:
ordering = ['title']
def JSONEncode(self):
#init a dictionary
JSONData = {};
#title
JSONData['title'] = self.title
#authors
authors = []
for author in self.authors.all():
authors.append(author.JSONEncode())
JSONData['authors'] = authors
#publisher
JSONData['publisher'] = self.publisher.JSONEncode()
JSONData['publication_date'] = self.publication_date.strftime('%d/%m/%Y')
#return the json data
return JSONData
然后我修改books.views中的代码:
def getAllBooks(request):
book_list = Book.objects.all()
book_list_data = []
for book in book_list:
book_list_data.append(book.JSONEncode())
return HttpResponse(json.dumps(book_list_data), content_type="application/json")
它的效果非常好,但缺点很明显 - 我必须为所有模型编写一个JSONEncode()
函数。所以我想知道Django是否提供了更好的方法来做到这一点?提前谢谢!
答案 0 :(得分:1)
您可以尝试使用Tastypie或django-rest-framework。您可以自定义发出的JSON。虽然它增加了另一层复杂性,但从长远来看它可能会有所回报。
答案 1 :(得分:0)
选项1为Django-piston。通过指定模型字段manually,您可以获得嵌套列表和外键。可能是获得你想要的最快的方法,最小的错误,但不是很灵活。
选项2是否要由您自己以天真的方式进行模型序列化。对于每个模型,定义一个将自身转换为python字典的方法,然后在views.py中使用simplejson.dumps使其成为JSON。这种方法为您提供了完全控制和无限灵活性,可以决定您的JSON结构。稍后您可以使用多继承替换更优雅的解决方案来添加as_dict并定义自己的JsonResponse类。
示例:
# In models.py, add as_dict() method to all models
# Example for class Book
def as_dict(self):
d = {
"id": self.id,
"publisher": self.publisher.as_dict(), # avoid this
"title": self.title,
"publication_date": str(self.publication_date),
"publisher": self.publisher,
"authors": [author.as_dict() for author in self.authors.all()] # avoid this
}
# then in views.py
def getAllBooks(request):
book_list = [book.as_dict() for book in Book.objects.all().select_related()]
return HttpResponse(simplejson.dumps(book_list),
content_type="application/json")
<强>无论其强>
这两种方法都很脏。 您的数据库可能并且可能会因此而挣扎。 Django ORM将生成丑陋的SQL。最好是避免嵌套模型序列化。如果你真的需要它,别忘了select_related()。
祝你好运!