Home > Software design >  Getting NOT NULL constraint failed: locations_location.city_id in DRF
Getting NOT NULL constraint failed: locations_location.city_id in DRF

Time:11-03

When I try to create an object through DRF serailizers in my api, I get the error NOT NULL constraint failed: locations_location.city_id.

I looked at a similar here and the solution provided seems to be exactly what I had to begin with.

My models:

class City(models.Model):
    code = models.CharField(max_length=4, default="", blank=False, unique=True)
    name = models.CharField(max_length=40, default="", blank=False, unique=True)
    time_added = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f"{self.name}, ({self.code})"

    class Meta:
        verbose_name = "City"
        verbose_name_plural = "Cities"


class Location(models.Model):
    status_choice = (
        ("Available", "Available"),
        ("Unavailable", "Unavailable"),
        ("Active", "Active"),
    )
    city = models.ForeignKey(City, on_delete=models.CASCADE, related_name="locations")
    name = models.CharField(max_length=256, default="", blank=True)
    rent = models.DecimalField(max_digits=7, decimal_places=2)
    email = models.EmailField(max_length=64)
    phone = models.CharField(max_length=20, default="", blank=True)
    lon = models.DecimalField(max_digits=7, decimal_places=5, blank=True, null=True)
    lat = models.DecimalField(max_digits=7, decimal_places=5, blank=True, null=True)
    street_number = models.CharField(max_length=50, null=True)
    street_name = models.CharField(max_length=50, null=True)
    postal_code = models.CharField(max_length=50, null=True)
    status = models.CharField(max_length=50, choices=status_choice, default="Available")
    time_added = models.DateTimeField(auto_now_add=True)

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

My serailizers:


class CitySerializer(serializers.ModelSerializer):
    locations = serializers.PrimaryKeyRelatedField(many=True, read_only=True)

    class Meta:
        model = City
        fields = "__all__"

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


class LocationSerializer(serializers.ModelSerializer):
    location_events = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
    booked_days = serializers.PrimaryKeyRelatedField(many=True, read_only=True)

    class Meta:
        model = Location
        fields = "__all__"
        depth = 1

    def create(self, validated_data):
        city = serializers.PrimaryKeyRelatedField(  # noqa
            many=False, queryset=City.objects.all()
        )
        return Location.objects.create(**validated_data)

This is the fake test data passed to the api in POST request:

{
 "name": "Darmstadt Hotel", 
 "city": 1,
 "email": "[email protected]", 
 "phone": " 49(0)7219 993238", 
 "rent": 275.38, 
 "lat": 52.9427, 
 "lon": 12.1076, 
 "street_name": "Eimerstra\\u00dfe", 
 "street_number": "34", 
 "postal_code": "80843", 
 "status": "Available"
}

A city with id of 1 exists in the database and is accessible through the api.

CodePudding user response:

Firstly, you have the city field in your LocationSerializer inside the create method, that must be an error? It should be the line below booked_days = .... I'm not sure this will solve the problem however.

class LocationSerializer(serializers.ModelSerializer):
    location_events = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
    booked_days = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
    city = serializers.PrimaryKeyRelatedField(  # noqa
        many=False, queryset=City.objects.all()
    ) # Move it here

    class Meta:
        model = Location
        fields = "__all__"
        depth = 1

    def create(self, validated_data):
        return Location.objects.create(**validated_data)
  • Related