183π
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',)
40π
This is what I did, letΒ΄s suppose a Book can have more than one author and an Author can have more than one book:
On Model:
class Author(models.Model):
name = models.CharField(max_length=100, default="")
last_name = models.IntegerField(default=0)
class Book(models.Model):
authors = models.ManyToManyField(Author, related_name="book_list", blank=True)
name = models.CharField(max_length=100, default="")
published = models.BooleanField(default=True)
On Serializers:
class BookSerializer(serializers.ModelSerializer):
authors = serializers.PrimaryKeyRelatedField(queryset=Author.objects.all(), many=True)
class Meta:
model = Book
fields = ('id', 'name', 'published', 'authors')
class AuthorSerializer(serializers.ModelSerializer):
book_list = BookSerializer(many=True, read_only=True)
class Meta:
model = Author
fields = ('id', 'name', 'last_name', 'book_list')
- [Django]-Execute code when Django starts ONCE only?
- [Django]-How to use MySQLdb with Python and Django in OSX 10.6?
- [Django]-Django: How to get related objects of a queryset?
19π
Adding to @Brianβs answer
"tags": [{"name": "tag1"}] can be simplified to "tags": ["tag1", "tag2",β¦] in this way:
class TagListingField(serializers.RelatedField):
def to_representation(self, value):
return value.name
class PostSerializer(serializers.ModelSerializer):
tag = TagListingField(many=True, read_only=True)
class Meta:
...
More info here: https://www.django-rest-framework.org/api-guide/relations/#custom-relational-fields
- [Django]-How do I use pagination with Django class based generic ListViews?
- [Django]-Django Rest Framework model serializer with out unique together validation
- [Django]-Storing an Integer Array in a Django Database
12π
The default ModelSerializer
uses primary keys for relationships. However, you can easily generate nested representations using the Meta
depth
attribute:
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ("text", "tag")
depth = 1
As mentioned in the documentation :
The
depth
option should be set to an integer value that indicates the depth of relationships that should be traversed before reverting to a flat representation.
- [Django]-AngularJS with Django β Conflicting template tags
- [Django]-Group by Foreign Key and show related items β Django
- [Django]-Custom django admin templates not working
- [Django]-Update only specific fields in a models.Model
- [Django]-Django Cache cache.set Not storing data
- [Django]-Chaining multiple filter() in Django, is this a bug?
4π
Django 2.0
For many to many field, if you want specific one:
class QuestionSerializer(serializers.ModelSerializer):
topics_list = serializers.SerializerMethodField()
def get_topics_list(self, instance):
names = []
a = instance.topics.get_queryset()
for i in a:
names.append(i.desc)
return names
class Meta:
model = Question
fields = ('topics_list',)
- [Django]-How to resize the new uploaded images using PIL before saving?
- [Django]-Django Footer and header on each page with {% extends }
- [Django]-Choose test database?
2π
In the serializer on init method you can pass the queryset to the field and rest_framework valide the ids on that queryset
1) first extend your serializer from serializers.ModelSerializer
class YourSerializer(serializers.ModelSerializer):
2) include the field on the meta class
class YourSerializer(serializers.ModelSerializer):
class Meta:
fields = (..., 'your_field',)
3) in the init method:
def __init__(self, *args, **kwargs):
super(YourSerializer, self).__init__(*args, **kwargs)
self.fields['your_field].queryset = <the queryset of your field>
You can limit the queryset for that field under any argument using filter or exclude like normally you do. In case that you want include all just use .objects.all()
- [Django]-How can I filter a Django query with a list of values?
- [Django]-Django custom management commands: AttributeError: 'module' object has no attribute 'Command'
- [Django]-No handlers could be found for logger
2π
models.py
class Tag(models.Model):
name = models.CharField(max_length=100)
# ===============
# ... rest of the fields ...
class Post(models.Model):
tag = models.ManyToManyField(Tag)
text = models.CharField(max_length=100)
serialiazers.py
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = '__all__'
class PostSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True, read_only=True)
class Meta:
model = Post
fields = ("text", "tag")
views.py
## FUNCTION BASED VIEW
def fbvPost_ListView(request):
# list
if request.method == "GET":
posts = Post.objects.all()
serializer = PostSerializer(instance=posts, many=True)
return JsonResponse(serializer.data, safe=False)
return JsonResponse({"success": False})
# ===========================================================
## CLASS BASED VIEW
class cbvPost_ListView(viewsets.ReadOnlyModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
NB: Tag, Post are two models & we need to serialize them. Here, Post model have a dependency of Tag models, so here we explicitly mention it, [tags = TagSerializer(many=True, read_only=True)] or its return itβs primary field value.
- [Django]-Django-rest-framework returning 403 response on POST, PUT, DELETE despite AllowAny permissions
- [Django]-Django β Website Home Page
- [Django]-"gettext()" vs "gettext_lazy()" in Django
0π
Hi I will be showing many to many for update and create. The context is the event can have many dances and dances can have many event.
The request will be as followed.
{
"competition": 2,
"title": "the title",
"dances":[ {"id":1},{"id":2}],
"description": "the desc"
}
The Create Function will be as followed.
def create(self, validated_data):
try:
dance_ids = []
for dance in self.initial_data['dances']:
if 'id' not in dance:
raise serializers.ValidationError({'detail': 'key error'})
dance_ids.append(dance['id'])
new_event = models.Event.objects.create(**validated_data)
if dance_ids:
for dance_id in dance_ids:
new_event.dances.add(dance_id)
new_event.save()
return new_event
except Exception as e:
raise serializers.ValidationError({'detail': e})
The Update Function will be as followed.
def update(self, instance, validated_data):
# Delete all records of genres.
try:
for current_genre in instance.dances.all():
instance.dances.remove(current_genre)
# Repopulate genres into instance.
for dance in self.initial_data['dances']:
if 'id' not in dance:
raise serializers.ValidationError({'detail': 'key error'})
dance_obj = models.Dance.objects.get(pk=dance['id'])
instance.dances.add(dance_obj)
event_updated = super().update(instance, validated_data)
return event_updated
except Exception as e:
raise serializers.ValidationError({'detail': e})
If you want to just do "dances":[1,2] instead, just make some amendments to the
for dance in self.initial_data['dances']:
if 'id' not in dance:
raise serializers.ValidationError({'detail': 'key error'})
dance_ids.append(dance['id'])
part. I hope this will be able to help yall out! π
- [Django]-Default value for user ForeignKey with Django admin
- [Django]-Is it bad to have my virtualenv directory inside my git repository?
- [Django]-How exactly do Django content types work?
0π
First, Tag needs its own serializer too
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = '__all__'
Then in your PostSerializer, add one line
class PostSerializer(serializers.ModelSerializer):
tag = TagSerializer(read_only=True, many=True).data
class Meta:
model = Post
fields = ("text", "tag")
This will make it so your Tag field in Post is an array of tag ids. if you donβt put the ".data" part, it will put all of the attributes of tag, which is probably too much in most cases
- [Django]-Django model blank=False does not work?
- [Django]-How to get the currently logged in user's id in Django?
- [Django]-Celery. Decrease number of processes
0π
You can use serializers.SlugRelatedField() or serializers.StringRelatedField(many=True) Serializer relations
In your case :
class PostSerializer(serializers.ModelSerializer):
tag = serializers.StringRelatedField(many=True) # this will return a list
class Meta:
model = Post
fields = ('tag', 'text',)
- [Django]-How to format time in django-rest-framework's serializer?
- [Django]-Dynamically adding a form to a Django formset
- [Django]-Django Reverse with arguments '()' and keyword arguments '{}' not found