2013-04-26 58 views
1

我得到了一个View.py功能,看起来像这样:Django的 - 返回JSON,错误

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时收到以下错误:

市ACMAR不是JSON序列化

所以,我想这个代替:

def GetAllCities(request): 

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

而这个工作,但它是非常缓慢的,它需要大约9秒(我的数据库包含了30000行) 应该它需要这么长时间还是我做错了什么? 我已经在PHP,Rails和NodeJS中构建了相同的应用程序。 在PHP中,平均需要2000ms,NodeJS = 800ms,Rails = 5882ms和Django 9395ms。我试图在这里进行基准测试,所以我不知道是否有一种方法来优化我的Django代码,或者它是如此快速?

回答

0

FOUND A SOLUTION

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

我的新views.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

1
  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) 
    
  2. 如果你真的真的需要所有城市,请考虑缓存响应。城市的位置,名称和人口并不是动态变化的事物,而是让我们说秒。缓存结果并仅重新计算每小时,每天或更多。 Django支持缓存out of the box

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

这确实是一个很好的答案,但我标杆,请参阅我的回答:) – JOSEFtw 2013-04-26 12:25:35

+0

即使您缩短了处理时间,但实际上并没有解决了这个问题。如果你有两倍多的城市,时间会增加两倍。 – 2013-04-26 13:47:15

0

另一件事你可以尝试争取多一点的速度是从数据库中你需要的值来获得,并得到查询集来构建字典。

这样一个简单的查询将工作:

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() 
+0

Aaah非常好,愿意尝试!谢谢 – JOSEFtw 2013-04-26 12:17:00