1

Using Django and its REST_Framework, I'm trying to add an object to my POSTGRES-11 database, whose model (Team) is related to another model (Country) by a ForeignKey relation. The JSON I send with the post request looks like this, where the number provided for country is supposed to be its id.

name:"test"
is_onsite:true
status:"PAID"
institution:"testU"
country:2

But then Django returns the following error:

IntegrityError at /api/register/team/
null value in column "country_id" violates not-null constraint
DETAIL:  Failing row contains (28, , f, PENDING, , null).

I've tried sending the same json with 'country' replaced with 'country_id', but I've been faced with the same error.

I've already tried the solution given Here, but then Django returns this JSON instead of adding the object:

{
    "country": [
        "This field is required."
    ]
}

models.py:

class Country(models.Model):
    name = models.CharField(max_length=255)
    flag = models.ImageField()
    class Meta:
        verbose_name_plural = 'Countries'

    def __str__(self):
        return self.name

class Team(models.Model):
    name = models.CharField(max_length=255, default="", blank=True)
    is_onsite = models.BooleanField(default=False)
    status = models.CharField(max_length=50, choices=TEAM_STATUS_CHOICES, default='PENDING')
    institution = models.CharField(max_length=255, default="")
    country = models.ForeignKey(Country, on_delete=models.CASCADE, default="", blank=True)

    def __str__(self):
        return self.name

serializers.py:

class CountrySerializer(serializers.ModelSerializer):
    class Meta:
        model = Country 
        fields = '__all__'

class TeamSerializer(serializers.ModelSerializer):
    class Meta:
        model = Team 
        fields = ['name', 'is_onsite', 'status', 'institution', 'country']

views.py:

class TeamCreateView(CreateAPIView):
    queryset = Team.objects.all()
    serializer_class = TeamSerializer

I should note that Django works perfectly fine when I try to add it via the HTML form provided at '/api/register/team', but not when it receives a JSON via outer post requests.

I've been stuck at this for days, so your help would be really appreciated.


@dirkgroten I forgot to mention, I did the former thing by adding the following snippet to my TeamSerializer and tried sending the 'countryId' (and not 'country_id') in my POST request, but it still didn't work. This snippet:

countryId = serializers.PrimaryKeyRelatedField(queryset=Country.objects.all())
    def create(self, validated_data):
        print(validated_data)
        return Team.objects.create(
            name=validated_data['name'],
            is_onsite=validated_data['is_onsite'],
            status=validated_data['status'],
            institution=validated_data['institution'],
            country=validated_data['countryId']
        )

As for the latter case, I added the country = CountrySerializer(many=False) line to my code, and sent a JSON like the following, but I still got the "This field is required" JSON. My POST JSON:

name:"test"
is_onsite:true
status:"PAID"
institution:"testU"
country:{"name": "Test"}

Even though the country 'Test' exists in my database, it still fails to add the team.

  • You sure there is a country with id `2` in your database? Also remove `default` from the model, if default is provided drf will not check for not null. – Vaibhav Vishal Aug 30 '19 at 14:15
  • Yep, pretty sure. "[ { "id": 2, "name": "Test", "flag": "http://localhost:8000/api/photo.jpg" } ]" – Erfan Abedi Aug 30 '19 at 14:46

1 Answers1

0

First of all, you should remove default="", blank=True on your country field for the Team model. FK fields should never have empty string as default. If you want the possibly for your country to be "unset", use blank=True, null=True. But if every Team always must have a country, then don't add anything.

You can do two things:

  • Either you use 'country_id' in the fields of your TeamSerializer and pass the field as country_id in your JSON. You need to do both, passing country_id in your JSON but country as field in the serializer won't work.

    fields = ['name', 'is_onsite', 'status', 'institution', 'country_id']
    
  • Or you add country = CountrySerializer(many=False) to your TeamSerializer but then in your json, you need to nest a country inside your request and it will create the country object:

    {'name': 'test',
     ...
     'country': {
         'name': 'Angola'
      }
    }
    
dirkgroten
  • 20,112
  • 2
  • 29
  • 42
  • but `countryId` doesn't match `country_id` from your POST. And "latter" means my second option, I don't see how your code relates to my second option. My first option is just to set `fields = ['country_id', ...]` – dirkgroten Aug 30 '19 at 14:38
  • I know it doesn't match, it was for a previous version where I named it 'countryId' and sent the request with a parameter named 'countryId', which gave the exact same "This field is required" response. – Erfan Abedi Aug 30 '19 at 14:46