Home > Back-end >  DRF: How to add annotates when create an object manually?
DRF: How to add annotates when create an object manually?

Time:01-14

Currently I'm trying to create an expected json to use in my test:

@pytest.mark.django_db(databases=['default'])
def test_retrieve_boards(api_client):
    board = baker.make(Board)
    objs = BoardSerializerRetrieve(board)
    print(objs.data)
    url = f'{boards_endpoint}{board.id}/'
    response = api_client().get(url)
    assert response.status_code == 200

But i'm receiving the following error:

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

Currently cards_idsare added on my viewSet on get_queryset method:

    def get_queryset(self):
        #TODO: last update by.
        #TODO: public collections.
        """Get the proper queryset for an action.

        Returns:
            A queryset object according to the request type.
        """
        if "pk" in self.kwargs:
            board_uuid = self.kwargs["pk"]
            qs = (
                self.queryset
                    .filter(id=board_uuid)
                    .annotate(cards_ids=ArrayAgg("card__card_key"))
            )

            return qs

        return self.queryset

and this is my serializer:

class BoardSerializerRetrieve(serializers.ModelSerializer):
    """Serializer used when retrieve a board

    When retrieve a board we need to show some informations like last version of this board
    and the cards ids that are related to this boards, this serializer will show these informations.
    """
    last_version = serializers.SerializerMethodField()
    cards_ids = serializers.ListField(child=serializers.IntegerField())

    def get_last_version(self, instance):
        last_version = instance.history.first().prev_record
        return HistoricalRecordSerializer(last_version).data

    class Meta:
        model = Board
        fields = '__all__'

what is the best way to solve it? I was thinking in create a get_cards_ids method on serializer and remove annotate, but I don't know how to do it and justing googling it now. rlly don't know if this is the correct way to do it.

CodePudding user response:

Test the view, not the serializer, i.e. remove BoardSerializerRetrieve(board) from your test code.

cards_ids is annotated on ViewSet level. The annotated queryset is then passed to serializer.

@pytest.mark.django_db(databases=['default'])
def test_retrieve_boards(api_client):
    board = baker.make(Board)
    url = f'{boards_endpoint}{board.id}/'
    response = api_client().get(url)
    assert response.status_code == 200

Also, instead of building the URL manually with url = f'{boards_endpoint}{board.id}/', consider using reverse, e.g. url = reverse("path-name", kwargs={"pk": board.id}).

  •  Tags:  
  • Related