获取Django中相关对象的列表

时间:2019-01-02 10:00:15

标签: django django-models django-forms

我有3种型号:

class Node(models.Model):
    ID = models.DecimalField(max_digits=19, decimal_places=10)
    name = models.CharField(default='node', max_length=32)
    connexion = models.CharField(max_length=255)
    # Many2one fields | Foreign keys:
    firm = models.ForeignKey('firme.Firme', on_delete=models.CASCADE, null=True, blank=True)


class ScheduledAction(models.Model):
    date = models.DateTimeField(default=datetime.now, blank=True)
    firm = models.ForeignKey('firme.Firme', on_delete=models.CASCADE, null=True, blank=True)
    node_ids = models.ManyToManyField(Node)

我希望在ScheduledAction表单中为选定的公司显示其相关节点的列表。通常我应该通过get来做到这一点:

class ScheduledActionForm(forms.ModelForm):
    date = forms.DateTimeField()
    firm = forms.ModelChoiceField(queryset=Firme.objects.all())
    node_ids = forms.ModelMultipleChoiceField(queryset=Node.objects.get(firm_id=firm.id), widget=forms.CheckboxSelectMultiple)

    class Meta:
        model = ScheduledAction
        fields = [
            'date',
            'firm',
            'node_ids'
        ]

这是我的views.py:

def planification_view(request, id):
    scheduledAction = ScheduledActionForm(request.POST or None)
    firme = get_object_or_404(Firme, id=id)
    nodes = Node.objects.all()
    if scheduledAction.is_valid():
        scheduledAction.save()
        print('formulaire enregistre')
        scheduledAction = ScheduledActionForm()
    context = {
        'firme': firme,
        'form': scheduledAction,
        'nodes': nodes
    }
    return render(request, "node/planification.html", context)

但是我得到了这个错误:

AttributeError: 'ModelChoiceField' object has no attribute 'id'

我该如何解决?

1 个答案:

答案 0 :(得分:2)

您的方法有几处错误

首先:您将变量'firm'分配给表单字段,然后使用该变量从数据库获取对象无论如何都行不通。 Node.objects.get(firm_id=firm.id)中的变量'firm'应该是一个牢固的实例。

秒:queryset=Node.objects.get(firm_id=firm.id)将不起作用,因为Model.objects.get()将返回对象而不是查询集。

如果要显示特定公司的所有节点,则需要将公司对象(或ID或其他标识符)传递给表单,例如,如果使用的是CBV,则将其通过get_form_kwargs()传递给表单并对其进行过滤Node.objects.filter(firm_id=firm.id)

更新: 由于您使用的是基于函数的视图,因此可能会有更干燥的方法,但是我只习惯使用CBV,所以我会尽力而为

在表单上,​​我们将声明一个名为firme的新变量(将其传递给您视图中的表单)

class ScheduledActionForm(forms.ModelForm):

def __init__(self, *args, **kwargs):
    self.firme = kwargs.pop('firme')
    super(ScheduledActionForm, self).__init__(*args, **kwargs)
    self.fields['node_ids'].queryset = Node.objects.filter(firm_id=self.firme.id)

date = forms.DateTimeField()
firm = forms.ModelChoiceField(queryset=Firme.objects.all()) # why do you want a list of all firms here? Or do you want a single object?
node_ids = forms.ModelMultipleChoiceField(queryset=Node.objects.none()), widget=forms.CheckboxSelectMultiple)

class Meta:
    model = ScheduledAction
    fields = [
        'date',
        'firm',
        'node_ids'
    ]

现在为您查看:

def planification_view(request, id):
firme = get_object_or_404(Firme, id=id)
nodes = Node.objects.all()
if request.method == 'POST':
    form = ScheduledActionForm(data=request.POST, firme=firme)
    if form.is_valid():
        scheduledAction = form.save()
        print('formulaire enregistre')
else:
    form = ScheduledActionForm(firme=firme)

context = {
    'firme': firme,
    'form': form,
    'nodes': nodes
}
return render(request, "node/planification.html", context)

遵循这些思路应该可以助您一臂之力。可能仍需要进行一些调整才能使其在您的项目中正常工作。如果您仍然无法理解,请阅读Django docs或阅读其教程

更新2: 不是最漂亮的解决方案,但它适用于OP