[英]Is there a better way to convert a Model to a well formatted JSON string?
我是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()
很明顯-我必須為所有模型編寫一個JSONEncode()
函數。 所以我想知道Django提供了更好的方法嗎? 提前致謝!
您可以嘗試使用Tastypie或django-rest-framework 。 您可以自定義發出的JSON。 雖然它增加了另一層復雜性,但從長遠來看可能會有所回報。
選項1是Django-piston 。 通過手動指定模型字段,您可以獲取嵌套列表和后續的外鍵。 可能是最快的方式來獲得所需的東西,將錯誤減少到最小,但並不真正靈活。
選項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()。
祝好運!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.