首页 > 解决方案 > Django Rest Framework - 获取相关的 FK 对象以在模板中使用;POST现在不起作用?

问题描述

我已经建立了一个表格并使用了 Vue 前端和 DRF 后端。它是一种用于添加(创建)新模型的表单 - 并具有相关模型的下拉列表,这些模型是正在创建的模型的 FK。

我需要访问所选 FK 项目的属性。

我的序列化程序如下所示:

class SubdomainSerializer(serializers.ModelSerializer):
    class Meta:
        model = Subdomain
        fields = [
            "id",
            "domain",
            "short_description",
            "long_description",
            "character_code",
        ]

    # def get_absolute_url(self, obj):
    #     return obj.get_absolute_url()


class EvidenceSerializer(serializers.ModelSerializer):
    created_by = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )
    updated_by = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )
    absolute_url = serializers.SerializerMethodField()
    created_by_name = serializers.SerializerMethodField()
    updated_by_name = serializers.SerializerMethodField()

    class Meta:
        model = Evidence
        fields = "__all__"

该表单用于创建一个新的“证据”项,“子域”是表单上包含所有相关子域的下拉菜单。

模型如下所示:

class Subdomain(CreateUpdateMixin):
    domain = models.ForeignKey(Domain, on_delete=models.PROTECT)
    short_description = models.CharField(max_length=100)
    long_description = models.CharField(max_length=250)
    character_code = models.CharField(max_length=5)

class Evidence(CreateUpdateMixin, CreateUpdateUserMixin, SoftDeletionModel):
    subdomain = models.ForeignKey(Subdomain, on_delete=models.PROTECT)
    evaluation = models.ForeignKey(
        Evaluation, related_name="evidences", on_delete=models.PROTECT
    )
    published = models.BooleanField(default=False)
    comments = models.CharField(max_length=500)

在我的表单中,我只想在用户从下拉列表中选择它时包含short_description每个subdomain- 我可能也想使用long_description

这是我呈现下拉列表的表单中的位:

                        <div class="form-group col-sm-4">
                            <label class="" for="subdomain">Subdomain</label>
                            <select name="subdomain" id="subdomain" class="form-control" v-model="element.subdomain">
                                <option v-for="choice in subdomains" :value="choice.id" >{{ choice.character_code }}</option>
                            </select>
                        </div>
                        <div class="small" v-if="element.subdomain">
                            <!-- THIS IS WHERE I WOULD LIKE TO DISPLAY THE SHORT DESCRIPTION FOR THE CHOICE IN THE DROPDOWN -->
                            {{ choice.short_description }}
                        </div>

当我发布时,表单数据看起来像这样:

evaluation: 2037
subdomain: 448
comments: Test comments to add to the subdomain
published: true
csrfmiddlewaretoken: 382796ryfuasiodfgyhakljyht37yaisdfaslk3r

我尝试过的东西-其中一些用于显示目的,但似乎破坏了表单/POST:

subdomain = SubdomainSerializer(read_only=True)

使用下拉列表上方的这两种方法都无法识别subdomain_id被选中的对象,并且最终都会在幕后引发此错误:

Cannot insert the value NULL into column 'subdomain_id', table 'local_app.dbo.myapp_evidence'; column does not allow nulls. INSERT fails.

任何关于如何进行的建议都会很棒。

TLDR;需要能够使用 DRF 访问 FK 关系上的属性以获取下拉列表,并能够在表单中提交该项目。

标签: javascriptdjangovue.jsdjango-rest-framework

解决方案


感谢@bdbd 为我指明了正确的方向。

对于任何好奇的人,我使用这些链接解决了它 - 结果我需要稍微更改我的序列化程序:

class SubdomainSerializer(serializers.ModelSerializer):
    class Meta:
        model = Subdomain
        fields = [
            "id",
            "domain",
            "short_description",
            "long_description",
            "character_code",
        ]


class EvidenceSerializer(serializers.ModelSerializer):
    created_by = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )
    updated_by = serializers.HiddenField(
        default=serializers.CurrentUserDefault()
    )
    absolute_url = serializers.SerializerMethodField()
    created_by_name = serializers.SerializerMethodField()
    updated_by_name = serializers.SerializerMethodField()
    # add the 'subdomain' as read only - but with all the attributes
    subdomain = SubdomainSerializer(read_only=True)
    # add the 'subdomain_id' as a PrimaryKeyRelatedField with the source being the subdomain
    subdomain_id = serializers.PrimaryKeyRelatedField(
        queryset=Subdomain.objects.all(), source="subdomain"
    )

    class Meta:
        model = Evidence
        fields = "__all__"

然后我稍微更新了 HTML:

                <div class="form-group col-sm-4">
                    <label class="" for="subdomain_id">Subdomain</label>
                    <select name="subdomain_id" id="subdomain" class="form-control" v-model="element.subdomain">
                        <option v-for="choice in subdomains" :value="choice" >{{ choice.character_code }}</option>
                    </select>
                </div>
                <div class="small" v-if="element.subdomain_id">
                    {{ element.subdomain.short_description }}
                </div>

然后在 ajax 调用中,我只需subdomain_idsubdomain.id

        data: {
            evaluation : evaluationId,
            subdomain_id : vm.element.subdomain.id,
            comments : vm.element.comments,
            published: vm.element.published,
            csrfmiddlewaretoken: vm.sharedStore.state.csrftoken,
        },

推荐阅读