在Django+DRF中使用perform_create创建含ForeignKey的对象
如何在Django REST Framework中用perform_create创建带ForeignKey的对象
先给你提个小细节问题:你写的Supervisor模型里,__str__方法用了self.supervisor,但模型里定义的外键字段是emp_id,这会导致报错的,得改成self.emp_id(如果Employee模型有name之类的字段,改成self.emp_id.name会更友好)。
回到你的核心问题,下面一步步教你用perform_create来处理带外键的对象创建:
第一步:先把序列化器配置好
首先得确保你的SupervisorSerializer正确包含了外键字段emp_id,不然序列化器没法处理这个字段的赋值。示例如下:
from rest_framework import serializers from .models import Supervisor class SupervisorSerializer(serializers.ModelSerializer): class Meta: model = Supervisor fields = ['id', 'emp_id'] # 必须包含emp_id这个外键字段
第二步:在APIView里实现perform_create
perform_create是DRF提供的钩子方法,能让你在保存对象前自定义逻辑,完美适配外键关联的场景,分两种常见情况:
情况1:前端传递外键ID(比如用户选择某个员工作为主管)
如果前端会在POST请求的body里传emp_id(对应的Employee的ID),你可以直接让序列化器处理,也可以在perform_create里加额外校验:
from rest_framework import mixins, generics from .models import Supervisor from .serializers import SupervisorSerializer class SupervisorAPIView(mixins.CreateModelMixin, generics.ListAPIView): """ 添加主管 """ lookup_field = 'pk' serializer_class = SupervisorSerializer queryset = Supervisor.objects.all() # 别忘了加这个,ListAPIView必须要有queryset def perform_create(self, serializer): # 这里可以加自定义逻辑,比如校验emp_id对应的Employee是否存在 # 比如: # from .models import Employee # emp_id = self.request.data.get('emp_id') # if not Employee.objects.filter(id=emp_id).exists(): # raise serializers.ValidationError("对应的员工不存在") # 没有额外逻辑的话直接保存就行,序列化器会自动处理外键关联 serializer.save() # 必须加这个post方法,因为CreateModelMixin需要它来处理创建请求 def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs)
情况2:自动关联当前登录用户(无需前端传值)
如果不需要前端选员工,而是要把当前登录的用户关联到Supervisor的外键(比如当前登录的员工就是要创建的主管),可以这么写:
def perform_create(self, serializer): # 假设你的User模型和Employee模型是一对一关联的,比如request.user.employee就是对应的Employee对象 # 这里要根据你实际的用户关联逻辑调整 current_employee = self.request.user.employee # 直接把外键对象传给save方法 serializer.save(emp_id=current_employee)
第三步:测试一下
如果是情况1,前端发送的POST请求body应该是这样的JSON:
{ "emp_id": 1 // 这里的1是你数据库里已存在的Employee的ID }
最后再补个模型的小修复
你的Supervisor模型的外键最好加上on_delete参数(Django3.0+是必填的),比如:
class Supervisor(models.Model): emp_id = models.ForeignKey(Employee, null=True, blank=True, on_delete=models.SET_NULL) def __str__(self): # 如果Employee有name字段,改成下面这样更直观 return f"主管: {self.emp_id.name}" if self.emp_id else "未关联员工的主管"
这样操作下来,就能顺利创建带ForeignKey的Supervisor对象啦。
内容的提问来源于stack exchange,提问作者Philip Mutua
相关产品推荐
相关产品推荐

