簡體   English   中英

有沒有更好的方法將模型轉換為格式正確的JSON字符串?

[英]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"
        }
    }
]

我們可以看到authorspublisher僅顯示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"
    }
]

authorspublisher字段包括所有數據。 我通過向所有模型添加一個名為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提供了更好的方法嗎? 提前致謝!

您可以嘗試使用Tastypiedjango-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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM