yezyilomo / django-restql

Turn your API made with Django REST Framework(DRF) into a GraphQL like API.
https://yezyilomo.github.io/django-restql
MIT License
616 stars 43 forks source link

How do I toggle between nested and flat values using the same serializer? #182

Open kdeasymoneysniper opened 4 years ago

kdeasymoneysniper commented 4 years ago

Hi, this might not be an issue, but just a lack of understanding on my part. I am trying to cut down on the number of serializers that I use, and I came across this package. I want to be able to sort of toggle between nested and flat values for my foreign key fields, and many-to-many fields, depending on the query params at the end of the api call. However, I tried doing that, but it does not seem to work. Here is my code

models.py

` class SalesProject(models.Model): sales_project_name = models.CharField(max_length=100) userProfile = models.ManyToManyField( 'UserProfile', through='ProjectUser', blank=True, related_name="team")

class UserProfile(models.Model): contact_number = PhoneNumberField(blank=True) email = models.EmailField(max_length=255) email_password = models.CharField(max_length=255) `

serializers.py

` class UserProfileDynamicSerializer(DynamicFieldsMixin, serializers.ModelSerializer): class Meta: model = UserProfile fields = 'all'

class SalesProjectDynamicSerializer(DynamicFieldsMixin, serializers.ModelSerializer): userProfile = UserProfileDynamicSerializer(many=True, read_only=True) class Meta: model = SalesProject fields = 'all' `

when calling the api without any query

` "userProfile": [ { "id": 1, "contact_number": "-", "email": "-", "email_password": "-", } ], "sales_project_name": "Ending Scene 222",

`

is it possible for me to return userProfile: [1], when there are no queries? or even when I specify the query as 'userProfile', it still returns me the nested object for userProfile, and I am not sure how to return it as a flat list. Im sorry if I misunderstood anything, thanks for the help. Look forward to your reply, thanks once again!

yezyilomo commented 4 years ago

If you want a flat list of ids this is how you should define userProfile field in your SalesProjectDynamicSerializer

userProfile = UserProfileDynamicSerializer(many=True, read_only=True, return_pk=True)
yezyilomo commented 4 years ago

Here is the part of documentation about return_pk kwarg https://django-restql.yezyilomo.com/querying_data/#return_pk-kwarg

kdeasymoneysniper commented 4 years ago

hello, thank you for the prompt reply, but is it possible to dynamically change it based on my query params in the api call? Or would I have to have 2 serializers defined, one being return_pk = True, and the other being without, if I were to want to use both flat lists and nested objects from time to time?

yezyilomo commented 4 years ago

Currently it's not possible to do it dynamically, you could have 2 seriealizers or just remove return_pk and add another MethodSerializerField which returns a flat list if ids, I think the latter is easier because you won't need to add another endpoint.

yezyilomo commented 4 years ago

You could also return only ids in userProfile field with query={userProfile{id}} but it'll be in form of [{id: 1}, {id: 2}, ...] which is not that bad because you can just extract ids in a list in your frontend.

kdeasymoneysniper commented 4 years ago

okay thanks, in the event that I am going to use the methodserializerfield, I would have to input the logic of returning the flat list of ids within that method? By the way, can I check for your data manipulation (post or put requests), is there the same functionality of being able to change the fields used based on the query params in the api call? Meaning like, if I were to only specify 'sales_project_name', my put request would only require me to send in a single object of key 'sales_project_name', without sending in 'userProfile' even if it is required in the database table, ONLY in the event that the userProfile has been filled into the database beforehand (through another post or put). Because an issue I am facing with django-rest-framework is that whenever I am updating an object through a POST request, the fields that are 'required' in that model would always be needed to be filled in, regardless of if there are already existing values in the current object in the database. What I would hope for, would be to be able to specify that for a specific PUT request, I am only going to update a single field, and leave the other fields entirely out of my PUT request data, even if they are considered required fields by the database, if there are already existing valid values for those fields in the database already, and I have no intention of changing them with that specific PUT request. Thank you, sorry I am new to DRF, and I tried explaining my situation the best way I could, thank you for taking the time to reply!

yezyilomo commented 4 years ago

It looks like you want to do a partial update but you are using PUT which is http method for a full update. If you want to do a partial update use PATCH http method.