django queryset аннотирует все поля в дочерней таблице - PullRequest
0 голосов
/ 17 мая 2018

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 голосов
/ 17 мая 2018

Для этого вы можете использовать свойство модели:

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

Вы также можете реализовать логику непосредственно на уровне сериализатора без свойства модели. Просто используйте 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
...