Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] static resolver fields called twice #1344

Open
dusty-phillips opened this issue Nov 22, 2024 · 1 comment
Open

[BUG] static resolver fields called twice #1344

dusty-phillips opened this issue Nov 22, 2024 · 1 comment

Comments

@dusty-phillips
Copy link

Describe the bug

Roughly following https://django-ninja.dev/guides/response/django-pydantic/ I am seeing static resolvers called twice, once with the Django model and once with the Pydantic Schema. Consider this schema:

class UserSchema(ModelSchema):
    both: str

    class Meta:
        model = User
        fields = ["username", "email"]

    @staticmethod
    def resolve_both(obj):
        print("called with", obj, obj.__class__)
        return f"{obj.username} <{obj.email}>"


@api.get("/hello", response=UserSchema)
def hello(request):
    user = User.objects.first()
    return UserSchema.from_orm(user)

The console output is:

called with me <class 'django.contrib.auth.models.User'>
called with both='me <[email protected]>' username='me' email='[email protected]' <class 'myproject.api.UserSchema'>

My guess is the function gets called by Django-ninja and then gets called again by Pydantic, because the name is overloaded. This doesn't seem to be expected/intended. The only way I can see to fix it in my code is to scatter isinstance calls in all my resolvers.

Versions (please complete the following information):

  • Python version: 3.12
  • Django version: tried with 5.1.3 and 4.2.15
  • Django-Ninja version: 1.3.0
  • Pydantic version: tried with 2.10.1 and 2.8.2
@Houet
Copy link

Houet commented Nov 27, 2024

Not sure if this is still relevant but you don't need the last line, that why it's called twice, you can directly return your user

class UserSchema(ModelSchema):
    both: str

    class Meta:
        model = User
        fields = ["username", "email"]

    @staticmethod
    def resolve_both(obj):
        print("called with", obj, obj.__class__)
        return f"{obj.username} <{obj.email}>"


@api.get("/hello", response=UserSchema)
def hello(request):
    return User.objects.first()

You can return the object / queryset directly, django-ninja will take care of the validation / serialization
e.g: in the documentation :

from typing import List

@api.get("/employees", response=List[EmployeeOut])
def list_employees(request):
   qs = Employee.objects.all()
   return qs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants