drf create manytomany fields - django

models
class CreatorRawArtwork(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=500)
descripton = models.TextField()
editions = models.IntegerField(null=True, blank=True)
price = models.CharField(max_length=500)
created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)
medias = models.FileField(null=True, blank=True, upload_to="raw-medias")
user = models.ForeignKey(to=Login, on_delete=models.CASCADE, related_name="creatorrawartwork", null=True, blank=True
)
collection = models.ForeignKey(
to=DesignerCollection, on_delete=models.CASCADE, related_name="creatorrawartwork", null=True, blank=True)
categories = models.ManyToManyField(DesignerCategories, related_name='creatorrawartwork')
def __str__(self):
return self.title
serializer
class CreatorRawArtworkSerializer(serializers.ModelSerializer):
categories = serializers.PrimaryKeyRelatedField(queryset=DesignerCategories.objects.all(), many=True)
class Meta:
model = CreatorRawArtwork
fields = "__all__"
depth=1
views
class CreatorRawArtworkView(viewsets.ModelViewSet):
queryset = CreatorRawArtwork.objects.all()
serializer_class = CreatorRawArtworkSerializer
Here i am trying to create manytomany fields using drf serialier it is showing some error
plese check the screenshot for parameter and responses
What can be the issue please take a look

class CreatorRawArtworkSerializer(serializers.ModelSerializer):
collection = DesignerCollectionSerializer(read_only=True) #assuming you have already defined serializer for *DesignerCollectionSerializer*
categories = DesignerCategoriesSerializer(many=True)
class Meta:
model = CreatorRawArtwork
fields = "__all__"
depth=1

I tested with your code and your code is working fine
just make sure your request data is json

Related

How to display all child category from parent category in django-rest-framework

I'm trying to show my all children category from parent category. I want to just hit one API end and show all tables which is related to that item. I want to hit "Master-Category" and show all releated "Category","Sub-Category" and "Root-Item" in Hierarchy form. I display all the data but cannot in Hierarchy form. Can anyone please give me the solution for this problem.
Model.py
from django.db import models
from django.contrib.auth.models import User
class MasterCategory(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True,
verbose_name="Created By")
title = models.CharField(max_length=100, null=False, blank=False)
description = models.TextField(default='')
def __str__(self):
return str(self.title)
#property
def category(self):
data = NewCategory.objects.filter(master_category__id=self.id).values
return data
#property
def sub_category(self):
data = NewSubcategory.objects.filter(category__id=self.id).values
return data
#property
def root_item(self):
data = Rootitem.objects.filter(sub_category__id=self.id).values
return data
class NewCategory(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True,
verbose_name="Created By")
title = models.CharField(max_length=100, null=False, blank=False)
description = models.TextField(default="")
master_category = models.ForeignKey(
MasterCategory, on_delete=models.CASCADE, null=True, blank=True)
def __str__(self):
return str(self.title)
class NewSubcategory(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True,
verbose_name="Created By")
title = models.CharField(max_length=100, null=False, blank=False)
description = models.TextField(default="")
category = models.ForeignKey(NewCategory, on_delete=models.CASCADE, null=True,
blank=True)
def __str__(self):
return str(self.title)
class Rootitem(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True,
verbose_name="Created By")
title = models.CharField(max_length=100, null=False, blank=False)
description = models.TextField(default="")
sub_category = models.ForeignKey(NewSubcategory, on_delete=models.CASCADE,
null=True, blank=True)
def __str__(self):
return str(self.title)
Serializers.py
I add #property function name in MasterCategorySerializer fields, "category", "sub_category", "root_item"
from .models import MasterCategory, NewCategory, NewSubcategory, Rootitem
from rest_framework import serializers
class MasterCategorySerializer(serializers.ModelSerializer):
class Meta:
model = MasterCategory
fields = ["title", 'category', 'sub_category', 'root_item']
class NewCategorySerializer(serializers.ModelSerializer):
class Meta:
model = NewCategory
fields = "__all__"
class NewSubcategorySerializer(serializers.ModelSerializer):
new_cat = NewCategorySerializer(source='category',read_only=True, many=True)
class Meta:
model = NewSubcategory
fields = "__all__"
class RootitemSerializer(serializers.ModelSerializer):
class Meta:
model = Rootitem
fields = "__all__"
**Viewset.py**
from API_app.models import MasterCategory
from API_app.serializers import MasterCategorySerializer
from rest_framework import viewsets
class MasterCategoryViewSet(viewsets.ModelViewSet):
queryset = MasterCategory.objects.all()
serializer_class = MasterCategorySerializer
My Desired Output, what i want.
{
Electronics <---- Master-Category
{
Smart-Phone <---- Category
{
Samsung <---- Sub-Category
{
Samsung S20 Ultra <---- Root-Item
}
}
}
}
Change your serializers as below. For this nested structure you don't need properties. As tables are connected with foreign key you can define related name between models and assign to its serializer. Default related name between table is tablename_set.
class RootitemSerializer(serializers.ModelSerializer):
class Meta:
model = Rootitem
fields = "__all__"
class NewSubcategorySerializer(serializers.ModelSerializer):
rootitem_set = RootitemSerializer(many=True)
class Meta:
model = NewSubcategory
fields = "__all__"
class NewCategorySerializer(serializers.ModelSerializer):
newsubcategory_set = NewSubcategorySerializer(many=True)
class Meta:
model = NewCategory
fields = "__all__"
class MasterCategorySerializer(serializers.ModelSerializer):
newcategory_set = NewCategorySerializer(many=True)
class Meta:
model = MasterCategory
fields = "__all__"
We have relationship between MasterCategory and NewCategory. As you don't define related_name therefore related name is newcategory_set and its response is NewCategorySeralizer. Make many=True because they are related with foreign key as there can be multiple newcategory related to mastercategory. Other relations are same as above explanation.
If you want to change this default related name then look at related_name, you can define it inside models.ForeignKey()

DRF using prefetch_related

I have two classes Vessels and Components, each vessel has several components.
I just want to fetch all vessels and all their related components in one query, I thought prefretch_related does that trick but in DRF in the api i am only receiving the vessels without their related components
models.py
class Vessel(models.Model):
name = models.CharField(max_length=255, null=True, blank=True)
imo = models.CharField(max_length=255, null=True, blank=True)
def __str__(self):
return self.name
class Component(models.Model):
vessel = models.ForeignKey(
Vessel, blank=True, null=True, on_delete=models.CASCADE, related_name='vessel_components')
name = models.CharField(max_length=200, blank=True, null=True)
manufacturer = models.CharField(max_length=200, blank=True, null=True)
model = models.CharField(max_length=200, blank=True, null=True)
type = models.CharField(max_length=200, blank=True, null=True)
remarks = models.TextField(blank=True, null=True)
def __str__(self):
return self.name
serializers.py
class VesselSerializer(serializers.ModelSerializer):
class Meta:
model = Vessel
fields = '__all__'
class ComponentSerializer(serializers.ModelSerializer):
class Meta:
model = Component
fields = '__all__'
the view :
#api_view(['GET'])
def getVessels(request):
vessels = Vessel.objects.all().prefetch_related('vessel_components')
vSerializer = VesselSerializer(vessels, many=True)
return Response(vSerializer.data)
the result i am getting :
I thought prefretch_related does that trick but in DRF.
This will fetch the Components for the Vessels, but since your serializers do not serialize these components, these will not end up in the result.
You should define the ComponentSerializer as subserializer for VesselSerializer, so:
class ComponentSerializer(serializers.ModelSerializer):
class Meta:
model = Component
fields = '__all__'
class VesselSerializer(serializers.ModelSerializer):
vessel_components = ComponentSerializer(many=True) # 🖘 subserializer
class Meta:
model = Vessel
fields = '__all__'

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)

how to use RelatedField in Django rest framework?

I have problem with Django restframe work i have 2 table that one of them is a foreign key to another i have used RelatedField in serializer but i get an error:'Relational field must provide a queryset argument,
can someone help me in this case
my code is as below:
class DocTable(models.Model):
project = models.CharField(max_length=1000, null=True, blank=True)
document_no = models.CharField(max_length=1000, null=True, blank=True)
document_title = models.TextField(null=True, default='', blank=True)
class PlanTable(models.Model):
document = models.ForeignKey(DocTable, on_delete=models.CASCADE, related_name='doctable')
work_type = models.CharField(max_length=1000, null=True, blank=True)
description_work = models.TextField(null=True, default='', blank=True)
serializers.py
class DocTableSerializer(serializers.ModelSerializer):
doctable = serializers.RelatedField(many=True)
class Meta:
model = DocTable
fields = ['pk', 'project', 'document_no', 'doctable']
read_only_fields = ['pk']
class PlanTableSerializer(serializers.ModelSerializer):
class Meta:
model = PlanTable
fields = ['pk', 'document', 'work_type', 'description_work']
read_only_fields = ['pk']
views.py
class DocTableListView(generics.ListAPIView):
lookup_field = 'pk'
serializer_class = DocTableSerializer
def get_queryset(self):
return PlanTable.objects.all()
def get_object(self):
pk = self.kwargs.get('pk')
return PlanTable.objects.get(pk=pk)
You have to provide queryset in RelatedField like this.
class DocTableSerializer(serializers.ModelSerializer):
doctable = serializers.RelatedField(many=True, queryset=DocTable.objects.all())
Or if you only want to use this related field for retrieving data, you can mark it as read only
doctable = serializers.RelatedField(many=True, read_only=True)

DRF need values instead of ID

This is my serializer class
class ProjectSerializer(ModelSerializer):
class Meta:
model = Project
exclude = ['deleted_at']
This is Models.py
class MandatoryFields(SoftDeletionModel):
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="%(app_label)s_%(class)s_created",null=True)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="%(app_label)s_%(class)s_updated",null=True)
created_date = models.DateTimeField(auto_now_add=True,null=True)
modified_date = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Project(MandatoryFields, Model):
project_name = models.CharField(max_length=255, blank=True)
project_areas = models.CharField(max_length=255, blank=True)
project_manager = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=True, null=True,
related_name="%(app_label)s_%(class)s_project_manager")
start_date = models.DateField(null=True, blank=True)
end_date = models.DateField(null=True, blank=True)
REQUIRED_FIELDS = []
def __str__(self):
return self.project_name
I am getting Id's for the foreign keys created_by,updated_by,project_manager .But I need the values instead of Id.
for example I am getting
created_by : 1
But I need
created_by: Alex
I have tried the following
class ProjectSerializer(ModelSerializer):
created_by = SlugRelatedField(read_only=True, slug_field='created_by')
class Meta:
model = Project
exclude = ['deleted_at']
But I am getting null values.
I think that's achievable by specifying source attribute for serializer field
Somthing like this:
class ProjectSerializer(ModelSerializer):
created_by = CharField(source="created_by.first_name")
class Meta:
model = Project
exclude = ['deleted_at']
Reference : https://www.django-rest-framework.org/api-guide/fields/#source