0

I have 3 models:

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)

I want in ScheduledAction form to show, for a selected firm, the list of its related nodes. Normally I should do this by 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'
        ]

This is my 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)

But I got this error:

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

How can I fix this?

0

1 Answer 1

2

There are several things wrong with your approach

first of all: you assigned the variable 'firm' to a form field and then using that same variable to get an object from the db won't work in anyway. The variable 'firm' in Node.objects.get(firm_id=firm.id) should be a firm instance.

second: queryset=Node.objects.get(firm_id=firm.id) won't work because Model.objects.get() will return an object not a query set.

If you want to show all the nodes for a specific Firm you will need to pass the firm object (or id or other identifier) to the form by for example passing it through the get_form_kwargs() if you are using CBV and filtering by it Node.objects.filter(firm_id=firm.id)

Update: Since you are using function based views there might be a more dry way to do this, but I'm only used to working with CBV so I'll try my best

On the form we will declare a new variable called firme (we will pass this to the form in your view)

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'
    ]

now for you view:

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)

Something along these lines should get you going. It might still require some tweaking to get it to work in your project. If you still have trouble understanding please read the Django docs and or do their tutorial

Update 2: Not the prettiest solution but it works for the OP

Sign up to request clarification or add additional context in comments.

6 Comments

I'm new to Django, can you please explain your solution in detail? Thanks.
can you show me the view you use to render the form?
I tried your code and got this error: NameError: name 'firme' is not defined
Sorry: node_ids = forms.ModelMultipleChoiceField(queryset=Node.objects.filter(firm_id=firme.id), widget=forms.CheckboxSelectMultiple) should be: node_ids = forms.ModelMultipleChoiceField(queryset=Node.objects.filter(firm_id=self.firme.id), widget=forms.CheckboxSelectMultiple)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.