Trouble Serializing a many-to-many field - python

Before this gets marked as a duplicate, I've looked at the following questions:
Django Rest framework Serialize many to many field
Django rest framework serializing many to many field
No results are being shown for payins when I test.
serializers.py
class PayinsSerializer(serializers.ModelSerializer):
class Meta:
model = Payins
fields = '__all__'
class UserStokvelSerializer(serializers.ModelSerializer):
payins = PayinsSerializer(many=True)
class Meta:
model = Stokvel
fields = '__all__'
models.py
class Payins(models.Model):
payin_date = models.DateField(default=timezone.now)
payin_by = models.ForeignKey(User, on_delete=models.CASCADE)
stokvel_payin = models.ForeignKey('Stokvel', on_delete=models.CASCADE, related_name="payin_user")
payin_amount = models.IntegerField()
def save(self, *args, **kwargs):
stokvel = Stokvel.objects.get(id = self.stokvel_payin.id)
stokvel.balance += self.payin_amount
stokvel.save()
super(Payins, self).save(*args, **kwargs)
class Stokvel(models.Model):
stokvel_name = models.CharField(max_length=55)
balance = models.IntegerField(default = 0)
payouts = models.ManyToManyField(Payouts, related_name="stokvel_payouts")
payins = models.ManyToManyField(Payins, related_name="stokvel_payins")
group_admin = models.ForeignKey(User, on_delete=models.CASCADE, related_name="stokvel_group_admin")
users = models.ManyToManyField(User, related_name="stokvel_users")
invite_key = models.CharField(default = secrets.token_hex(15), max_length=55)

Was able to figure it out using this guide:
By modifying this example:
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ('order', 'title')
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True)
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')

Related

how to serialize two classes have one to many relation in django

this is my models
class Users(models.Model) :
name = models.CharField(max_length=20 , blank=False , null=False)
email = models.EmailField(max_length=50 , blank=True , null=True)
password = models.CharField(max_length=30 , blank=False , null=False)
birthday = models.DateField(null=False)
photo = models.ImageField(upload_to = 'user_photos/%y/%m/%d')
#friend = models.ManyToManyField('self',through='Notif',null=True,related_name='friend')
class Product(models.Model):
pub_date = models.DateTimeField(default=datetime.now)
price = models.DecimalField(max_digits=100000,decimal_places=5,null=False,blank=False)
size = models.IntegerField(null=True,blank=True,default='undefined')
photo = models.ImageField(upload_to = 'product_photos/%y/%m/%d',null=True)
#for 1--n relation with users
user_id = models.ForeignKey(Users,on_delete=models.CASCADE,null=True,related_name='user')
this is my serializers.py
class ProductSerializer (serializers.ModelSerializer):
class Meta :
model = Product
fields = '__all__'
class UsersSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = '__all__'
i want to send product object with the email of his user
what i have to do in serializers and views to make it
note i use function based views in my views
First of all, you should change user_id to user.
in serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = ['id','email']
class ProductSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
class Meta :
model = Product
fields = '__all__'
in function based views:
def get_product(request,product_id):
instance = Product.objects.select_related('user').get(id=product_id)
serializer = ProductSerializer(instance)
return Response(serializer.data)
NOTE: select_related is used to get product with user at the same query (join query).

Django error while serializing image model of child field

I am new to this tech, while working on django project i got some issues when i try to serialize Ticket's account.profile_pic
models.py
class Account(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE
profile_pic = models.ImageField(upload_to='images/profile_pics/', blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
class Ticket(models.Model):
author = models.ForeignKey(Account, on_delete=models.CASCADE)
descr = models.TextField(blank=False, null=False)
likes = models.ManyToManyField(User)
serializers.py
class DetailedTicketSerializer(serializers.ModelSerializer):
# Error occurs on below line: No file associated with ImageField
author_profile_pic = serializers.ReadOnlyField(source='author.profile_pic')
author_username = serializers.ReadOnlyField(source='author.user.username')
class Meta:
model = Ticket
fields = ['id', 'author_profile_pic', 'author_username', 'likes', 'descr']
Anyone knows how do i serialize Account.profile_pic's url???
serialize the account class. in your ticketserializer call the account serializer.
Here an example:
class
HobbySerializer(serializers.ModelSerializer):
class Meta:
model = Hobby
fields = '__all__'
class ProfileSerializer(serializers.ModelSerializer):
user_hobby = HobbySerializer(many=True)
class Meta:
model = Profile
fields = '__all__'

Django returning chain of 2 different model querysets

Here is my view
serializer_class = SceneSerializer
permission_classes = (permissions.IsAuthenticated,)
def get_queryset(self):
scene = Scene.objects.filter(user = self.request.user)
for s in scene:
test = Scene.objects.get(static_id = s.static_id)
lights = test.light.all()
temp = list(chain(scene, lights))
Here are my 2 serializers
class LightSerializer(serializers.ModelSerializer):
class Meta:
model = Light
fields = '__all__'
class SceneSerializer(serializers.ModelSerializer):
class Meta:
model = Scene
fields = '__all__'
Here is my models
class Light(models.Model):
static_id = models.AutoField(primary_key=True)
id = models.CharField(max_length=100, blank=True, null=True)
company = models.CharField(max_length=25, blank=True, null=True)
name = models.CharField(max_length=100, blank=True, null=True)
label = models.CharField(max_length=100, blank=True, null=True)
user = models.ForeignKey(User,on_delete=models.DO_NOTHING, related_name='userLights' )
def __str__(self):
return "{0} - {1}".format(self.user,self.static_id)
class Scene(models.Model):
static_id = models.AutoField(primary_key=True)
color = RGBColorField()
title = models.CharField(max_length=100, blank=True, null=True)
user = models.ForeignKey(User,on_delete=models.DO_NOTHING, related_name='userScenes' )
light = models.ManyToManyField(Light)
def __str__(self):
return "{0} - {1}".format(self.user,self.static_id)
Goal is to return the complete objects of the scene and the lights attached to each scene. the chain is working correctly but when I return the chain I am getting
You can include reverse relationships in serializers by adding the reverse relationship to fields
class SceneSerializer(serializers.ModelSerializer):
class Meta:
model = Scene
fields = ['light', 'static_id', 'color', 'title', 'user']
This will just return a list of ids, to serialize the related objects you can add the related serializer with many=True
class SceneSerializer(serializers.ModelSerializer):
light = LightSerializer(many=True)
class Meta:
model = Scene
fields = ['light', 'static_id', 'color', 'title', 'user']

How to access reversed relationship using Django rest framework

Here are my models :
class Profile(models.Model):
user = models.ForeignKey(User, related_name="profile", on_delete=PROTECT)
plan = models.ForeignKey(Plans, on_delete=PROTECT)
full_name = models.CharField(max_length=2000)
company_name = models.CharField(max_length=50, null=True, blank=True)
activation_token = models.UUIDField(default=uuid.uuid4)
activated = models.BooleanField(default=False)
thumb = models.ImageField(upload_to='uploads/thumb/', null=True, blank=True)
renew_data = models.DateField()
is_paid = models.BooleanField(default=False)
And as you see the Profile model have user field that is related to the Abstract user of django framework. now here is how i call them using an API :
Serializers
class ProfileSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Profile
fields = ['company_name']
class UserSerializer(serializers.HyperlinkedModelSerializer):
profile_set = ProfileSerializer(
read_only=True, many=True) # many=True is required
class Meta:
model = User
depth = 1
fields = ['username', 'id', 'profile_set']
But when I call the API it shows only the fields username and 'id but not the profile_set
Your UserSerializer should like this,
class UserSerializer(serializers.HyperlinkedModelSerializer):
# no need to set `profile.all` as you have related name profile defined in your model
profile_set = ProfileSerializer(source='profile', many=True)
class Meta:
model = User
depth = 1
fields = ['username', 'id', 'profile_set']
OR,
class UserSerializer(serializers.HyperlinkedModelSerializer):
profile = ProfileSerializer(many=True) # as you have related name `profile`
class Meta:
model = User
depth = 1
fields = ['username', 'id', 'profile']
Try setting the source of your serializer:
profile_set = ProfileSerializer(
source='profile.all',
read_only=True, many=True
)
It looks like you've set the related_name on your foreign key:
user = models.ForeignKey(User, related_name="profile", on_delete=PROTECT)
This defines the reverse relation name, so that's how you need to refer to it in DRF, too:
class UserSerializer(serializers.HyperlinkedModelSerializer):
profile = ProfileSerializer(read_only=True, many=True)
class Meta:
model = User
depth = 1
fields = ['username', 'id', 'profile']
Since it's clearly a plural, I'd also suggest you rename profile to profiles.

Add Extra fields in serializer from one to one relation models

In this project, I have two models Student and Parent related to each other through one to one field.
In Parent serializer, I want to add Students attributes like age. I am thinking of using SerializerMethodField for both cases is their any better way to do it?
I am not getting the queries on how to get the object attributes and little explanation would be great.
Here what I have done till now.
Models.py
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, default=None)
batch = models.ForeignKey(Batch, on_delete=models.CASCADE, null=True, related_name='students')
email = models.EmailField(null=True)
phone_number = models.CharField(max_length=10, null=True)
dob = models.DateField(blank=True, null=True, help_text="Enter in the following format : YYYY-MM-DD")
address = models.TextField(max_length=150, null=True)
age = models.IntegerField(blank=True)
image = models.ImageField(upload_to='profile_pictures', default='student_image.png', blank=True)
#property
def remarks(self):
return self.remark_set.all()
#property
def marks(self):
return self.marks_set.all()
def __str__(self):
return self.user.firstName + ' ' + self.user.lastName
class Parent(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, default=None)
child = models.ForeignKey(Student, on_delete=models.CASCADE)
email = models.EmailField(null=True)
phone_number = models.CharField(max_length=10, null=True)
address = models.TextField(max_length=150, null=True)
image = models.ImageField(upload_to='profile_pictures', default='student_image.png', blank=True)
def __str__(self):
return self.user.firstName + ' ' + self.user.lastName
Serilaizer.py
class ParentSerializer(serializers.HyperlinkedModelSerializer):
student_age = serializers.SerializerMethodField()
student_batch = serializers.SerializerMethodField()
parent_name = serializers.SerializerMethodField()
class Meta:
model = Parent
fields = "__all__"
def get_student_age(self, obj):
return Parent.objects.get(child__age = self.obj.user.child)
def get_student_batch(self, obj):
return Parent.objects.get(child__bacth = self.obj.user.child)
def get_parent_name(self, user):
return Parent.objects.get(user=self.request.user)
Views.py
class ParentView( mixins.ListModelMixin, mixins.RetrieveModelMixin,viewsets.GenericViewSet):
queryset = Parent.objects.all()
serializer_class = serializers.ParentSerializer
first way:
from apps.models import Student, parent
class BasicUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
class BasicStudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = "__all__"
class ParentSerializer(serializers.ModelSerializer):
user = BasicUserSerializer(read_only=True,many=False)
child = BasicStudentSerializer(read_only=True, many=True)
class Meta:
model = Parent
fields = '__all__'
you can do this way . its replace a serializer field that you want and if parent have several child then in child's field you have new all child's information as dictionary.
================================================================
second way is use HyperLinkModel .
class ParentSerializer(serializers.ModelSerializer):
user = serializers.HyperlinkedRelatedField(read_only=True,many=False)
child = serializers.HyperlinkedRelatedField(read_only=True, many=True)
class Meta:
model = Parent
fields = '__all__'
but notice that in first way you will have a independent serializer class that every time you need to serialize model class that related to User or Child you can use them simply.

Categories

Resources