How to include ManyToMany Fields in DjangoRestFramework? - django

class EntityServiceSerializer(serializers.ModelSerializer):
class Meta:
model = Service
fields = '__all__'
class EntityCreateSerializer(serializers.ModelSerializer):
entity_service = EntityServiceSerializerThrough(read_only=True, source='serviceschedule_set', many=True)
class Meta:
model = Entity
fields = '__all__'
Model looks like this
class Entity(models.Model):
entity_service = models.ManyToManyField(Service, through='ServiceSchedule')
class ServiceSchedule(models.Model):
service = models.ForeignKey(Service, on_delete=models.CASCADE)
entity = models.ForeignKey(Entity, on_delete=models.CASCADE)
class Service(models.Model):
service_name = models.CharField(max_length=256, null=True)
slug = models.SlugField(max_length=128, unique=True, null=False, editable=False)
created_at = models.DateTimeField(editable=False, default=timezone.now)
updated_at = models.DateTimeField(default=timezone.now)
animal = models.ForeignKey(Animal, on_delete=models.CASCADE, default=None)
I have these serializers (there are more fields in entity model, but they're irrelevant since the only problem i have is with the Many2Many)
The thing is, when i put in body "entity_service": [1,2] in the response i still get = []. Even though i have in my database Services with pk 1,2,3,4.
Do you know how can i make it work?

Try it without a source as the field name is the same as the model field name
class EntityCreateSerializer(serializers.ModelSerializer):
entity_service = EntityServiceSerializerThrough(read_only=True, many=True)
class Meta:
model = Entity
fields = '__all__'

Related

How do I pull in data from multiple models into a specific model serializer?

I have this model that represents a bookmark or favorite. It has multiple foreign keys to other models. In the api I would like to pull in the data from each of the models that is referenced in the particular bookmark.
The model:
class Bookmark(models.Model):
marktype = models.CharField(max_length=10)
post = models.OneToOneField(Post, on_delete=models.CASCADE, null=True, blank=True)
question = models.OneToOneField(Question, on_delete=models.CASCADE, null=True, blank=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="created at")
updated_at = models.DateTimeField(auto_now=True, verbose_name="updated at")
class Meta:
verbose_name = "bookmark"
verbose_name_plural = "bookmarks"
ordering = ["created_at"]
db_table = "bookmarks"
def __str__(self):
return "{}'s bookmark".format(self.owner.username)
I tried to use a SerializerMethodField but I get an error: 'NoneType' object has no attribute 'id'
Here is the serializer
class BookmarkSerializer(serializers.ModelSerializer):
post = serializers.SerializerMethodField()
question = serializers.SerializerMethodField()
class Meta:
model = Bookmark
fields = '__all__'
def get_post(self, obj):
obj = Post.objects.get(id=obj.post.id)
post = ShortPostSerializer(obj)
return post.data
def get_question(self, obj):
obj = Question.objects.get(id=obj.question.id)
question = ShortQuestionSerializer(obj)
return question.data
what am I doing wrong please?
You can update your serializer like the following (You can short it as you want or use your ShortQuestionSerializer as well instead of QuestionSerializer),
class QuestionSerializer(serializers.ModelSerializer):
class Meta:
model = Question
fields = '__all__'
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__'
class BookmarkSerializer(serializers.ModelSerializer):
post = PostSerializer()
question = QuestionSerializer()
class Meta:
model = Bookmark
fields = '__all__'

drf create manytomany fields

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

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.

Django rest framework get all related foreign key

I have two models Organization and Departments. I would like to get all the department related particular organization id by using DRF, how can I do this
class Organization(models.Model):
name = models.CharField(max_length=30, unique=True)
description = models.CharField(max_length=100)
class Departments(models.Model):
name = models.CharField(max_length=30, unique=True)
description = models.CharField(max_length=100)
email= models.CharField(max_length=30, unique=True)
phone= models.CharField(max_length=30)
org_linked=models.ForeignKey(Organization)
user_linked=models.ForeignKey(User)
class OrganizationAndDepartmentSerializer(serializers.ModelSerializer):
org_department=facilitesntSerializer(many=True)
class Meta:
model = facilites
fields=('org_department',)
class OrganizationAndDepartmentViewSet(viewsets.ModelViewSet):
serializer_class =OrganizationAndDepartmentSerializer
If you want the full nested representation; declare a nested serializer as follows:
class DepartmentSerializer(serializers.ModelSerializer):
class Meta:
model = Departments
fields = ('__all__')
class OrganizationSerializer(serializers.ModelSerializer):
departments = DepartmentsSerializer(many=True, source='org_linked_set', read_only=True)
class Meta:
model = Organization
fields = (
'name',
'description',
'departments'
)

Django REST Framework join table results in attribute exception

I am building an API in Django using REST Framework but am running into an issue.
Serializers:
class SquadSerializer(serializers.Serializer):
class Meta:
model = Squad
fields = ('name')
id = serializers.IntegerField(read_only=True)
name = serializers.CharField(style={'base_template': 'textarea.html'})
class MembershipSerializer(serializers.Serializer):
class Meta:
model = Membership
fields = ('employee_id', 'squad_id')
squad = SquadSerializer()
employee = EmployeeSerializer()
class EmployeeSerializer(serializers.HyperlinkedModelSerializer):
habitat = HabitatSerializer()
class Meta:
model = Employee
fields = ('id', 'first_name', 'last_name', 'function',
'start_date', 'end_date', 'visible_site', 'habitat')
Models:
class Employee(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
function = models.CharField(max_length=50)
start_date = models.DateField()
end_date = models.DateField(null=True, blank=True)
visible_site = models.BooleanField()
habitat = models.ForeignKey(Habitat, on_delete=models.SET_NULL, null=True, blank=True)
class Squad(models.Model):
name = models.TextField(max_length=40)
class Membership(models.Model):
class Meta:
unique_together = (('employee', 'squad'))
employee = models.ForeignKey(Employee, on_delete=models.CASCADE, null=False, blank=True, default=1)
squad = models.ForeignKey(Squad, on_delete=models.CASCADE, null=False, blank=True, default=1)
The problem is that I keep running into this error:
AttributeError: Got AttributeError when attempting to get a value for field `name` on serializer `SquadSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Membership` instance.
Original exception text was: 'Membership' object has no attribute 'name'.
When executing this test (and a couple others)
def test_membership_serializer_id_name_field_content(self):
"""
The name field of a squad should contain an id
"""
serializer = create_membership_serializer(self.membership, '')
self.assertEqual(serializer.data['id'], self.membership.id)
I've seen multipe people with the same issues here on Stack Overflow but the often suggest solution (to add many=True to SquadSerializer() and EmployeeSerializer()) doesn't work. I hope anyone here has any knowledge on why this happens.
If you want to map your seriailizer to your model, you should use ModelSerializer. In tupple, if it has only one value, you should write it as (1,) not (1). Your SquadSerializer should be like
class SquadSerializer(serializers.ModelSerializer):
class Meta:
model = Squad
fields = ('name',) # or ('id', 'name')
id = serializers.IntegerField(read_only=True)
name = serializers.CharField(style={'base_template': 'textarea.html'})
Your MembershipSerializer should be like
class MembershipSerializer(serializers.ModelSerializer):
class Meta:
model = Membership
fields = ('employee', 'squad')
squad = SquadSerializer()
employee = EmployeeSerializer()