【问题标题】:Django ORM access User table through multiple modelsDjango ORM通过多个模型访问User表
【发布时间】:2014-08-18 21:27:35
【问题描述】:

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)
    ...

问题

我返回的数据包含时间、程序和成本代码信息,但我无法查询回“用户”表。我怎样才能在同一个查询集中回复说“用户名”(来自用户表)?

注意:我已将我的查询集更改为all_objects = Time.objects.all(),这会获取用户信息,但它不会拉入“成本代码”。我的模型也有返回 get_by_natural_key 的 ModelManager,因此相关字段出现在我的 JSON 中。

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

这是 JSON 对象当前在 Firebug 中的显示方式:

感谢您的帮助!

【问题讨论】:

    标签: django django-orm


    【解决方案1】:

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

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

    要从每个相关模型中获取所有字段作为嵌套字典,您可以这样做:

    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 类,例如只为 time.user 输出 username

    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)
    

    【讨论】:

      【解决方案2】:

      您真正想要的是 Django 本身不支持的对象的“深度”序列化。这是一个常见的问题,在这里详细讨论:Serializing Foreign Key objects in Django。请参阅该问题以获取一些替代方案。

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

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

      【讨论】:

      • 谢谢安东。我实际上查看了该线程,但找不到最新的解决方案(Wad of Stuff 序列化程序不支持 Django 1.6)。如果我在本周末之前没有更好的答案,我会尽可能接受你的答案。
      猜你喜欢
      • 2014-05-27
      • 1970-01-01
      • 2019-08-13
      • 2019-09-30
      • 1970-01-01
      • 1970-01-01
      • 2019-08-27
      • 2020-08-04
      • 2012-11-30
      相关资源
      最近更新 更多