尝试序列化使用 select_related 的查询集——无法获取外键模型的字段

Trying to serialize a queryset that uses select_related -- Can't obtain fields of foreignkey model

我在执行查询时能够访问正确的字段 ('author.username')。

但是如果我 运行 通过序列化程序进行相同的查询,它不会打印出 select_related 模型字段。

我应该指定所有字段,加上外键模型的附加字段吗?

views.py

query = Chat.objects.select_related('author').filter(id=chat.id)
print(query)    # [<Chat: 108>]
print(query[0]) # 108
print(query[0].author.username) # superman



context = serializers.serialize("json", Chat.objects.select_related('author').filter(id=chat.id))
print("---------")
print(context) # [{"model": "chats.chat", "pk": 108, "fields": {"author": 29, "text": "this is a message", "chatroom": 11, "written_at": "2016-01-07T23:03:28.968Z"}}]

--- 已更新 --- views.py

context = ChatSerializer(chat)

# output
{u'text': u'come on', u'chatroom': OrderedDict([(u'id', 11), ('created_at', u'2016-01-07T00:27:28.391467Z'), ('creator', 29), ('participant', 1)]), u'written_at': u'2016-01-08T01:12:20.310776Z', u'author': OrderedDict([(u'id', 29), ('password', u'pbkdf2_sha256000$h0whlzx0BleTcUWdRkUsPYB7Ia6F+pYxX+31BMhJJfpWiLHfoL9NOY='), ('last_login', u'2016-01-07T00:26:37.907507Z'), ('email', u'superman@gmail.com'), ('username', u'superman'), ('first_name', u'clark'), ('last_name', u'kent'), ('is_active', True), ('is_admin', False), ('joined_on', u'2016-01-06T23:57:43.191484Z'), ('is_online', False), ('is_contractor', False), ('profile_pic', '/media/bicycle_z3NDBPI.jpeg'), ('braintree_id', u'20401140'), ('braintree_client_token', u'eyJ2ZXJzaW9uIjoyLCJhdXRob3JpemF0aW9uRmluZ2VycHJpbnQiOiI1MjIxM2UwZDQ4OGM0MmFkNTYzY2IzMDJlMDBkMmIyMWIwZWEzYzBiNWEzZTg2ZmNhMmJlNWM3MTI5YjNmNGJifGNyZWF0ZWRfYXQ9MjAxNi0wMS0wNlQyMzo1Nzo0NC42MTgzNzQ2NTgrMDAwMFx1MDAyNmN1c3RvbWVyX2lkPTIwNDAxMTQwXHUwMDI2bWVyY2hhbnRfaWQ9ZGZ6amRrdHM1ZnNxeXF0alx1MDAyNnB1YmxpY19rZXk9ZGtta245cDNjNTQzZGhudyIsImNvbmZpZ1VybCI6Imh0dHBzOi8vYXBpLnNhbmRib3guYnJhaW50cmVlZ2F0ZXdheS5jb206NDQzL21lcmNoYW50cy9kZnpqZGt0czVmc3F5cXRqL2NsaWVudF9hcGkvdjEvY29uZmlndXJhdGlvbiIsImNoYWxsZW5nZXMiOltdLCJlbnZpcm9ubWVudCI6InNhbmRib3giLCJjbGllbnRBcGlVcmwiOiJodHRwczovL2FwaS5zYW5kYm94LmJyYWludHJlZWdhdGV3YXkuY29tOjQ0My9tZXJjaGFudHMvZGZ6amRrdHM1ZnNxeXF0ai9jbGllbnRfYXBpIiwiYXNzZXRzVXJsIjoiaHR0cHM6Ly9hc3NldHMuYnJhaW50cmVlZ2F0ZXdheS5jb20iLCJhdXRoVXJsIjoiaHR0cHM6Ly9hdXRoLnZlbm1vLnNhbmRib3guYnJhaW50cmVlZ2F0ZXdheS5jb20iLCJhbmFseXRpY3MiOnsidXJsIjoiaHR0cHM6Ly9jbGllbnQtYW5hbHl0aWNzLnNhbmRib3guYnJhaW50cmVlZ2F0ZXdheS5jb20ifSwidGhyZWVEU2VjdXJlRW5hYmxlZCI6ZmFsc2UsInBheXBhbEVuYWJsZWQiOnRydWUsInBheXBhbCI6eyJkaXNwbGF5TmFtZSI6ImthbGxhcm9vIiwiY2xpZW50SWQiOm51bGwsInByaXZhY3lVcmwiOiJodHRwOi8vZXhhbXBsZS5jb20vcHAiLCJ1c2VyQWdyZWVtZW50VXJsIjoiaHR0cDovL2V4YW1wbGUuY29tL3RvcyIsImJhc2VVcmwiOiJodHRwczovL2Fzc2V0cy5icmFpbnRyZWVnYXRld2F5LmNvbSIsImFzc2V0c1VybCI6Imh0dHBzOi8vY2hlY2tvdXQucGF5cGFsLmNvbSIsImRpcmVjdEJhc2VVcmwiOm51bGwsImFsbG93SHR0cCI6dHJ1ZSwiZW52aXJvbm1lbnROb05ldHdvcmsiOnRydWUsImVudmlyb25tZW50Ijoib2ZmbGluZSIsInVudmV0dGVkTWVyY2hhbnQiOmZhbHNlLCJicmFpbnRyZWVDbGllbnRJZCI6Im1hc3RlcmNsaWVudDMiLCJiaWxsaW5nQWdyZWVtZW50c0VuYWJsZWQiOnRydWUsIm1lcmNoYW50QWNjb3VudElkIjoia2FsbGFyb28iLCJjdXJyZW5jeUlzb0NvZGUiOiJVU0QifSwiY29pbmJhc2VFbmFibGVkIjpmYWxzZSwibWVyY2hhbnRJZCI6ImRmempka3RzNWZzcXlxdGoiLCJ2ZW5tbyI6Im9mZiJ9'), ('payment_method_nonce', u'dbd01080-35e2-4a3b-a695-560491a14567'), ('payment_method_token', u'cfty3w')])}

console.log() 输出

ChatSerializer(<Chat: 118>):
    author = NestedSerializer(read_only=True):
        id = IntegerField(label='ID', read_only=True)
        password = CharField(max_length=128)
        last_login = DateTimeField(allow_null=True, required=False)
        email = EmailField(max_length=255, validators=[<UniqueValidator(queryset=User.objects.all())>])
        username = CharField(max_length=80)
        first_name = CharField(max_length=45)
        last_name = CharField(max_length=45)
        is_active = BooleanField(required=False)
        is_admin = BooleanField(required=False)
        joined_on = DateTimeField(read_only=True)
        is_online = BooleanField(required=False)
        is_contractor = BooleanField(required=False)
        profile_pic = ImageField(allow_null=True, required=False)
        braintree_id = CharField(allow_blank=True, allow_null=True, max_length=255, required=False)
        braintree_client_token = CharField(allow_blank=True, allow_null=True, max_length=2000, required=False)
        payment_method_nonce = CharField(allow_blank=True, allow_null=True, max_length=255, required=False)
        payment_method_token = CharField(allow_blank=True, allow_null=True, max_length=255, required=False)
    text = CharField(max_length=255)
    chatroom = NestedSerializer(read_only=True):
        id = IntegerField(label='ID', read_only=True)
        created_at = DateTimeField(read_only=True)
        creator = PrimaryKeyRelatedField(queryset=User.objects.all())
        participant = PrimaryKeyRelatedField(queryset=Contractor.objects.all())
    written_at = DateTimeField(read_only=True)

Django 的序列化程序不支持它:ticket. I suggest you using the Django Rest Framework

我猜您正在搜索使用外键连接表

仔细阅读它很长但值得一读

假设您有 2 个模型:- Employee 和 Organization

Organization(models.Model):
  organization_name = models.CharField()

Employee(models.Model):
  employee_name = models.CharField()
  employee_organization= models.ForeignKey(Organzation,on_delete=models.CASCADE)

你必须在前端访问员工模型,但你收到的数据是:

data : { 
         employee_name:"some_employee_name",
         employee_organization:"some_org_id" #Here you are getting org_id but 
                                             #that's not what you want I assume
       }

但你真正想在前端得到的是:-

data : {
        employee_name:"some_employee_name",
        employee_organization: {
                              organization_name:"some_organization_name"
                              }
       }

这样您就可以访问“组织名称”而不是“组织 ID”。这称为使用外键加入 table。

为此,您必须像这样为模型创建序列化程序:-

 OrganizationSerializer(serializer.ModelSerializer):
    model = models.Organization
    field = "__all__"

 EmployeeSerializer(models.Model):
    employee_organization = OrganizationSerializer() # This does the trick
    model = models.Employee
    fields = "__all__"

您应该 return 在您的视图中使用 EmployeeSerializer 通常将数据发送到前端,如下所示:-

class EmployeeView(APIView):
    def get(self, request, format=None):
        queryset= models.Employee.objects
                        .select_related("employee_organization")
                        .get(id="some_employee_id")

        serializer = serializers.EmployeeSerializer(queryset)

        return Response(serializer.data)

现在您将获得所需的数据:-

 data : {
            employee_name:"some_employee_name",
            employee_organization: {
                                  organization_name:"some_organization_name"
                                 }
        }

现在您可以随心所欲地提取“organization_name”。