Django - 返回 JSON,错误

Posted

技术标签:

【中文标题】Django - 返回 JSON,错误【英文标题】:Django - Return JSON, Error 【发布时间】:2013-04-20 12:55:00 【问题描述】:

我有一个看起来像这样的 View.py 函数:

def GetAllCities(request):

cities = list(City.objects.all())
return HttpResponse(json.dumps(cities))

我的城市模型如下所示

class City(models.Model):
    city = models.CharField()
    loc = models.CharField()
    population = models.IntegerField()
    state = models.CharField()
    _id = models.CharField()

    class MongoMeta:
        db_table = "cities"

    def __unicode__(self):
        return self.city

我正在使用一个看起来像这样的 MongoDB


   "_id" : ObjectId("5179837cbd7fe491c1f23227"),
   "city" : "ACMAR",
   "loc" : "[-86.51557, 33.584132]",
   "state" : "AL",
   "population" : 6055

尝试从 GetAllCities 函数返回 JSON 时出现以下错误:

City ACMAR 不是 JSON 可序列化的

所以我尝试了这个:

def GetAllCities(request):

    cities = serializers.serialize("json", City.objects.all())
    return HttpResponse(cities)

这可行,但速度很慢,大约需要 9 秒(我的数据库包含 30000 行) 应该花这么长时间还是我做错了什么? 我用 php、Rails 和 NodeJS 构建了相同的应用程序。 在 PHP 中平均需要 2000 毫秒,NodeJS = 800 毫秒,Rails = 5882 毫秒和 Django 9395 毫秒。我试图在这里进行基准测试,所以我想知道是否有办法优化我的 Django 代码,或者这是否尽可能快?

【问题讨论】:

【参考方案1】:

    当然,您不需要返回所有城市,因为您可能不会显示所有 30000 行(至少以用户友好的方式)。考虑一个解决方案,您只返回请求位置的某个范围内的城市。 Mongo 支持geospatial indexes,所以这样做应该没有问题。网上也有很多关于如何在 Django/MongoDB 中进行空间过滤的教程。

    def GetAllCities(request, lon, lat):
    
        #Pseudo-code
        cities = City.objects.filterWithingXkmFromLonLat(lon, lat).all() 
    
        cities = serializers.serialize("json", cities) 
        return HttpResponse(cities)
    

    如果您真的非常需要所有城市,请考虑缓存响应。城市的位置、名称和人口都不是动态变化的,比方说几秒钟。缓存结果并仅每小时、每天或更长时间重新计算。 Django支持缓存out of the box

    @cache_page(60 * 60)
    def GetAllCities(request):
       (...)
    

【讨论】:

这是一个非常好的答案,但我正在做基准测试,看看我的答案:) 即使你缩短了处理时间,你实际上并没有解决问题。如果您将拥有两倍以上的城市,那么时间将增加两倍。【参考方案2】:

您可以尝试加快速度的另一件事是从 db 中获取您需要的值并获取 QuerySet 来构建字典。

这样一个简单的查询就可以了:

City.objects.all().values('id', 'city', 'loc', 'population', 'state')

或者你可以把它放在一个经理中:

class CitiesManager(models.Manager):

    class as_dict(self):
        return self.all().values('id', 'city', 'loc', 'population', 'state')

class City(models.Model):
    .... your fields here...

    objects = CitiesManager()

然后在你的视图中使用它:

City.objects.as_dict()

【讨论】:

啊啊非常好,试试吧!谢谢【参考方案3】:

找到解决方案

我正在使用不同的方法进行基准测试,一种方法是查看一种语言/框架选择数据库中的所有行并将其作为 JSON 返回的速度。我现在找到了一个解决方案,可以将它的速度提高一半!

我的新观点.py

def GetAllCities(request):

    dictionaries = [ obj.as_dict() for obj in City.objects.all() ]
    return HttpResponse(json.dumps("Cities": dictionaries), content_type='application/json')

还有我的新模型

class City(models.Model):
    city = models.CharField()
    loc = models.CharField()
    population = models.IntegerField()
    state = models.CharField()
    _id = models.CharField()
def as_dict(self):
        return 
            "id": self.id,
            "city": self.city,
            "loc": self.loc,
            "population": self.population,
            "state": self.state
            # other stuff
        

    class MongoMeta:
         db_table = "cities"

def __unicode__(self):
        return self.city

找到解决方案here

【讨论】:

以上是关于Django - 返回 JSON,错误的主要内容,如果未能解决你的问题,请参考以下文章

关于Django中JsonResponse返回中文字典编码错误的解决方案

在 django 1.5 CBV 中返回 HttpResponse 时的 simplejson 错误

在 Django Rest Framework 中找不到资源时返回自定义 404 错误

在 Django 中返回 JSON 响应

安装夹具(SQLite3 数据库)时,cygwin 上的 Django loaddata 命令返回错误

将 django ValuesQuerySet 转换为 json 对象