You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django序列化器多对多关联数据传递及非空约束问题排查

Hey there! Let's walk through these two issues you're hitting when building your skill-add-to-profile API—they’re super common with Django’s serializers and database relations, so let’s break them down step by step.

1. First Issue: "This field is required" Error for the User Field

That error {"user": {"user": ["This field is required."]}} tells me your serializer is expecting a user value to be sent in the request, but either your frontend isn’t passing it… or more importantly, you shouldn’t be asking the frontend to send it at all.

Why this happens:

By default, Django’s ModelSerializer marks foreign key fields (like your user relation on UserSkill) as required. But for actions like adding a skill to the current logged-in user’s profile, you should automatically populate the user field from the request, not rely on the frontend to send a user ID (which is also a security risk).

Fix steps:

First, update your serializer to either exclude the user field or mark it as read-only, then auto-assign the logged-in user during creation:

# Serializer code
class UserSkillSerializer(serializers.ModelSerializer):
    class Meta:
        model = UserSkill
        fields = ["id", "skill_item"]  # Remove "user" from fields, or add it to read_only_fields
        read_only_fields = ["user"]

    def create(self, validated_data):
        # Auto-populate the user with the logged-in user from the request
        validated_data["user"] = self.context["request"].user
        return super().create(validated_data)

Then make sure your view passes the request to the serializer’s context (most generic views do this by default, but if not, add this):

# View code
class UserSkillCreateAPIView(generics.CreateAPIView):
    serializer_class = UserSkillSerializer

    def get_serializer_context(self):
        context = super().get_serializer_context()
        context["request"] = self.request
        return context

Now your request body only needs to include the skill_item ID, no user field required.

2. Second Issue: IntegrityError ("NOT NULL constraint failed: wantedly_webapp_userskill.skill_item_id")

Even after setting null=True on your skill_item foreign key, you’re still hitting this database constraint error. Here are the most likely culprits:

Why this happens:

  1. You didn’t apply model migrations: Changing null=True in your model doesn’t update the database automatically—Django needs a migration to alter the table’s constraint.
  2. Missing blank=True on the model field: null=True affects the database, but blank=True tells Django’s form/serializer validation that the field can be left empty. Without it, the serializer will still reject empty values.
  3. Your request isn’t sending a valid skill_item ID: If you’re trying to associate an existing skill, you need to pass a valid ID in the request body—if you skip it, the database will try to insert a NULL value, which the old constraint (before migration) blocks.

Fix steps:

First, update your UserSkill model to include both null=True and blank=True for the skill_item field (if you want to allow empty skills; if you always require a skill, skip blank=True and ensure the request sends a valid ID):

# Model code
class UserSkill(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    skill_item = models.ForeignKey(
        SkillItem, 
        on_delete=models.CASCADE, 
        null=True, 
        blank=True  # Add this line
    )

Then run the migrations to update the database:

python manage.py makemigrations
python manage.py migrate

If you want to require a skill_item (which makes sense for this feature—users are adding existing skills), update your serializer to ensure it’s pulling valid skill IDs:

class UserSkillSerializer(serializers.ModelSerializer):
    # Explicitly define the skill_item field to validate against existing skills
    skill_item = serializers.PrimaryKeyRelatedField(
        queryset=SkillItem.objects.all(),
        required=True  # Ensure this is set if you want to force a skill selection
    )

    class Meta:
        model = UserSkill
        fields = ["id", "skill_item"]
        read_only_fields = ["user"]

    def create(self, validated_data):
        validated_data["user"] = self.context["request"].user
        return super().create(validated_data)

Finally, double-check your request body is sending a valid skill_item ID, like:

{"skill_item": 1}

内容的提问来源于stack exchange,提问作者Divyanshu Jimmy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:40:48