Django Rest Framework: foreign key field is required in viewset or serializer

1.5k Views Asked by At

I am very new to Django Rest Framework (DRF). I have read that viewsets are very good, because it reduces the amount of code, but I found it more complex.

Description: Imagine that I want to implement a phonebook API, in which we have some users and each of them has it own contacts and each contact can have several phone number. So, I have three models here.

  1. User (Default Django model)
  2. Contact
class Contact(models.Model):
    owner = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='contacts'
    )
    name = models.CharField(
        max_length=70
    )
    description = models.TextField()

  1. Phone Number
class Phones(models.Model):
    person = models.ForeignKey(
        Contact,
        related_name="phones",
        on_delete=models.CASCADE,
    )

    phone_no = models.CharField(
        max_length=11,
    )

Problem Definition What I want is to create new contact with the current request.user. So I should have my contact.serializers like the following:

class ContactSerializer(serializers.ModelSerializer):
    owner = serializers.SlugRelatedField(queryset=User.objects.all(), slug_field='user')


    class Meta:
        model = Contact
        fields = ['id', 'owner', 'name', 'description']
        read_only_fields = ['owner']

and my views is like:


class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer
    permission_classes = [IsCreator]

    def get_permissions(self):
        if self.request.method == "GET":
            self.permission_classes = [IsCreator, permissions.IsAdminUser,]

        if self.request.method == "POST":
            self.permission_classes = [permissions.IsAuthenticated,]

        if self.request.method == "PUT":
            self.permission_classes = [IsCreator]

        if self.request.method == "DELETE":
            self.permission_classes = []

        return super(ContactViewSet, self).get_permissions()

Error Whenever I want to post a new contact using postman, I have pass the name, description and owner and it should automatically detects the owner from the request but it doesn't and I have got the following error:

postman screenshot

PS: If it is necessary to checkout the project here is my project link.

What should I do?

2

There are 2 best solutions below

0
On

The problem was solved after applying the below changes.

apps.contacts.views.py:

add the following method to the body of the class

def perform_create(self, serializer):
    return serializer.save(owner = self.request.user)

apps.contacts.serializers.py:

class ContactSerializer(serializers.ModelSerializer):
    class Meta:
        model = Contact
        fields = ['id', 'name', 'description', 'owner']

PS I am also looking for more answers, in this case add your answer.

2
On

One thing you could do is add currentuserdefault. like this

class ContactSerializer(serializers.ModelSerializer):
    owner = serializers.HiddenField(default=serializers.CurrentUserDefault())

    class Meta:
        model = Contact
        fields = ['id', 'owner', 'name', 'description']

And in your view code remember to pass request in context. Like this

class ContactViewSet(viewsets.ModelViewSet):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer
    permission_classes = [IsCreator]

    def get_serializer_context(self):
        context = super().get_serializer_context()
        context.update({"request": self.request})
        return context