I have two classes
class Drink(models.Model):
name = models.CharField(max_length=100, blank=False, default='')
brand = models.TextField()
percentage = models.IntegerField()
class Drinking(models.Model):
amount = models.IntegerField(blank=False)
drinks = models.ForeignKey(Drink, related_name='drinks',blank = True,null=True)
and want to add a list of drinks to the Drinking model via a REST POST.
In the serializer I have the following:
class DrinkingSerializer(serializers.ModelSerializer):
drinks = serializers.PrimaryKeyRelatedField(many=True, read_only=False ,queryset=Drink.objects.all())
class Meta:
model = Drinking
fields = ('pk','drinks','amount')
def create(self, validated_data):
return Drinking.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.amount = validated_data.get('amount', instance.amount)
instance.save()
return instance
When I try to POST an Drinking Object:
{
"drinks": [2],
"amount": 5
}
I get the Error, that Drinkings.drinks must be Drink instance. My guess is that I have to change the queryset to only get the primary key of the drinks but I don't know how.
UPDATE
I did a small change in the logic, so every Drinking class can only have one Drink and one amount. This works now with the following Serializer:
class DrinkingSerializer(serializers.ModelSerializer):
drink = serializers.PrimaryKeyRelatedField(many=False, read_only=False, queryset=Drink.objects.all())
Are you sure that Drink object with id 2 exists?
Also, try making request without brackets: "drinks": 2 - in my DRF Api nothing else is needed.
I think the field drinks in your Drinking model should be in the Drink model.
class Drinking(models.Model):
amount = models.IntegerField(blank=False)
class Drink(models.Model):
name = models.CharField(max_length=100, blank=False, default='')
brand = models.TextField()
percentage = models.IntegerField()
drinks = models.ForeignKey(Drinking, related_name='drinks',blank = True,null=True)
Then, using these models your serializer should look like this:
class DrinkingSerializer(serializers.ModelSerializer):
drinks = serializers.PrimaryKeyRelatedField(many=True, read_only=False ,queryset=Drink.objects.all())
class Meta:
model = Drinking
fields = ('pk','drinks','amount')
I hope this helps.
Related
I have a very simple question and I'm surprised it hasn't been asked before on this website.
I have the two following models:
# models.py
class Film(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=150)
genre = models.ManyToManyField(Genre)
class Genre(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100, unique=True)
I need to make an API that gets 2 integers, id of movie and id of genre, and adds the said genre to the movie. seems very simple but I don't know how I could do this. I could really use the help.
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
Let us imagine that I have two models.
First model contains curse details and user that created this course
class Course(models.Model):
course_name = models.CharField(max_length=100, null=False)
description = models.CharField(max_length=255)
user_profile = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
and my second model is:
class Lesson(models.Model):
course = models.OneToOneField(Course, on_delete=models.CASCADE) #
# inside the course I want my APIVIEW to list only the courses that current user created.
# OnetoOne relationship does not solve the problem.
status = models.CharField(choices=STATUS, null=False, default=GOZLEMEDE,max_length=20)
tariffs = models.FloatField(max_length=5,null=False,default=0.00)
continues_off = models.CharField(max_length=2)
user_profile = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
My serializers for both Models:
class LessonSerializer(serializers.ModelSerializer):
class Meta:
model = models.Lesson
fields = ('course', 'status', 'tariffs', 'continues_off', 'user_profile')
def create(self, validated_data):
lesson = models.Lesson.objects.create(
course = validated_data['course'],
status = validated_data['status'],
tariffs=validated_data['tariffs'],
continues_off=validated_data['continues_off'],
user_profile=validated_data['user_profile']
)
return lesson
class CourseSerializer(serializers.ModelSerializer):
"""Serializers Course content"""
class Meta:
model = models.Course
fields = '__all__'
def create(self,validated_data):
course = models.Course.objects.create(
course_name = validated_data['course_name'],
description=validated_data['description'],
user_profile=validated_data['user_profile']
)
return course
My Viewset:
class LessonViewset(viewsets.ModelViewSet):
model = models.Lesson
serializer_class = serializers.LessonSerializer
authentication_classes = (SessionAuthentication,)
permission_classes = (IsAuthenticated,BasePermission,)
def get_queryset(self):
user_current = self.request.user.id
return models.Lesson.objects.filter(user_profile=user_current)
How can I get the desired result. I want to get the courses for the current user and show them as a dropdown list in my API view. Just only the courses that user created should be in the dropdown list not all.
OnetoOne relationship gives all results of course table.
i think change your view code to :
def get_queryset(self,id):
return model.objects.filter(user_profile=id)
#You do not need to call it again when you put the Lesson on the model
\
I want to post a movie into the collection's movie field( list of movies).
I define the model as
class Movie(models.Model):
# collection = models.ForeignKey(Collection, on_delete = models.CASCADE) #, related_name='reviews'
title = models.CharField(max_length=200)
description = models.CharField(max_length=200)
genres = models.CharField(max_length=200)
uuid = models.CharField(max_length=200)
def __str__(self):
return self.title
class Collection(models.Model):
title = models.CharField(max_length=200)
uuid = models.CharField(max_length=200, primary_key = True)
description = models.CharField(max_length=200)
movie = models.ForeignKey(Movie, on_delete = models.CASCADE)
def __str__(self):
return self.title
this is how i am using the viewset
class CollectionViewSet(viewsets.ModelViewSet):
queryset = models.Collection.objects.all()
serializer_class = serializers.CollectionSerializer
but i am not able to enter values for the movie field
enter image description here
also my serializer
class CollectionSerializer(serializers.ModelSerializer):
class Meta:
model = Collection
fields = '__all__'
By default, DRF will represent the relationship with a PrimaryKeyRelatedField, thus expecting a movie ID.
To achieve what you want (create an instance of movie with a collection), you need to overwrite the foreign key field in your serializer with your own Movie serializer.
class MovieSerializer(serializers.ModelSerializer):
class Meta:
model = Movie
fields = '__all__'
class CollectionSerializer(serializers.ModelSerializer):
movie = MovieSerializer()
class Meta:
model = Collection
fields = '__all__'
def create(self, validated_data):
movie = validated_data.pop('movie')
movie = Movie .objects.create(**movie )
collection = Collection.objects.create(movie=movie, **validated_data)
return collection
You need to overwrite the create method so when creating a Collection, you also create a movie.
However, I am not sure the foreign key is set in the right model in your model. (a movie belongs to many collection but not the other way around?) If that's not what you want, just reverse the logic for the serializer.
Edit:
Sending the following should work fine:
{ "uuid": "1001",
"title": "Action",
"description": "Action Movies",
"movie": { "title": "The Burkittsville 7",
"description": "The story of Rustin Parr.",
"genres": "Horror",
"uuid": "5e904"
}
}
The only problem as I mentionned earlier is in your model you defined the foreign key field in collection. So it expects one single movie instance and not a list, thus I took off the brackets you put around movie. Maybe you should consider setting the foreign key in the Movie model, or use a Many to many relationship.
#models.py
class Movie(models.Model):
# collection = models.ForeignKey(Collection, on_delete = models.CASCADE) #, related_name='reviews'
title = models.CharField(max_length=200)
description = models.CharField(max_length=200)
genres = models.CharField(max_length=200)
uuid = models.CharField(max_length=200)
def __str__(self):
return self.title
class Collection(models.Model):
title = models.CharField(max_length=200)
uuid = models.CharField(max_length=200, primary_key = True)
description = models.CharField(max_length=200)
movie = models.ManyToManyField(Movie, on_delete = models.CASCADE)
def __str__(self):
return self.title
serializers.py:
class MovieSerializer(serializers.ModelSerializer):
class Meta:
model = Movie
fields = '__all__'
class CollectionSerializer(serializers.ModelSerializer):
movie = MovieSerializer(read_only=True, many=True)
class Meta:
model = Collection
fields = '__all__'
hope this will give you better unserstand this will work for you
I have the following models
class STUser(AbstractBaseUser):
email = models.EmailField(unique=True)
name = models.CharField(max_length=255)
companyname = models.CharField(max_length=200, blank=True, null=True)
...
class VenuePermissions(models.Model):
user = models.ForeignKey(STUser, on_delete=models.CASCADE)
venue = models.ForeignKey(Venue, on_delete=models.CASCADE)
signupvaildatestring = models.CharField(max_length=200, blank=True, null=True)
...
I want to grab all the STUser objects and grab all their permissions.
So what I would like is to grab all the VenuePermissions objects. And grab the user and venue object of each venuePermission
Two ways I can do this. use the VenuePermissions_set attribute on STUser but then how do I grab the venue when its just going to be a pk value?
Or focus on the VenuePermissions objects and grab the user and venue from the pk values but how?
I remember nested queries, and I kinda did one in my browse code.
here is an example:
rooms = Room.objects.filter(venue=OuterRef('pk'), sixtyroundseatingoption= True)
venuelist = venuelist.annotate(sixtyrounds=Exists(rooms))
venuelist = venuelist.filter(Q(sixtyrounds = True) | Q(fullbuyoutsixtyroundseatingoption = True))
I've done the set objects in a serializer before
Example serializer:
class RoomAndImageSerializer(serializers.ModelSerializer):
roomimage_set = RoomImageSerializer(many=True, read_only=True)
class Meta:
model = Room
fields = ('pk','name')
any help with this query would be appreciated!
So this is what I am currently trying, I will post an answer if this works:
class VenueUserList(ListAPIView):
serializer_class = VenueUserListSerializer
queryset = VenuePermissions.objects.select_related('user').select_related('venue').filter(signupvaildatestring=None)
class VenueUserListSerializer(serializers.ModelSerializer):
user = UserSerializer()
venue = VenueSerializer()
class Meta:
model = VenuePermissions
fields = ('user', 'venue', 'isvenueviewer', 'isvenueeventplanner', 'isvenueadministrator')
Here is the answer. However I still need to group venues by user. Working on that.
class VenueUserList(ListAPIView):
serializer_class = VenueUserListSerializer
queryset = VenuePermissions.objects.select_related('user').select_related('venue').filter(signupvaildatestring=None)
class VenueUserListSerializer(serializers.ModelSerializer):
user = UserSerializer()
venue = VenueSerializer()
class Meta:
model = VenuePermissions
fields = ('user', 'venue', 'isvenueviewer', 'isvenueeventplanner', 'isvenueadministrator')
My model:
class HospitalDoctor(models.Model):
hospital = models.ForeignKey(Hospital)
full_name = models.CharField(max_length=100, unique=True)
expertization = models.CharField(max_length=50)
nmc_no = models.CharField(max_length=20)
timings = models.ManyToManyField('Timing', related_name='shift_timing')
appointment = models.IntegerField(default=0)
def __unicode__(self):
return self.full_name
class Timing(models.Model):
hospital = models.ForeignKey(Hospital)
doctor = models.ForeignKey(HospitalDoctor)
day = models.CharField(max_length=20)
mng_start = models.IntegerField()
mng_end = models.IntegerField()
eve_start = models.IntegerField()
eve_end = models.IntegerField()
def __unicode__(self):
return self.day
and I have created form for this:
class HospitalDoctorInfoForm(forms.ModelForm):
class Meta:
model = HospitalDoctor
fields = ('hospital','full_name', 'expertization', 'nmc_no')
class TimingForm(forms.ModelForm)
class Meta:
model = Timing
fields = ('day','mng_start', 'mng_end', 'eve_start', 'eve_end')
I want to save the two form at once. The TimingForm contains the schedule of a doctor for 1 week so I need 7 forms for 7 days and the day should be set as per week initially like Sunday, Monday....DoctorInfoForm contains the information about doctor.
I tried using CreateView but I need to use form_class there?
How can I make it possible? Any suggestion.
It is just simple in django.
if HospitalDoctorinfoform.is_valid() and Timingform.is_valid():
#Dosomething
HospitalDocinfoform.save()
Timingform.save()
BIngo!!