基于用户选择选择自动填充外键字段

时间:2017-09-05 13:52:34

标签: python django python-3.x

我有两种模式:

class ActionForm(ModelForm):
    class Meta:
        model = Action
        fields = '__all__'
    def __init__(self, *args, **kwargs):
        super(AlertForm, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
        if instance and instance.pk:
            disabledFields = ['entity',
                              'entityDescription']
            for field in disabledFields:
                self.fields[field].disabled=True
        else:
            self.fields['entity'].blank=True
            self.fields['entityDescription'] = ModelChoiceField(queryset=Entity.objects.all())

ActionFormSet = modelformset_factory(Action, extra=1, exclude=(), form=ActionForm)

class ActionFormsetHelper(FormHelper):
    def __init__(self, *args, **kwargs):
        super(ActionFormsetHelper, self).__init__(*args, **kwargs)
        self.form_method = 'post'
        self.template = 'bootstrap/table_inline_formset.html'
        self.add_input(Submit("submit", "Submit"))
        self.layout = Layout(
            Field('entity', css_class="input", type="hidden"),
            Field('entityDescription', css_class="input"),
            Field('action', css_class="input")
        )

我有一个模型表单和模型formset,还有一个表单帮助器,用于表单:

def actions(request):
    newActions = Action.objects.filter(action='')
    formset = ActionFormSet(request.POST or None, queryset=newActions)
    helper = ActionFormsetHelper()
    context = {'formset':formset, 'helper':helper}
    if request.method == 'POST':
        for form in formset:
            if form.is_valid():
                if form.has_changed():
                    obj = form.save(commit=False)
                    obj.entity = form.cleaned_data['entityDescription']
                    obj.save()
        return HttpResponseRedirect('/actions')
    return render(request, 'actions/actions.html', context)

我有一个观点:

entityDescription    action
Jim Halpert          [Blank Cell]
Michael Scott        [Blank Cell]
[Blank Cell]         [Blank Cell]

所以我呈现的页面看起来像这样:

entity

entityDescription被隐藏,Entityentity模型驱动。当用户选择entityDescription时,我希望ActionentityDescription模型中自动填充。从逻辑上讲,这意味着Entity需要返回entity模型,找到相应的entity主键,并将该值放在Action外键中{ {1}}模型。

我对此的尝试是在视野中。我保存了表单而没有提交,试图为entity分配一些值,然后尝试提交表单。此尝试会导致此错误:

Cannot assign "<Some Entity Description>": "Action.entity" must be a "Entity" instance.

这是有道理的,因为我尝试将entityDescription分配给entity,而不是分配entity。我接下来试图以一种hacky方式获取entity,因为它是entityDescription中的第一个单词:

obj.entity = form.cleaned_data['entityDescription'].split(' ', 1)[0]

这导致了同样的错误,尽管entity在错误中看起来是正确的。现有模型formset成员和新成员都会发生这些错误。

当用户从Entity模型中选择值时,如何检索Entity模型的主键?那么如何将该主键分配给Action模型中相应的外键字段?

修改:

enter image description here

因此Jim和Michael是Action中的现有记录。用户可以为他们分配动作。空行是一个新动作。用户可以从entityDescription模型中选择Entityentity是一个隐藏的字段(即Jim为1,Michael为2)。

当用户为新行选择entityDescription(即用户选择Jim)时,应在保存表单之前将主键(1)输入隐藏的entity字段。

另一个编辑:

经过进一步调查,如果我在提供的答案中实施解决方案,问题出现在:

obj.entity = Entity.objects.get(pk=pk)

这实际上是返回entityDescription模型的Entity(即由def __str__定义的内容)而不是主键。我试图将其改为......

obj.entity = Entity.objects.get(pk=pk).entity

...但是这会导致主键作为字符串而不是对象返回。因此,它无法保存到数据库中。我该如何将这个字符串变成一个对象?换句话说,如何使用查询语言从Django模型的一个对象中的一个字段中获取一个值?

1 个答案:

答案 0 :(得分:0)

您的obj.entity应该指定为对象,并且form.cleaned_data不会作为对象返回。

尝试打印输出内容,如果我按照您的情况,将其从所选实体中设为id/pk

print(form.cleaned_data['entityDescription'])
# eg: 16

然后:

obj.entity = form.cleaned_data['entityDescription']

应该是;

pk = form.cleaned_data['entityDescription']
obj.entity = get_object_or_404(Entity, pk=pk)
#            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this is object instance

# OR

pk = form.cleaned_data['entityDescription']
obj.entity = Entity.objects.get(pk=pk)
#            ^^^^^^^^^^^^^^^^^^^^^^^^^ this is object instance