django select only specific fields from many to many field in serializer - django

My models:
class RequisiteItem(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
enrollable = models.ForeignKey(Enrollable, on_delete=models.CASCADE)
created_by = models.ForeignKey(ElsUser, on_delete=models.CASCADE)
completed_within_days = models.IntegerField()
date_completed_by = models.DateTimeField(default=now, editable=False)
class Requisite(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(default=None, blank=True, null=True, max_length=255)
description = models.CharField(default=None, blank=True, null=True, max_length=255)
items = models.ManyToManyField(RequisiteItem, blank=True)
enrolments = models.ManyToManyField(Enrollee, blank=True)
created_by = models.ForeignKey(ElsUser, on_delete=models.CASCADE, related_name="requisites", default=None)
timestamp = models.DateTimeField(default=now, editable=False)
#property
def created_by_user(self):
return self.created_by.username
Serializer class:
class RequisiteSerializer(serializers.ModelSerializer):
created_by = serializers.CharField(source='created_by_user')
class Meta:
model = Requisite
fields = ('id', 'name', 'description', 'items', 'enrolments', 'created_by', 'timestamp')
read_only_fields = ['id']
depth = 1
I have enrolments ,created by,requisite items which are foreign keys and manytomany fields etc .In my list API i want only specific fileds from the foreign key to be displayed. For example in the created by field, Elsuser is a custom user inheriting from AbstractUser . I want only the username and email fields from this model and not the entire fields. Similar case for the manyto many fields . How do i implement this?

You can create a serializer to get only the required fields. Example:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('') #the fields you require to display
Then change your serializer as:
class RequisiteSerializer(serializers.ModelSerializer):
created_by = UserSerializer()
class Meta:
model = Requisite
fields = ('id', 'name', 'description', 'items', 'enrolments', 'created_by', 'timestamp')
read_only_fields = ['id']
depth = 1

Related

Serializing specific fields from another model

I was trying to serialize policy_length, coverage_amount from Policy model and use it in a serializer that was using Insuree model.
I'm using Policy and Insuree models:
Policy model
class Policy(TimeStampedModel):
policy_length = models.FloatField(max_length=2, blank=True, null=True)
coverage_amount = models.FloatField(max_length=256, blank=True, null=True)
Insuree model
class Insuree(TimeStampedModel):
user = models.OneToOneField(
'User', related_name='insuree', null=False, on_delete=models.CASCADE,
primary_key=True)
coverage_amount = models.ForeignKey(Policy, on_delete=models.CASCADE, max_length=256, blank=True, null=True)
policy_length = models.ForeignKey(Policy, on_delete=models.CASCADE, max_length=2, blank=True, null=True)
class PolicySelectionSerializer(serializers.ModelSerializer):
class Meta:
model = Insuree
fields = ('age', 'gender', 'disposable_income') #Current fields
fields = ('age','gender',disposable_income', 'policy_length', 'coverage_amount') #The field I need and want to do
You may use Nested Serializer.
PolicySerializer(ModelSerializer)
class Meta:
model = Policy
fields = ( 'policy_length', 'coverage_amount')
InsureeSerializer(ModelSerializer)
class Meta:
policy = PolicySerializer(many = True)
model = Insuree
fields = ('age', 'gender', 'disposable_income', 'policy',)

How do I filter data with two parameter from two different Django models

I want to create a JSON object which will
Search the particular Projects from the model "EmpProject" by a specific emp_id
Search whose project status is "Pending" from the model "Project" with the help of (1.) Search result
I am using JSON Parser (no models or generic view)
Models
Below are my models I have not use many to many field instead I created a Intermediate Table if the solution is also possible by using manytomanyfield than also suggest
class Employee(models.Model):
employeeid = models.IntegerField()
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
phone_no = models.CharField(max_length=10)
date_of_birth = models.DateField()
email = models.EmailField(unique=True)
password = models.CharField(max_length=50)
designation = models.CharField(max_length=50)
dept_id = models.ForeignKey(Department, on_delete=models.SET_NULL, null=True, blank=True)
class Meta:
ordering = ('id',)
def __str__(self):
return self.emp_name
class Project(models.Model):
projectname = models.CharField(max_length=50, unique=True,)
project_status = models.CharField(max_length=50)
description = models.TextField()
start_date = models.DateField(auto_now_add=True)
due_date = models.DateField()
class Meta:
ordering = ('id',)
def __str__(self):
return self.projectname
class EmpProject(models.Model):
emp_id = models.ForeignKey(Employee,on_delete=models.SET_NULL, null=True, blank=True)
project_id = models.ForeignKey(Project, on_delete=models.SET_NULL, null=True, blank=True)
class Meta:
unique_together = [['emp_id','project_id']]
ordering = ('project_id',)
def __str__(self):
return self.emp_id
Serializer
class EmployeeSerializer(serializers.ModelSerializer):
dept_id = serializers.SlugRelatedField(queryset=Department.objects.all(), slug_field='dept_name')
class Meta:
model = Employee
fields = [
'id',
'employeeid',
'first_name',
'last_name',
'phone_no',
'date_of_birth',
'email',
'password',
'designation',
'dept_id',
]
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = [
'id',
'projectname',
'project_status',
'description',
'start_date',
'due_date' ,
]
class EmpProjectSerializer(serializers.ModelSerializer):
emp_id=serializers.SlugRelatedField(queryset=Employee.objects.all(),slug_field='employeeid')
project_id=serializers.SlugRelatedField(queryset=Project.objects.all(),slug_field='projectname')
class Meta:
model = EmpProject
fields = [
'emp_id',
'project_id',
]
You can try something like this:
Project.objects.filter(id__in=EmpProject.objects.filter(id__in=emp_id).values("project_id"), project_status="Pending")
Few points worth mentioning:
It's good idea to use a intermediate table when we want to have extra data related to association. But for that kindly have a look at through attribute supported in ManyToManyField https://docs.djangoproject.com/en/2.2/ref/models/fields/#django.db.models.ManyToManyField.through
project_status is CharField, I think you should consider ChoiceField, charfield may introduce lots of dirty data in database.

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.

Django rest nested serializer not displaying fields

I have a model Workflow and WorkflowLevel. Each workflow has many WOrkflow levels .Im trying to use nested serializer :
class WorkflowLevelSerializer
(serializers.ModelSerializer):
class Meta:
model = WorkflowLevel
fields = '__all__'
class
WorkflowSerializer
(serializers.ModelSerializer):
levels = WorkflowLevelSerializer(many=True)
class Meta:
model = Workflow
fields = ('id', 'name', 'description',
'tenant', 'levels')
models.py:
class Workflow(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=32, default=None, null=True)
description = models.CharField(max_length=100, default=None, null=True)
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, default=None,
null=False)
class Meta:
unique_together = ('name', 'tenant',)
class WorkflowLevel(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
workflow = models.ForeignKey(Workflow, on_delete=models.CASCADE,
default=None, null=False)
level = models.IntegerField(default=None, null=False)
operation = models.CharField(max_length=32, default=None, null=False)
class Meta:
unique_together = ('workflow', 'level',)
The levels field is not displaying in the workflow listAPI view .
Getting error:
Got AttributeError when attempting to get a value
for field `levels` on serializer
`WorkflowSerializer`.
The serializer field might be named incorrectly
and not match any attribute or key on the
`Workflow` instance.
Original exception text was: 'Workflow' object
has no attribute 'levels'.
You can define related_name in the Model like this:
workflow = models.ForeignKey(Workflow, on_delete=models.CASCADE, related_name="levels", default=None, null=False)
I am using related_name='levels', so that in Serializer, it will use that reverse relationship name to fetch WorkflowLevel data from db.

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