Home > Software design >  Foreign key field not rendering in serializers django
Foreign key field not rendering in serializers django

Time:12-28

I am trying to show up the foreign key fields name instead of object id but not able to get through it. Tried using the related_name and then binding that to the serializer but still no luck,

models.py


class Employee(base_models.BaseDateModel):
    """
    DB model to store employee data
    """
   
    name = models.CharField(max_length=50)
    level = models.SmallIntegerField(choices=LEVEL_CHOICES, default=L1)

    def __str__(self):
        return f'{self.name} - {self.get_level_display()}'


class Room(base_models.BaseDateModel):
    """
    DB model to store available rooms in the building
    """
    name = models.CharField(max_length=15)

    def __str__(self):
        return f'{self.name}'


class Seat(base_models.BaseDateModel):
    """
    DB model to store available seats in a given room
    """
    room = models.ForeignKey('seating.Room', on_delete=models.CASCADE)

    def __str__(self):
        return f'{self.room} - {self.id}'


class EmployeeSeating(base_models.BaseDateModel):
    """
    DB model to store the seating details of any employee
    """
    name = models.ForeignKey('seating.Employee', on_delete=CASCADE, related_name='emp_name')
    room = models.ForeignKey('seating.ROOM', on_delete=CASCADE, related_name='emp_room')
    seat = models.ForeignKey('seating.SEAT', on_delete=CASCADE, related_name='emp_seat')

    def __str__(self):
        return f'{self.name} - {self.room} - {self.seat}'

serializers.py

class EmployeeSeatingSerializer(serializers.ModelSerializer):

    emp_name = serializers.StringRelatedField()
    emp_room = serializers.StringRelatedField()
    emp_seat = serializers.StringRelatedField()

    class Meta:
        model = EmployeeSeating
        fields = ('id', 'emp_name', 'emp_room', 'emp_seat')

views.py

def listemp_api(request, pk=None):

    """
    Method to return the list of employee in a given room
    """

    if request.method == 'GET':

        room_id = pk
        if room_id:
            employee_data = EmployeeSeating.objects.filter(room_id = room_id)
       
            serializer = EmployeeSeatingSerializer(employee_data, many=True)
            return Response(serializer.data)
        else:
            employee_data = EmployeeSeating.objects.all()
            print(employee_data)
            serializer = EmployeeSeatingSerializer(employee_data, many=True)
            return Response(serializer.data)

The result of the queryset using my view is as below

[
    {
        "id": 1
    },
    {
        "id": 2
    },
    {
        "id": 5
    }
]

but I want the room, seat and other serialized fields that I added using stringfield but not able to achieve that. Using fields = '__all__' gives me object number but misses out the additional fields I want ie. emp_room, emp_name etc

CodePudding user response:

Before moving on, I want to explain that the related_name field is used if you want to access EmployeeSeating model from Employee model. But, EmployeeSeatingSerializer is doing the opposite. Secondly, in the EmployeeSeating model foreign keys, I think you should consider renaming seating.ROOM to seating.Room (if it's not working) and the same for seating.SEAT. Make sure from django admin panel if foreign keys are linked properly, otherwise, nothing will work.

Make sure to do makemigrations and migrate after making changes in database.

First, just try this on name field of the serializer. Remove other fields.

  1. Create a model serializer for the Employee model, say EmployeeSerializer. Only give the field which you want to show, which in this case is the name field.
  2. In your EmployeeSeatingSerializer, change emp_name field to the field which is used to refer to Employee model, which is name in this case. Do the same for other fields as well.
  3. Change emp_name = serializers.StringRelatedField() to name = EmployeeSerializer(). Do the same for other fields.

Give this a try.

CodePudding user response:

Try this:

class Employee(base_models.BaseDateModel):
"""
DB model to store employee data
"""

name = models.CharField(max_length=50)
level = models.SmallIntegerField(choices=LEVEL_CHOICES, default=L1)

def __str__(self):
    return f'{self.name} - {self.get_level_display()}'


class Room(base_models.BaseDateModel):
"""
DB model to store available rooms in the building
"""
name = models.CharField(max_length=15)

def __str__(self):
    return f'{self.name}'


class Seat(base_models.BaseDateModel):
"""
DB model to store available seats in a given room
"""
room = models.ForeignKey(Room, on_delete=models.CASCADE)

def __str__(self):
    return f'{self.room} - {self.id}'


class EmployeeSeating(base_models.BaseDateModel):
"""
DB model to store the seating details of any employee
"""
name = models.ForeignKey(Employee, on_delete=CASCADE, related_name='emp_name')
room = models.ForeignKey(Room, on_delete=CASCADE, related_name='emp_room')
seat = models.ForeignKey(Seat, on_delete=CASCADE, related_name='emp_seat')

def __str__(self):
    return f'{self.name} - {self.room} - {self.seat}'
  • Related