2

when I try to create a new Post by posting the following JSON:

{
    "text": "test",
     "location": 1
}

I get the following error:

NOT NULL constraint failed: grapevineapp_post.location_id

models.py:

class Location(models.Model):
    name = models.CharField(max_length=80)
    created = models.DateTimeField(auto_now_add=True)
    def __str__(self):
        return self.name

class Post(models.Model):
    text = models.CharField(max_length=512)
    owner = models.ForeignKey('auth.User', related_name='posts', on_delete=models.CASCADE)
    location = models.ForeignKey(Location, related_name='posts', on_delete=models.CASCADE)
    created = models.DateTimeField(auto_now_add=True)
    def __str__(self):
        return self.text

views.py:

class PostList(generics.ListCreateAPIView):
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

class PostDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
    queryset = Post.objects.all()
    serializer_class = PostSerializer

Serializers.py

class PostSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    text = serializers.CharField(required=False, allow_blank=True, max_length=512)
    owner = serializers.ReadOnlyField(source='owner.username')
    location = serializers.PrimaryKeyRelatedField(many=False, read_only=True)

    def create(self, validated_data):
        return Post.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.text = validated_data.get('text', instance.text)
        instance.location = validated_data.get('location', instance.location)
        instance.save()
        return instance
class UserSerializer(serializers.ModelSerializer):
    posts = serializers.PrimaryKeyRelatedField(many=True, queryset=Post.objects.all())

    class Meta:
        model = User
        fields = ('id', 'username', 'posts')

DB has already been cleared. Locations have been created by using the admin interface. I know that the issue is something trivial, but I just can't get it to work.

2
  • 1
    Your location is read_only=True? Commented Dec 8, 2018 at 21:21
  • If I set it to False I get: AssertionError: Relational field must provide a queryset argument, override get_queryset, or set read_only=True. Commented Dec 8, 2018 at 21:54

1 Answer 1

8

To elaborate on what Willem Van Onsem said, you have your PostSerializer.location field set as read-only. The json data that you provided for it will be ignored (documentation), i.e. it won't be included in your validated_data.

Then when you call Post.objects.create(**validated_data) in your create method it tries to create an instance of Post without the location argument and you get your error.

EDIT: After your comment above about queryset.

You need to provide a queryset for it to validate against (documentation). In your case you want

location = serializers.PrimaryKeyRelatedField(
    many=False,
    queryset=Location.objects.all()
)
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you very much! Works as expected. I'm still learning and now I can go on!
I have a similar issue presently.Can you help me.look into it please stackoverflow.com/questions/62655168/…
Wow this answer took me 3 days to find! My QueryDicts kept failing on a foreign key = Null value. This works perfectly. Thanks!

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.