django queryset注释子表中的所有字段

时间:2018-05-17 08:46:36

标签: django django-models django-rest-framework django-queryset

models.py

class Userinfo(models.Model):

    useruid = models.BigAutoField(db_column='UserUID', primary_key=True)

    useremail = models.CharField(
    db_column='UserEmail', unique=True, max_length=100)

    userpassword = models.CharField(db_column='UserPassword', max_length=128)

    passwordsalt = models.CharField(db_column='PasswordSalt', max_length=128)

    class Meta:
    managed = False
    db_table = 'userinfo'

class Postinfo(models.Model):


    postuid = models.BigAutoField(db_column='PostUID',primary_key=True)

    useruid = models.ForeignKey(
    'Userinfo', db_column='UserUID', on_delete=models.CASCADE)


    content = models.TextField(db_column='Content')

    class Meta:
          managed = False
          db_table = 'postinfo'

如果我收到用户列表和用户的上一篇文章

我认为使用注释

models.Userinfo.objects.all().annotate(lastpost="??").order_by("-useruid")

“??”中的值是什么

喜欢这种形式

[{userinfo1,"lastpost":{postinfofields}},{userinfo2,"lastpost":{postinfofields}},{userinfo3,"lastpost":{postinfofields}}]

这个查询可以不使用forloop吗?

Serializer.py

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Postinfo
        fields = ('postuid','content') 

class UserSerializer(serializers.ModelSerializer):   

     lastpost = PostSerializer() 

     class Meta:
        model = Userinfo
        fields = ['useruid', 'useremail', 'lastpost']

view.py

  userinfos = models.Userinfo.objects.all().order_by("-useruid")
  result = UserSerializer(userinfos,many=True)
  print(result.data)

引发异常

Got AttributeError when attempting to get a value for field `lastpost` on serializer `UserSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Userinfo` instance.
Original exception text was: 'Userinfo' object has no attribute 'lastpost'.

如果我添加read_only = True打印此

[OrderedDict([('useuid', 1), ('useremail', 'test')]), OrderedDict([('useruid', 2), ('useremail', 'test2')])]

1 个答案:

答案 0 :(得分:1)

您可以使用model的属性:

class Userinfo(models.Model):

    useruid = models.BigAutoField(db_column='UserUID', primary_key=True)

    useremail = models.CharField(
    db_column='UserEmail', unique=True, max_length=100)

    userpassword = models.CharField(db_column='UserPassword', max_length=128)

    passwordsalt = models.CharField(db_column='PasswordSalt', max_length=128)

    @property
    def lastpost(self):
        return self.postinfo_set.latest('postuid')

现在你不需要注释,只需在模板中使用它,例如:

{{ user.lastpost.content }}

<强> UPD

要使用ModelSerializer序列化属性,只需添加序列化程序的字段'lastpost'

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Postinfo
        fields = ('postuid','content') 

class UserSerializer(serializers.ModelSerializer):   
    lastpost = PostSerializer() 

    class Meta:
        model = Userinfo
        fields = ['useruid', 'useremail', 'lastpost']

<强> UPD2

您也可以直接在序列化程序级别实现逻辑,而无需使用model的属性。只需使用SerializerMethodField

class UserSerializer(serializers.ModelSerializer):   
    lastpost = SerializerMethodField() 

    class Meta:
        model = Userinfo
        fields = ['useruid', 'useremail', 'lastpost']

    def get_lastpos(self, obj):
        last = obj.postinfo_set.latest('postuid')
        serializer = PostSerializer(last)
        return serializer.data