Django ORM通过多个模型访问用户表

时间:2014-06-27 17:13:55

标签: django django-orm

views.py

我正在创建一个我想要序列化并作为JSON返回的查询集。查询集如下所示:

all_objects = Program.objects.all()
test_data = serializers.serialize("json", all_objects, use_natural_keys=True)

这会拉回除“用户”模型(两个模型之间的链接)之外的所有内容。

models.py

from django.db import models
from django.contrib.auth.models import User

class Time(models.Model):
    user = models.ForeignKey(User)
    ...

class CostCode(models.Model):
    program_name = models.TextField()        
    ...

class Program(models.Model):
    time = models.ForeignKey(Time)
    program_select = models.ForeignKey(CostCode)
    ...

问题

我的返回数据有Time,Program和CostCode信息,但我无法查询'User'表。如何在同一个查询集中取回“用户名”(来自用户表)?

注意:我已将查询集更改为all_objects = Time.objects.all(),这会获取用户信息,但之后它不会引入“CostCode”。我的模型还有ModelManagers返回get_by_natural_key,因此相关字段显示在我的JSON中。

最终,我希望所有四个模型的数据都出现在我的序列化JSON字段中,我只是缺少'用户名'。

这是一张JSON对象当前如何出现在Firebug中的图片: Firefox's Firebug showing the JSON object

感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

乍一看似乎有点重量级,但你可以看看使用Django REST Framework:
http://www.django-rest-framework.org/api-guide/serializers#modelserializer

您可以定义和使用序列化程序类,而无需对框架执行任何其他操作。序列化程序返回一个python dict,然后可以很容易地转储到JSON。

要将每个相关模型的所有字段作为嵌套dicts,您可以这样做:

class ProgramSerializer(serializers.ModelSerializer):
    class Meta:
        model = Program
        depth = 2

all_objects = Program.objects.all()
serializer = ProgramSerializer(all_objects, many=True)
json_str = json.dumps(serializer.data)

要自定义每个模型包含的字段,您需要为每个模型定义ModelSerializer类,例如仅为username输出time.user

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('username', )

class TimeSerializer(serializers.ModelSerializer):
    """
    specifying the field here rather than relying on `depth` to automatically
    render nested relations allows us to specify a custom serializer class
    """
    user = UserSerializer()

    class Meta:
        model = Time

class ProgramSerializer(serializers.ModelSerializer):
    time = TimeSerializer()

    class Meta:
        model = Program
        depth = 1  # render nested CostCode with default output

all_objects = Program.objects.all()
serializer = ProgramSerializer(all_objects, many=True)
json_str = json.dumps(serializer.data)

答案 1 :(得分:2)

你真正想要的是一个"深的" Django本身不支持的对象的序列化。这是一个常见问题,这里将详细讨论:Serializing Foreign Key objects in Django。对于某些替代方案,请参阅该问题。

通常Django希望您分别序列化Time,CostCode,Program和User对象(即每个对象的单独JSON数组),并通过ID引用它们。 ID可以是数字主键(PK),也可以是"自然"用natural_key定义的键。

您可以使用natural_key返回所需的任何字段,包括user.username。或者,您可以根据需要定义自定义序列化程序输出。这些方法中的任何一种都可能使得无法将数据加载回Django数据库,这对您来说可能不是问题。