【问题标题】:DRF: How to add annotates when create an object manually?DRF:手动创建对象时如何添加注释?
【发布时间】:2022-01-13 15:43:06
【问题描述】:

目前我正在尝试创建一个预期的 json 以在我的测试中使用:

@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

但我收到以下错误:

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'

目前cards_ids被添加到我的视图集中get_queryset方法:

    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

这是我的序列化器:

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__'

解决问题的最佳方法是什么?我正在考虑在序列化程序上创建一个get_cards_ids 方法并删除注释,但我不知道该怎么做,现在只是在谷歌上搜索它。不知道这是否是正确的做法。

【问题讨论】:

    标签: python django serialization django-rest-framework


    【解决方案1】:

    测试视图,而不是序列化程序,即从测试代码中删除 BoardSerializerRetrieve(board)

    cards_ids 在 ViewSet 级别上进行了注释。然后将带注释的查询集传递给序列化程序。

    @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
    

    另外,不要使用 url = f'{boards_endpoint}{board.id}/' 手动构建 URL,而是考虑使用 reverse,例如url = reverse("path-name", kwargs={"pk": board.id}).

    【讨论】:

    • 那么,我是否也应该为序列化程序创建一个单独的测试?
    • 我通常不这样做,因为测试视图意味着测试相关的序列化程序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 2018-06-20
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多