Reputation: 175
I am making an API with django rest framework and what it's supposed to do is, it has to return the movies that a certain celebrity has acted or directed in.
And I dont know how to do that. because the film model has manytomany fields called filmActor and filmDirector and I want to preferably make this api by extending the ModelSerializer class.
# Models.py
class Celebrity(models.Model):
celebID = models.AutoField(primary_key=True)
nameOf = models.CharField(max_length=100, unique=True)
details = models.TextField(null=True)
class Film(models.Model):
filmID = models.AutoField(primary_key=True)
title = models.CharField(max_length=150)
filmActor = models.ManyToManyField(Celebrity, related_name='actor')
filmDirector = models.ManyToManyField(Celebrity, related_name='director')
# Serializers.py
class CelebrityRetrieveSerializer(serializers.ModelSerializer):
# TO BE DONE
Upvotes: 1
Views: 488
Reputation: 1
class Actor(models.Model):
image = models.ImageField("Image", upload_to='cast/')
name = models.CharField("Name", max_length=255)
type = models.CharField('Type', max_length=255, default='Actor')
description = models.TextField('About')
slug = models.SlugField("Link", unique=True)
class Meta:
verbose_name = "Actor"
verbose_name_plural = "Cast"
def current_path(self):
return "/Actor/" + str(self.name) + "/"
def get_absolute_url(self):
return reverse('actor_detail_url', kwargs={'slug': self.slug})
def __str__(self):
return self.name
class Movie(models.Model):
poster = models.ImageField(
'Poster', blank=True, upload_to='posters/')
movie = models.FileField("Movie Copy", upload_to="movies/")
title = models.CharField('Title', max_length=255)
description = models.TextField('Description')
genre = models.ManyToManyField(
Genre, blank=True, verbose_name='Genre')
director = models.ManyToManyField(
Director, blank=True, verbose_name='Director')
cast = models.ManyToManyField(
Actor, blank=True, verbose_name='Cast')
imdb_rating = models.ForeignKey(
IMDb_Rating, on_delete=models.CASCADE, null=True, verbose_name="IMDb Rating")
rotten_tomatoes_rating = models.ForeignKey(
Rotten_Tomatoes_Rating, on_delete=models.CASCADE, null=True, verbose_name="Rotten Tomatoes Rating")
other_rating = models.ForeignKey(
Other_Rating, on_delete=models.CASCADE, null=True, verbose_name="Other Rating")
budget = models.CharField('Budget', max_length=255,
default="20 million", blank=True)
box_office = models.CharField(
'Box Office', max_length=255, default="1.50 billion", blank=True)
composers = models.ManyToManyField(
Composer, blank=True, verbose_name="Composers")
date = models.DateField('Release Date', default=timezone.now)
country = CountryField(blank_label='Select Country')
Quality = models.CharField("Quality", max_length=255, default="720p")
runtime = models.CharField("Runtime", max_length=255, default="1h 20m")
publication = models.BooleanField("Publication", default=True)
slug = models.SlugField('Link', unique=True)
class Meta:
verbose_name = 'Movie'
verbose_name_plural = 'Movies'
def get_absolute_url(self):
return reverse('movie_detail_url', kwargs={'slug': self.slug})
def __str__(self):
return self.title
<div class="cast-column">
{% for actor in movie.cast.all %}
<a href="{% url 'actor_detail_url' actor.slug %}">
<div class="actor" style="{% if not forloop.first %} margin-left: 8px; {% endif %}">
<div class="actor-picture">
<img src="{{actor.image.url}}" alt="{{actor.name}}">
</div>
<div class="actor-n_r">
<div class="actor-name">{{actor.name}}</div>
<div class="actor-role">{{role.role}}</div>
</div>
</div>
</a>
{% endfor %}
</div>
Upvotes: 0
Reputation: 175
The answer that @ThomasGth gave, works only if you have 1 foreign-key or many-to-many field.
to do this with two foreign keys, you have to name the field in your serializers.py, the name that was given to the related_name field in your models.py. so the code should be something like this:
class CelebrityRetrieveSerializer(serializers.ModelSerializer):
class FilmSerializer(serializers.ModelSerializer):
class Meta:
model = Film
fields = ('title',)
actor = FilmSerializer(read_only=True, many=True,)
director = FilmSerializer(read_only=True, many=True,)
class Meta:
model = Celebrity
fields = '__all__'
You also have to make sure to give a value to related_name that does not conflict with the other names you have used in your code. for example if you set it to related_name = Film
it could cause problems.
Upvotes: 1
Reputation: 870
You can access many-to-many related objects thanks to "_set". Something like this should work:
class FilmSerializer(serializers.ModelSerializer):
class Meta:
model = Film
fields = ('filmID', 'title')
class GenreRetrieveSerializer(serializers.ModelSerializer):
film_set = FilmSerializer(many=True)
class Meta:
model = Genre
fields = '__all__'
Upvotes: 1