【问题标题】:Django - Return JSON, ErrorDjango - 返回 JSON,错误
【发布时间】: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 代码,或者这是否尽可能快?

【问题讨论】:

    标签: django json mongodb


    【解决方案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):
         (...)
      

    【讨论】:

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

    【讨论】:

      猜你喜欢
      • 2010-11-02
      • 2012-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-24
      • 1970-01-01
      相关资源
      最近更新 更多