我正在尝试访问jsonfield序列化程序"assigned_facilities“中的二叉树。但我收到了以下错误:
django.db.utils.IntegrityError: null value in column "assigned_facilities_id" of relation "users_leadfacilityassign" violates not-null constraint
DETAIL: Failing row contains (78, null, null, 159).
File "/app/users/api/views.py", line 53, in perform_create
serializer.save(agent=self.request.user)
File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 205, in save
self.instance = self.create(validated_data)
File "/app/users/api/serializers.py", line 252, in create
instance.leadfacility.create(assigned_facilities_id=assigned_facilities.get('facility_id'), datetime=assigned_facilities.get('datetime'))我基本上是试图为我的json中的每个项目创建一个"LeadFacilityAssign“对象,这样我就可以为我想要添加到引线中的每个工具创建一个"LeadFacilityAssign”对象。
有人知道是什么导致了这个错误吗?我尝试了几种不同的方法,但到目前为止都没有用。
json
{
"facilities": [{
"facility_id": "1",
"datetime": "2018-12-19 09:26:03.478039"
},
{
"facility_id": "1",
"datetime": "2018-12-19 09:26:03.478039"
}
]
}serializers.py
class LeadUpdateSerializer(serializers.ModelSerializer):
is_owner = serializers.SerializerMethodField()
assigned_facilities = serializers.JSONField(required=False, allow_null=True, write_only=True)
class Meta:
model = Lead
fields = (
"id",
"first_name",
"last_name",
"is_owner",
"assigned_facilities",
)
read_only_fields = ("id", "is_owner")
def get_is_owner(self, obj):
user = self.context["request"].user
return obj.agent == user
def create(self, validated_data):
assigned_facilities = validated_data.pop("assigned_facilities")
instance = Lead.objects.create(**validated_data)
for facility in assigned_facilities:
instance.leadfacility.create(assigned_facilities_id=assigned_facilities.get('facility_id'), datetime=assigned_facilities.get("datetime"))
return instancemodels.py
class Facility(models.Model):
name = models.CharField(max_length=150, null=True, blank=False)
def __str__(self):
return self.name
class Lead(models.Model):
first_name = models.CharField(max_length=40, null=True, blank=True)
last_name = models.CharField(max_length=40, null=True, blank=True)
def __str__(self):
return f"{self.first_name} {self.last_name}"
class LeadFacilityAssign(models.Model):
assigned_facilities = models.ForeignKey(Facility, on_delete=models.CASCADE, related_name='leadfacility')
lead = models.ForeignKey(Lead, on_delete=models.CASCADE, related_name='leadfacility')
datetime = models.DateTimeField()views.py
class LeadCreateView(CreateAPIView):
permission_classes = [IsAuthenticated, IsLeadOwner]
serializer_class = LeadUpdateSerializer
def perform_create(self, serializer):
serializer.save(agent=self.request.user)
class LeadUpdateView(UpdateAPIView):
permission_classes = [IsAuthenticated, IsLeadOwner]
serializer_class = LeadUpdateSerializer
def get_queryset(self):
return Lead.objects.all()发布于 2022-11-06 17:59:43
你有三张桌子:
key
表,其中lead_facility_id是不可空的,但是它的两个外键(lead_id和facility_id)是可空的。并且将这些可空值赋值给非空字段.
也许您正在尝试这样做:lead_falility_id (table: LeadFacility talbe) = facility_id (table: facility_id)
但您做的错误是:lead_falility_id (表: LeadFacility talbe) = facility_id (表:LeadFacility)。
因此,您要为非空字段执行: lead_facility_id = null。
发布于 2022-11-08 17:11:44
您的JSON与序列化程序不匹配。序列化器字段与模型字段不匹配。您的视图与您的模型或序列化程序不匹配。
所以,让我们从头开始。
如果我正确理解,您希望在创建或更新LeadFacilityAssign对象的同时创建一个对象。有一些方法可以解决这个问题,比如在铅创建请求之后立即使用post_save信号,但是让我们按照您的意思.
从您的领头串行化器来看,这“很好”:
class LeadUpdateSerializer(serializers.ModelSerializer):
is_owner = serializers.SerializerMethodField()
assigned_facilities = serializers.JSONField(required=False, allow_null=True, write_only=True)
class Meta:
model = Lead
fields = (
"id",
"first_name",
"last_name",
"is_owner",
"assigned_facilities",
)
read_only_fields = ("id", "is_owner")但这一点:
def get_is_owner(self, obj):
user = self.context["request"].user
return obj.agent == user在最后一行中有一个比较语句(==),这意味着它可以返回一个True或False值(?),而且您没有在其他任何地方使用"agent“字段,也没有在序列化程序中声明,甚至在模型中的字段中声明。只需去掉该函数或在您的LeadFacilityAssign模型中添加“代理”字段(假设您将为该关系分配一个领导、一个设施和一个代理)。
我猜您期待从您的JSON电话是“设施”的信息。从上面声明的字段中,我猜您应该期待一个"assigned_facilities“字段,它不会显示在您的JSON数据中,但是让我们假设您的API将接收一个"assigned_facilities”字段,而不是一个与单个引线相关的许多设施的“assigned_facilities”子块。
我还没有测试下面的代码,但是根据REST文档,您现在必须在序列化程序中定义两个方法,一个用于CREATE,另一个用于UPDATE。
创建:
def create(self, validated_data):
lead = Lead.objects.create(first_name=validated_data['first_name'], last_name=validated_data['last_name'] #Here you will create the Lead object that you will reference later in your LeadFacilityAssign relationship with the dictionary information from the received data, so let's save it:
lead.save()
#Now we need to create all facilities relationships to this Lead:
facilities = validated_data['assigned_facilities'] #This will create a "facilities" sub-dict from your received data with a facility_id and a datetime field in key-value pair.
for item in facilities:
facility = Facility.objects.get(id=item['facility_id']) #Get a single facility object for each ID in your JSON. If this fails, try converting it to int().
datetime = item['datetime'] #Again, if it fails because it's taken as string, try converting it to datetime object.
entry = LeadFacilityAssign.objects.create(assigned_facilities=facility, lead=lead, datetime=datetime) #Create the entry.
entry.save() #Save the entry
return #Exit your functionUpdate方法应该看起来大致相同。
在视图中,如果不使用"agent“字段,只需为安全起见解析用户,或者如果希望将其作为所有者包含在模型中,则只需稍后使用。
class LeadCreateView(CreateAPIView):
permission_classes = [IsAuthenticated, IsLeadOwner]
serializer_class = LeadUpdateSerializer
def perform_create(self, serializer):
serializer.save(user=self.request.user)发布于 2022-11-02 12:38:49
您的JSON示例包含“功用”,但是您的序列化程序有assigned_facilities = serializers.JSONField(required=False, allow_null=True, write_only=True)。
class LeadUpdateSerializer(serializers.ModelSerializer):
is_owner = serializers.SerializerMethodField()
facilities = serializers.JSONField(required=False, allow_null=True, write_only=True)
class Meta:
model = Lead
fields = (
"id",
"first_name",
"last_name",
"PrimaryAddress",
"City",
"PostalCode",
"RegionOrState",
"pc_email",
"Cell",
"secphone",
"client_cell",
"client_secphone",
"birthday",
"curr_client_address",
"curr_client_city",
"curr_client_zip",
"ideal_address",
"ideal_city",
"ideal_zip",
"ideal_state",
"budget",
"client_email",
"client_first_name",
"client_last_name",
"lead_status",
"created_at",
"agent",
"is_owner",
"relationship",
"marital_status",
"gender",
"pets",
"facilities",
)
read_only_fields = ("id", "created_at", "agent", "is_owner")
def get_is_owner(self, obj):
user = self.context["request"].user
return obj.agent == user
def create(self, validated_data):
facilities = validated_data.pop("facilities", None)
instance = Lead.objects.create(**validated_data)
for facilities in assigned_facilities:
LeadFacilityAssign.objects.create(assigned_facilities_id=assigned_facilities.get("facility_id"), datetime=assigned_facilities.get("datetime"), lead=instance)
return instance此外,您还为设施添加了必需的False,因此如果没有所请求的工具,则可能会导致validated.pop(“功用”)错误。您应该向pop方法中添加另一个参数。Validated.pop(“设施”,无)
https://stackoverflow.com/questions/74287146
复制相似问题