django-ninja icon indicating copy to clipboard operation
django-ninja copied to clipboard

Still issues on multiple schema response

Open paolodina opened this issue 3 years ago • 5 comments

Similarly to #579 I have two schemas and I want to conditionally return one or the other.

@router.get('/', response={200: list[ExchangeSchema|ExchangeMiniSchema]})
def list_exchanges(request, mini: bool = False):
    if mini:
        result = Exchange.objects.all().only("id", "name", "desc")
        return [ExchangeMiniSchema(**r.__dict__) for r in result]

    result = Exchange.objects.all()
    return [ExchangeSchema(**r.__dict__) for r in result]
  1. First it's not clear to me if I have to return the query result as a schema, like I do
return [ExchangeMiniSchema(**r.__dict__) for r in result]

or if it's enough to return the Django queryset directly, if it will be casted to the right output response schema.

  1. Whatever I tried on output schema response, I keep get returning the first schema defined in the union (the full ExchangeSchema). Not being too good with typing I also tried using list[ExchangeSchema]|list[ExchangeMiniSchema] and typing.Union too, but no way to make it work.

The response I get is always

[
    {
        "id": null,
        "alias": "aax",
        "name": "aax",
        "desc": "",
        "ref_link": "",
        "sponsor": false,
        "position": null,
        "enabled": true,
        "blacklist": false
    }
]

and never

[
    {
        "id": null,
        "name": "aax",
        "desc": "",
     }
]

If that matters those schemas inherit from ninja.ModelSchema.

paolodina avatar Oct 07 '22 21:10 paolodina

@paolodina As I can see, you have closed this issue without submitting a solution. Could you please let us know how you resolved it? Thanks

laith43d avatar Apr 05 '23 21:04 laith43d

@laith43d I added a query string parameter and used a schema or the other conditionally. Not really a solution.

I closed this issue because I wasn't sure it made sense.

paolodina avatar Apr 05 '23 22:04 paolodina

To someone who is looking solution for this issue. Just remove response code in router section.

And use different schema in same api. This is code that I really made for success or error.

@comments_router.post("/{comment_id}/favorite/")
def post_favorite_comment(request, comment_id: int):
    try:
        comment = Comment.objects.get(id=comment_id)
        comment.voters.add(request.user)
        comment.save()
        comment.user_has_favorite = True
        if Comment.objects.filter(parent_id=comment_id).exists():
            comment.has_child = True
        comment.favorite_count = comment.voters.count()
    except Comment.DoesNotExist:
        return ErrorMessages.from_orm(
            {"success": False, "message": "There is no comment."}
        )
    return VerseCommentSchema.from_orm(comment)

I referenced #474

quroom avatar Oct 31 '23 00:10 quroom

Same issue here.

nythrox avatar Feb 28 '24 22:02 nythrox