Django serializer data - django

I need to get value of basket in 'title' not in 'id'.
How can I do this? How can I get a value of 'title' from 'Position' model in another 'Client' model using ManyToManyField. It automatically transmits ID and the 'title' is required
I have tried many ways but... It must be easy, but i search info 2 days
class Position(models.Model):
title = models.CharField(max_length=150, verbose_name='Title')
slug = models.SlugField(max_length=100, unique=True, db_index=True, verbose_name='URL')
description = models.CharField(max_length=500, verbose_name='Describe')
photo = models.ImageField(upload_to="photos/%Y/%m/", verbose_name='Photo', null=True)
price = models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Price')
date_create = models.DateTimeField(auto_now_add=True, verbose_name='Date create')
date_update = models.DateTimeField(auto_now=True, verbose_name='Date update')
is_published = models.BooleanField(default=True, verbose_name='Is published')
in_stock = models.BooleanField(default=True, verbose_name='In stock')
class Client(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
basket = models.ManyToManyField('Position', default=None, blank=True, related_name='basket')
def __str__(self):
return f'{self.user.username}, id-{self.user.id}'
class ClientSerializer(serializers.ModelSerializer):
class Meta:
model = Client
fields = "__all__"
class ClientViewSet(viewsets.ModelViewSet):
serializer_class = ClientSerializer
permission_classes = (IsOwnerOrReadOnly,)
def get_queryset(self):
pk = self.kwargs.get('pk')
# need a list of objects, not an one
return Client.objects.filter(pk=pk)
result:
{
"id": 1,
"user": 1,
"basket": [
1
]
}
need something like this - "basket":['monitor','keyboard']

You can use the PositionSerializer to get the title of each Position object in the Client's basket ManyToManyField.
class PositionSerializer(serializers.ModelSerializer):
class Meta:
model = Position
fields = ('title',)
class ClientSerializer(serializers.ModelSerializer):
basket = PositionSerializer(many=True, read_only=True)
class Meta:
model = Client
fields = "__all__"

Related

Django Rest Framework prefetching data

I would like to minimize number of queries to get data. I have 3 models:
class SubCategory(models.Model):
game = models.ForeignKey(Game, verbose_name=_("Gra"), on_delete=models.CASCADE)
name = models.CharField(verbose_name=_("Nazwa"), max_length=40)
...
class GameTask(CloneModel):
game = models.ForeignKey(Game, verbose_name='Gra', related_name='tasks', on_delete=models.CASCADE)
name = models.CharField(verbose_name='Nazwa', max_length=200)
subcategory = models.ForeignKey(SubCategory, verbose_name=_("Podkategoria"), on_delete=models.SET_NULL, blank=True, null=True)
class TaskLevel(CloneModel):
name = models.CharField(max_length=50)
master_task = models.ForeignKey(GameTask, related_name='sub_levels', on_delete=models.CASCADE)
My subcategory view looks like:
class SubCategoryList(ListAPIView, PermissionMixin):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = SubCategorySerializer
def get_queryset(self):
return SubCategory.objects.filter(game=self.get_game()).order_by("slug")
and my SubCategorySerializer:
class SubCategorySerializer(serializers.ModelSerializer):
developments = SubCategoryDevelopmentSerializer(many=True, read_only=True)
in_progress = serializers.SerializerMethodField()
class Meta:
model = SubCategory
fields = ("id", "name", "slug", "description", "image", "developments", "in_progress")
def get_in_progress(self, obj: SubCategory):
user = self.context["request"].user
subcategory_tasks = obj.gametask_set.all()
// rest of the logic
All I want to achieve is to return only tasks, which are related to TaskLevel model as master_task. I was trying using
subcategory_tasks = obj.gametask_set.all().prefetch_related("sub_levels")
but the amount of queries was the same. Could somebody give my any hint how to solve this?

how to use django Serializer or signal to add object in database?

I create ticket , ticketflow , ticketstate , tickettype models
i need a serializer or signal that when user create ticket programmatically add ticketflow object and set state of ticket to submited or something else
Here is my models
class TicketType(models.Model):
title = models.CharField(max_length=255, blank=False, unique=True, null=False)
def __str__(self):
return self.title
class TicketState(models.Model):
title = models.CharField(max_length=255, blank=False, unique=True, null=False)
def __str__(self):
return self.title
class Ticket(models.Model):
id = models.UUIDField(primary_key=True, default=uuid4 , editable=False)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE)
ticket_type = models.ForeignKey(TicketType,on_delete=models.CASCADE , default=1)
title = models.CharField(max_length=255, blank=False, null=False)
message = models.TextField()
attachment = models.FileField(upload_to='uploads/tickets/', validators=[FileExtensionValidator(allowed_extensions=['pdf','docx','zip','jpg','png'])], blank=True)
created_on = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
class TicketFlow(models.Model):
uuid = models.UUIDField(default=uuid4, editable=False)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE)
ticket = models.ForeignKey(Ticket,on_delete=models.CASCADE , related_name='ticketflow')
ticket_state = models.ForeignKey(TicketState,on_delete=models.CASCADE , default=1 , related_name='ticketstate')
message = models.TextField()
attachment = models.FileField(upload_to='uploads/tickets/', validators=[FileExtensionValidator(allowed_extensions=['pdf','docx','zip','jpg','png'])], blank=True)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now= True)
class Meta:
ordering = ['-created_on']
here is my serializers
class TicketTypeSerializer(serializers.ModelSerializer):
class Meta:
model = TicketType
fields = ('id','title',)
class TicketStateSerializer(serializers.ModelSerializer):
class Meta:
model = TicketState
fields = ('id','title',)
class TicketSerializer(serializers.ModelSerializer):
class Meta:
model = Ticket
fields = ['id' , 'author', 'ticket_type','title' ,'message' , 'attachment' , 'created_on']
class TicketFlowSerializer(serializers.ModelSerializer):
class Meta:
model = TicketFlow
fields = ['author', 'ticket_state', 'message', 'attachment', 'created_on', 'updated_on']
It'll be great if someone can help me out in this. how can i create signal or override create method in serializers
You probably want your "state" field to be read-only in the serializer, this way it can only be changed programmatically, and in the model set a default value with default='pending'.
Then you can override the update method in a Serializer (see the doc here):
def update(self, instance, validated_data):
validated_data['state'] = 'edited'
return super(MySerializer, self).update(instance, validated_data)

Django rest fetch data from bridge model

I want to get all the user details and list of all the roles against the
user details model
My Models
class UserDetail(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,
related_name='userdetail_user', default='111')
cn = models.CharField(max_length=200)
sn = models.CharField(max_length=200)
u_id = models.CharField(max_length=200)
display_name_cn = models.CharField(max_length=200)
display_name_en = models.CharField(max_length=200)
given_name = models.CharField(max_length=200)
employee_number = models.CharField(max_length=200)
email = models.CharField(max_length=200)
created_at = models.DateTimeField(default=datetime.now, blank=True)
last_login = models.DateTimeField(default=datetime.now, blank=True)
def __str__(self):
return self.given_name
class Role(models.Model):
title = models.CharField(max_length=20)
description = models.CharField(max_length=200)
created_at = models.DateTimeField(default=datetime.now, blank=True)
last_updated = models.DateTimeField(default=datetime.now, blank=True)
status = models.BooleanField(default=True)
def __str__(self):
return self.title
class UserRole(models.Model):
userdetail = models.ForeignKey(UserDetail, on_delete=models.CASCADE,
related_name='userrole_userdetail')
role = models.ForeignKey(Role, on_delete=models.CASCADE)
approver = models.ForeignKey(UserDetail, on_delete=models.SET_NULL,
null=True,
related_name='userrole_userdetail_approver')
created_at = models.DateTimeField(default=datetime.now, blank=True)
last_updated = models.DateTimeField(default=datetime.now, blank=True)
status = models.BooleanField(default=True)
My Serializers
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email')
class UserRoleSerializer(serializers.ModelSerializer):
class Meta:
model = UserRole
fields = (
'id', 'userdetail', 'role', 'approver', 'last_updated', 'status')
depth = 1
def to_representation(self, instance):
representation = super(UserRoleSerializer, self).to_representation(
instance)
representation['userdetail'] = UserDetailSerializer(
instance.userdetail).data
representation['role'] = RoleSerializer(instance.role).data
representation['approver'] = UserDetailSerializer(
instance.approver).data
return representation
class RoleSerializer(serializers.ModelSerializer):
class Meta:
model = Role
fields = ('id', 'title', 'description', 'last_updated', 'status')
class UserDetailSerializer(serializers.ModelSerializer):
user = UserSerializer()
roles = serializers.SerializerMethodField(read_only=True)
class Meta:
model = UserDetail
fields = ('id', 'roles', 'user', 'cn', 'sn', 'u_id', 'display_name_cn',
'display_name_en', 'given_name', 'employee_number', 'email',
'last_login')
lookup_field = 'u_id'
def get_roles(self, obj):
roles = UserRole.objects.filter(userdetail=obj)
return roles
When I try to fetch all the user details it gives me an error
"Object of type 'UserRole' is not JSON serializable".
I have already tried to serialize the list of object fetched inside get_roles method of UserDetailsSerializer but its no help
In your Serializers, you have to replace
roles = serializers.SerializerMethodField(read_only=True)
With
userrole_userdetail = UserRoleSerializer(many=True, read_only=True)
Its because your FK relation name must match the related name given in the model. Also in UserRoleSerializer you do not need the to_representation method.

Serializers in Foreign Key Django

i need to get information from Reservation, ReservationDetails and Product, but just get Reservation and ReservationDetails
i have 3 models
class Reservation(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
userReservation = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
dateStart = models.DateTimeField(null=False, blank=False, default=datetime.now)
dateFinish = models.DateTimeField(null=False, blank=False, default=datetime.now)
date_Created = models.DateTimeField(auto_now_add=True)
date_Modified = models.DateTimeField(auto_now=True, db_index=True)
def __str__(self):
return str(self.id)
class DetailsReservation(models.Model):
Reservation = models.ForeignKey(Reservation, blank=False, on_delete=models.CASCADE, null=True, related_name='reservation_details')
product = models.ForeignKey(Product, blank=False, on_delete=models.CASCADE, null=True, related_name='products_reservation')
Quantity = models.IntegerField(null=False, blank=False, default=0)
userbyReserva = models.ForeignKey(User, editable=False, on_delete=models.CASCADE, default=1)
class Product(models.Model):
product_Description = models.CharField(max_length=255)
Quantity = models.IntegerField(null=False, blank=False, default=0)
Quantity_Max_Reservation = models.IntegerField(null=False, blank=False, default=0)
product_Comments = models.CharField(max_length=255)
size = models.CharField(max_length=10, null=True)
product_Status = models.BooleanField(default=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True, related_name='products')
date_Created = models.DateTimeField(default=datetime.now, blank=True)
date_Modified = models.DateTimeField(default=datetime.now, blank=True)
And i tried to create serializers
class ReservationDetailsSerializers(serializers.ModelSerializer):
products = serializers.PrimaryKeyRelatedField(queryset=Product.objects.all(), required=False)
class Meta:
model= DetailsReservation
fields = ['Reservation', 'Quantity', 'userbyReserva', 'products']
class ReservationDetailsListSerializer(serializers.ModelSerializer):
reservation_details = ReservationDetailsSerializers(many=True)
class Meta:
model = Reservation
fields = ['id', 'userReservation', 'dateStart', 'dateFinish', 'reservation_details']
but the response does not show this field
[
{
"id": "6d87ba1c-61bc-41bd-80c8-31a51df8d32f",
"userReservation": 1,
"dateStart": "2018-09-16T17:19:34-05:00",
"dateFinish": "2018-09-16T17:19:35-05:00",
"reservation_details": [
{
"Reservation": "6d87ba1c-61bc-41bd-80c8-31a51df8d32f",
"Quantity": 1,
"userbyReserva": 1
>>"here should show this information product"
}
]
},
{
"id": "0ed26395-2579-4c40-9a63-460f5095ac51",
"userReservation": 2,
"dateStart": "2018-09-16T19:21:24-05:00",
"dateFinish": "2018-09-16T19:21:24-05:00",
"reservation_details": [
{
"Reservation": "0ed26395-2579-4c40-9a63-460f5095ac51",
"Quantity": 1,
"userbyReserva": 2
}
]
}
]
and it is my views.py
class getAllReservationDetails(generics.ListCreateAPIView):
queryset = Reservation.objects.prefetch_related('reservation_details')
print(queryset.query)
serializer_class = ReservationDetailsListSerializer
def get_object(self):
queryset = self.queryset()
obj = get_object_or_404(queryset)
return obj
I review this Link, but i don't know, why doesn't show the information product.
But, that is not working as I wanted.
What should I do?
Did you try creating a serializer for the Product model and use it on the ReservationDetailsSerializers?
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
class ReservationDetailsSerializers(serializers.ModelSerializer):
products = ProductSerializer(source='product', required=False)
class Meta:
model= DetailsReservation
fields = ['Reservation', 'Quantity', 'userbyReserva', 'products']
You can find more about this topic on Specifying nested serialization
The DetailsReservation model has not attribute products, but it has product. So remove the "s" from products or use source = 'product' in ReservationDetailsSerializers serializer
Method - 1 : removal of "s"
class ReservationDetailsSerializers(serializers.ModelSerializer):
product = serializers.PrimaryKeyRelatedField(queryset=Product.objects.all(), required=False)
class Meta:
model= DetailsReservation
fields = ['Reservation', 'Quantity', 'userbyReserva', 'product']
Method - 2 : speciying source argument
class ReservationDetailsSerializers(serializers.ModelSerializer):
products = serializers.PrimaryKeyRelatedField(queryset=Product.objects.all(),
required=False, source='product')
class Meta:
model = DetailsReservation
fields = ['Reservation', 'Quantity', 'userbyReserva', 'products']
UPDATE
I think you need nested serializer representation. If so, you've to define a seperate serializer (say ProductSerializer) and add it to ReservationDetailsSerializers instead of serializers.PrimaryKeyRelatedField()
#new serializer class
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__' # you can specify the fields here
Hence Method-1 become
class ReservationDetailsSerializers(serializers.ModelSerializer):
product = ProductSerializer(required=False)
class Meta:
model= DetailsReservation
fields = ['Reservation', 'Quantity', 'userbyReserva', 'product']
and the Method-2 become
class ReservationDetailsSerializers(serializers.ModelSerializer):
products = ProductSerializer(required=False, source='product')
class Meta:
model = DetailsReservation
fields = ['Reservation', 'Quantity', 'userbyReserva', 'products']

DRF - nested serializer

I have several models
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
gender = models.CharField(max_length=2)
name = models.CharField(max_length=200)
birthday = models.DateField(auto_now=False, auto_now_add=False)
weight = models.IntegerField(default=0)
heigth = models.IntegerField(default=0)
sign = models.CharField(max_length=200, choices=SIGNS_CHOICES, default='E')
orientation = models.CharField(max_length=200, choices=ORIENTATION_CHOICES, default='E')
bodytype = models.CharField(max_length=200, choices=BODYTYPE_CHOICES, default='E')
education = models.CharField(max_length=200, choices=EDUCATION_CHOICES, default='E')
religion = models.CharField(max_length=200, choices=RELIGION_CHOICES, default='E')
smoking = models.CharField(max_length=200, choices=SMOKING_CHOICES, default='E')
alcohol = models.CharField(max_length=200, choices=ALCOHOL_CHOICES, default='E')
kids = models.CharField(max_length=200, choices=KIDS_CHOICES, default='E')
pets = models.CharField(max_length=200, choices=KIDS_CHOICES, default='E')
location = models.CharField(max_length=100)
latitude = models.FloatField()
longtitude = models.FloatField()
class ProfilePic(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profilePic = models.ImageField(upload_to='Images/', default='Images/None/No-img.jpg')
class ProfileFields(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
order = models.IntegerField(default=0)
and several serizlizers
class ProfilePicSerializer(ModelSerializer):
class Meta:
model = ProfilePic
fields = [
'profilePic',
'user',
]
class ProfileSerializer(ModelSerializer):
class Meta:
model = Profile
fields = '__all__'
class ProfileFieldsSerializer(ModelSerializer):
class Meta:
model = ProfileFields
fields = [
'user',
'title',
'text',
'order'
]
What I try to do is to create user serizlizer that will show profile, profilePic and profileFields
I do it like so
class UserSerializer(ModelSerializer):
profile = ProfileSerializer(many=False)
profilePic = ProfilePicSerializer(many=False)
profile_fields = ProfileFieldsSerializer(many=True)
class Meta:
model = User
fields = '__all__'
write_only_fields = ('password',)
read_only_fields = ('id',)
def create(self, validated_data):
user = User.objects.create(
username=validated_data['username'],
email=validated_data['email'],
)
user.set_password(validated_data['password'])
user.save()
return user
But I get error
Got AttributeError when attempting to get a value for field `profilePic` on serializer `UserSerializer`.The serializer field might be named incorrectly and not match any attribute or key on the `User` instance.Original exception text was: 'User' object has no attribute 'profilePic'.
Profile model adds to JSON, but profilePic and profileFields return error about not matching and attribute. What Am I doing wrong here ?
It is not recognizing profilePic on the user instance because it doesn't exist. If you try to do user.profilePic you'll get the same error.
You should be able to set the related_name on the ProfilePic model user ForeignKey so that user has a profilePic property and user.profilePic returns the user's profile pic.
class ProfilePic(models.Model):
user = models.OneToOneField(User, related_name="profilePic", on_delete=models.CASCADE)
...