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

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).

Related

how to make serializer for two models that dont have relation with each other

i am working on ecommerce shop and in my home page i want to return all the products and 7 images for the icons for the categories , my models.py is
class Product(models.Model):
pub_date = models.DateTimeField(default=datetime.now)
price = models.DecimalField(max_digits=100,decimal_places=2,null=False,blank=False)
category = models.CharField(max_length=20 ,blank=False, null=False ,default='none', choices=cat)
product_name = models.CharField(max_length = 50, null=True)
photo = models.ImageField(upload_to = 'product_photos/%y/%m/%d',null=True)
class Category(models.Model):
icon = models.ImageField(upload_to = 'icon',null=True)
and my serializers.py is
class ProductSerializer (serializers.ModelSerializer):
class Meta :
model = Product
fields = '__all__'
class CategorySerializer (serializers.ModelSerializer):
class Meta :
model = Category
fields = '__all__'
and my views.py
#api_view(['GET'])
#permission_classes ([AllowAny] , )
def home (request):
p = Product.objects.filter(is_discount= 1).order_by('-pub_date')
serializer = ProductSerializer(p,many=True)
return Response (serializer.data)
how to return both the category and product in the same view , NOTE : my views.py is function based view

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__'

pass user data to serializer in nested serializers when creating object in django rest framework

When User tries to add an Announcement, should i pass all the informations of the user in the form ?
i'm using token authentification.
So for adding an Announcement the user must be authenticated.
Models.py
class User(AbstractUser):
username = None
email = models.EmailField(max_length=100, verbose_name='email',
unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
class Announcement(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
photo = models.ManyToManyField(Photo, blank=True)
class Photo(models.Model):
name = models.CharField(max_length=100)
content_type = models.CharField(max_length=100)
path = models.CharField(max_length=100)
class Parameter(models.Model):
name = models.CharField(max_length=100)
value = models.FloatField(blank=True, null=True)
announcement = models.ForeignKey(
Announcement,related_name='parameters', on_delete=models.CASCADE)
Serializers.py
class AnnouncementSerializer(serializers.ModelSerializer):
author = UserSerializer(required=True)
parameters = ParameterSerializer(many=True,
required=False)
photo = PhotoSerializer(many=True,
required=False)
class Meta:
model = Announcement
fields = ['id', 'name', 'author',
'parameters', 'photo']
class UserSerializer(serializers.ModelSerializer):
photo = PhotoSerializer()
class Meta:
model = User
fields = ['id', 'email','photo', ]
class ParameterSerializer(serializers.ModelSerializer):
class Meta:
model = Parameter
fields = '__all__'
class PhotoSerializer(serializers.ModelSerializer):
class Meta:
model = Photo
fields = '__all__'
Views.py
class AnnouncementCreate(CreateAPIView):
permission_classes = [IsAuthenticated]
queryset = models.Announcement.objects.all()
serializer_class = AnnouncementSerializer
When trying the browsable API. to create a new announcement i have to enter all the informations of the user. But if the user is already authenticated. is there any solution to create the announcement for only this user and show it to the other users ?
If you don't want to create a User when creating an Announcement, omit the author field from your AnnouncementSerializer, then pass the current user when saving serializer object:
serializer.py
class AnnouncementSerializer(serializers.ModelSerializer):
parameters = ParameterSerializer(many=True, required=False)
photo = PhotoSerializer(many=True, required=False)
class Meta:
model = Announcement
fields = ['id', 'name', 'parameters', 'photo']
views.py
class AnnouncementCreate(CreateAPIView):
permission_classes = [IsAuthenticated]
queryset = models.Announcement.objects.all()
serializer_class = AnnouncementSerializer
def perform_create(self, serializer):
serializer.save(author=self.request.user)

I cannot register a user using Django-Rest-Framework

I can't add a new user using Django Rest Framework. Here is my code from models.py:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
password = models.CharField(max_length=15, default= None)
first_name = models.CharField(max_length=100, validators=[name_validator])
last_name = models.CharField(max_length=100, validators=[name_validator])
email = models.CharField(max_length=100, validators=[mail_validator])
created_at = models.DateTimeField(auto_now_add=True)
As you can see I am using models.OneToOneField cause I want to extend the default user to add some more fields.
Bellow is my serializers.py file:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
permissions_classes = [
permissions.AllowAny
]
fields = '__all__'
The viewset is the following:
class UserViewset(viewsets.ModelViewSet):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
When I go to my endpoints and try to add a new user, I cannot put anything in the "user" field:
Click for image
I am a beginner and it would be of great help.
Thank you!
you can to this
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
password = models.CharField(max_length=15, default= None)
first_name = models.CharField(max_length=100, validators=[name_validator])
last_name = models.CharField(max_length=100, validators=[name_validator])
email = models.CharField(max_length=100, validators=[mail_validator])
created_at = models.DateTimeField(auto_now_add=True)
serializer.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
class ProfileSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
class Meta:
model = Profile
fields = '__all__'
views.py
class UserViewset(viewsets.ModelViewSet):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
permission_classes = [permission. AllowAny,]
When you want to extend the default user to add some more fields, the best way for that is substituting a custom User model by inheritance the AbstractUser model. Using this way, you can CRUD the user easily.

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.

Categories

Resources