8

I have the following serializer

class MyModelSerializer(serializers.ModelSerializer):
    user = UserSerializer()

    def create(self, validated_data):
        print("TEST")
        MyModel, created = MyModel.objects.get_or_create(**validated_data)
        return MyModel

    class Meta:
        model = MyModel
        fields = ('pk', 'title', 'user', 'movie', 'timestamp', 'text',)

and the following viewset:

class MyModelViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

When I make an POST request to the endpoint corresponding to specified viewset, the create() method does absolutely nothing. I tried to print out in console TEST as you can see, but nothing.

Does anyone have an idea about this strange behavior?

Thanks in advace!

Edit: API call:

return axios({
  method: 'post',
  url: 'http://localhost:8000/api/mymodel/',
  data: {
     title: this.title,
     movie: this.id,
     text: this.text,
     user: this.user
}
11
  • Does it return any response? Commented Sep 26, 2018 at 17:38
  • No, with or without it, the same thing. Commented Sep 26, 2018 at 17:42
  • 1
    Ensure the data you are sending are valid (ie, the response code is 200 / 201) Commented Sep 26, 2018 at 17:47
  • When i'm sending the data, I get 400 Bad request Commented Sep 26, 2018 at 18:04
  • How do you calling the API? Pls add that code snippet also @yierstem Commented Sep 26, 2018 at 18:04

3 Answers 3

7

If you look at the implementation of POST handling in a ViewSet, you can find this:

def create(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    self.perform_create(serializer)
    headers = self.get_success_headers(serializer.data)
    return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

Your create method is called after serializer validates the data.

The error you see (user already exists) is a result of calling serializer.is_valid from the snippet above.

Therefore, it never gets to call your create. Your create would be called as part of self.perform_create() from this snippet above.

So this means that you are trying to create a user which already exists. So in your model you have unique username.

Sign up to request clarification or add additional context in comments.

7 Comments

I've been through source code, I ended up at the same conclusion, but I don't know how can I get around it, is there a way to change serializer data before it gets validated? Should I modify serializer.initial_data beforehand? Thanks
@yierstem why you want to do that ? it is good practice to validate the data. And you must do it anyway. Serializer won't let you call save without calling is_valid first. if you dont want to validate data and just call create, just dont use the serializer at all.
I don't want to exclude the data validation, I want to change the data that gets passed to the serializer. for some reason, it tries to create a user record when I just want to get the user data for a specific instance of the serialized model. I want it behave like normal foreign keys in Django, I submit the user pk, the view gets user pk from the request to get the necessary user object (not to create it), to create a mymodel record, so I can retrieve it when I send a get request to mymodel viewset.
It seems that you want to do update then? so instead of POST, do the PUT/PATCH. this will get an instance and update the fields which you want
I'm not sure why would it be a put/patch if I want to create new records for mymodel and not change anything about the user, I'm not following.
|
2

Ok. I found an alternative. Since I only wanted the username from user object, I removed user = UserSerializer() and I added user_username = serializers.ReadOnlyField(source='user.username'):

class ReviewSerializer(serializers.ModelSerializer):
    user_username = serializers.ReadOnlyField(source='user.username')

    class Meta:
        model = Review
        fields = ('pk', 'title', 'user', 'user_username', 'movie', 'timestamp', 'review_text',)

user = UserSerializer() gave me headaches, so I got around it. I will check Entushiast Martin answer as a solution since they drove me to the actual answer. Thank you.

Solved.

Comments

0

It might because you have some sort of error handling in place, because the way your def create function is written will throw an error. I tested the below code and it worked for me give it a go:

class MyModelSerializer(serializers.ModelSerializer):
    user = UserSerializer()

    class Meta:
        model = MyModel
        fields = ('pk', 'title', 'user', 'movie', 'timestamp', 'text',)

    def create(self, validated_data):
        print("TEST")
        data = validated_data
        data, created = MyModel.objects.get_or_create(**data)
        return data

Hope this helps!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.