首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >"assigned_facilities_id“列中的空值

"assigned_facilities_id“列中的空值
EN

Stack Overflow用户
提问于 2022-11-02 09:42:06
回答 4查看 180关注 0票数 0

我正在尝试访问jsonfield序列化程序"assigned_facilities“中的二叉树。但我收到了以下错误:

代码语言:javascript
复制
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

代码语言:javascript
复制
{
    "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

代码语言:javascript
复制
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 instance

models.py

代码语言:javascript
复制
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

代码语言:javascript
复制
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()
EN

回答 4

Stack Overflow用户

发布于 2022-11-06 17:59:43

你有三张桌子:

key

  • LeadFacility Lead表,其中lead_id是不可空的,因为它是主键

  • 设施表,其中facility_id是不可空的,因为它是主

表,其中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。

票数 3
EN

Stack Overflow用户

发布于 2022-11-08 17:11:44

您的JSON与序列化程序不匹配。序列化器字段与模型字段不匹配。您的视图与您的模型或序列化程序不匹配。

所以,让我们从头开始。

如果我正确理解,您希望在创建或更新LeadFacilityAssign对象的同时创建一个对象。有一些方法可以解决这个问题,比如在铅创建请求之后立即使用post_save信号,但是让我们按照您的意思.

从您的领头串行化器来看,这“很好”:

代码语言:javascript
复制
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")

但这一点:

代码语言:javascript
复制
    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。

创建:

代码语言:javascript
复制
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 function

Update方法应该看起来大致相同。

在视图中,如果不使用"agent“字段,只需为安全起见解析用户,或者如果希望将其作为所有者包含在模型中,则只需稍后使用。

代码语言:javascript
复制
class LeadCreateView(CreateAPIView):
    permission_classes = [IsAuthenticated, IsLeadOwner]
    serializer_class = LeadUpdateSerializer

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)
票数 1
EN

Stack Overflow用户

发布于 2022-11-02 12:38:49

您的JSON示例包含“功用”,但是您的序列化程序有assigned_facilities = serializers.JSONField(required=False, allow_null=True, write_only=True)

代码语言:javascript
复制
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(“设施”,无)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74287146

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档