Django Rest Framework Serializing Many to Many Field

Django rest framework serializing many to many field

You will need a TagSerializer, whose class Meta has model = Tag. After TagSerializer is created, modify the PostSerializer with many=True for a ManyToManyField relation:

class PostSerializer(serializers.ModelSerializer):
tag = TagSerializer(read_only=True, many=True)

class Meta:
model = Post
fields = ('tag', 'text',)

Answer is for DRF 3

DRF serialization - many-to-many field with through

You need to change IngredientSerializer to use the RecipeIngredientsDetails model, and also explicitly set the related serializer inside the RecipeSerializer:

from rest_framework.serializers import ReadOnlyField
class IngredientDetailSerializer(ModelSerializer):
id = ReadOnlyField(source='ingredient.id')
ingredient = ReadOnlyField(source='ingredient.name')
measurement_unit = ReadOnlyField(source='ingredient.measurement_unit')

class Meta:
model = RecipeIngredientsDetails
fields = ["id", "ingredient", "measurement_unit", "amount",]

class RecipeSerializer(ModelSerializer):
ingredients = IngredientDetailSerializer(source="recipeingredientsdetails_set", many=True)
class Meta:
model = Recipe
fields = ["name", "ingredients"]
depth = 1

add instances to a manytomany field in django rest framework

You might want this:

class GenreSerializer(serializers.ModelSerializer):
class Meta:
model = Genre
fields = ('name', 'id')

class FilmSerializer(serializers.ModelSerializer):
genre = GenreSerializer(many=True, read_only=False)

class Meta:
model = Film
fields = ('name', 'id', 'genre')

def update(self, instance, validated_data):
genres_data = validated_data.pop('genre')
instance = super(FilmSerializer, self).update(instance, validated_data)

for genre_data in genres_data:
genre_qs = Genre.objects.filter(name__iexact=genre_data['name'])

if genre_qs.exists():
genre = genre_qs.first()
else:
genre = Genre.objects.create(**genre_data)

instance.genre.add(genre)

return instance

Django Rest framework Serialize many to many field

If you need to de-serialize fields, you should not use read_only=True:

class FindBus(serializers.ModelSerializer):
passengers = PassengerSerializer(many=True)
...

Note that this won't be enough for saving m2m relationships: as explained in Writable nested serializers, you'll also need to define create() and/or update() methods on your serializer:

class FindBus(serializers.ModelSerializer):
passengers = PassengerSerializer(many=True)
...

def create(self, validated_data):
...

def update(self, validated_data):
...

The reason for the need of the create/update is that you have to decide whether the passenger details that you receive refer to existing objects or need to be created.

You might also need to add fields = ('__all__',) (or specify the fields you're interested in) to your PassengerSerializer:

class PassengerSerializer(serializers.ModelSerializer):
class Meta:
model = Passenger
fields = ('__all__',)

Serialize filtered related fields in Django Rest framework

you could use a SerializerMethodField() to filter down the Challenges groups to just the user groups. To do this you may also need to pass in serializer context as well

To set up the serializer context:

class ChallengeList(generics.ListAPIView):
...
def get_serializer_context(self):
context = {user_groups: self.request.user.user_groups.all()}
return context
...

Then access this context in the SerializerMethodField in your serializer

class ChallengeSerializer(serializers.ModelSerializer):

groups_of_user = SerializerMethodField()

class Meta:
model = Challenge
fields = [..., "groups_of_user"]

def get_groups_of_user(self, challenge):
user_groups = self.context.get('user_groups')
groups_of_user = challenge.groups & user_groups
return GroupSerializer(groups_of_user, many=True).data

With this implementation you could also add prefetch_related('groups') on your queryset in ChallengeList to improve performance



Related Topics



Leave a reply



Submit