使用另一个对象(来自不同的查询集)覆盖对象元素(来自queryset)以进行json编码

时间:2013-09-25 15:01:27

标签: python django

请原谅可能变得明显的蟒蛇noobness。这是一个视图功能。它是一个jsonp响应,并且完全按照要求工作,非常出色(一些元素被修改为无关)。

更新:这是我的功能,完整。

class stores(ListView):
    model = Store

    def get_queryset(self):

        args = [Q()]
        output = []

        callback = self.request.GET.get('callback', False)
        region = self.request.GET.get('region', False)
        country = self.request.GET.get('country', False)

        if region:
            args.append(Q(country__region_id=int(region)))

        if country:
            args.append(Q(country=int(country)))

        outputs =  self.model.objects.filter(reduce(operator.and_, args))

        for i, item in enumerate(outputs):
            outputs[i].contacts = pk__in=list(list(Contact.objects.filter(store=item.id).values()))

        return '%s(%s)' % (callback, json) if callback != False else json

这是我从脚本中获得的回复

[{"pk": 2837, "model": "store.store", "fields": {"geolocation": "-30.8040344,111.8395886", "code": "", "logo": "dist/logo/theshop_Sykes_9.jpg", "photo": "", "postcode": "2222/1111", "openinghours": "", "exclude": false, "city": "Perth", "dealer_type": "distrib", "contacts": "[{'phone': u' +1111 7000', 'fax': u'+61 2222 2122', 'type': u'general', 'email': u'notworking@theshop.com'}, {'phone': u'+61 2222 1111', 'fax': u'+61 1111 2222', 'type': u'general', 'email': u'notworking@theshop.com'}]", "servedcountries": [{"lat": "-25.244398", "lng": "132.775136", "name": "Oz"}], "comments": "", "state": "", "latitude": "-31.8040344", "legal_store": "theshop Pty Ltd", "updated": "2013-08-06T15:11:15Z", "street1": "thehouse", "street2": "Landsdale", "street3": "", "phone": "", "address": "The house", "product_type": [], "name": "theshop Pty Ltd", "sectors": "Industrial", "created": "2013-08-06T13:50:48Z", "url": "http://www.theshopsykes.com/", "country": {"lat": "-25.274398", "lng": "133.775136", "name": "Australia"}, "longitude": "115.8395886", "local_store": "theshop Pty Ltd"}}]

将该字符串粘贴到json解码器中,就像http://json.parser.online.fr/

那样

您将看到未正确解析contacts元素。

我尝试过:

outputs[i].contacts = serializers.serialize("json", Contact.objects.filter(distributor=item.id), use_natural_keys=True)

但是我得到了一个错误。

AttributeError: 'unicode' object has no attribute 'name'

这是模型声明,以防它有用。

class Contact(models.Model):
    contact_type = models.CharField('Email Type', max_length='20', choices=(('sales', 'Sales'), ('support', 'Support'), ('general', 'General')), blank=True)
    email = models.EmailField(max_length=200, blank=True)
    phone = models.CharField('Phone Number', max_length=200, blank=True)
    fax = models.CharField('Fax Number', max_length=200, blank=True)
    store = models.ForeignKey(Store)

    def __unicode__(self):
        return self.contact_type

    def natural_key(self):
        return self.contact_type

2 个答案:

答案 0 :(得分:0)

我猜您正在寻找序列化相关对象(联系人,与商店相关)。

由于这是一个非常重要的问题,我建议看看像https://code.google.com/p/wadofstuff/wiki/DjangoFullSerializers这样的东西 - 不确定Django核心中是否还有更新的选项(select_related?)。

干杯,

答案 1 :(得分:0)

史蒂夫,我认为你对序列化如何运作的思考是有缺陷的。我设想了一个从查询集到JSON响应的过程,这是一个两步过程,Django序列化程序可以完成这两个过程。

1)将查询集转换为字符串和数字的字典。 2)将该字典转换为JSON。

第一步比人们想象的更难。例如。序列化程序必须决定序列化哪些属性。例如。如果你在模型上定义一个属性,它们似乎被序列化(否则联系人不会显示)。我期待Django序列化程序只序列化模型字段,但我猜不是!

它还必须决定如何向其他模型展示关系。这称为嵌套,有多种选择:只列出相关模型的主键,或者包括它的序列化版本。人们可以只列出相关模型的主键,或者包含一个或多个深度级别。

-

就解决问题而言,我可以提出两点建议:

  • 正如madflo所说,Django序列化程序可能过于基本,无法满足您的需求。我看看还有什么可用的。就个人而言,我是Django Rest Framework的忠实粉丝;但这可能对你的用例来说太过分了。他们关于嵌套的文档可能仍然有用。
  • 我会很好地了解servedcountriescontacts之间的差异。似乎servedcountries是一个按预期序列化的相关模型,因此找出原因并且contacts不是。包含商店模型的声明会很有帮助。

注:

我对这条线不太确定;我认为你的意思是pk__in_list

outputs[i].contacts = pk__in=list(list(Contact.objects.filter(store=item.id).values()))

无论如何,如果我理解正确,你应该能够用

替换它
outputs[i].contacts = Contacts.objects.filter(store=item.id).values_list('pk', flat=True)