Search code examples
djangovariablesdjango-forms

Error while passing Variable from View to Form in Django


I try to send a variable form View to Form in Django. I find a solution and it's working but the problem is that I have to call the fonction form = DonneeForm(variable=variable) but it seems to just send me the entire HTML code. So I would like to find a way for the DonneeForm() to behave as DonneeForm which work but doesn't allow me to send a variable.

Thanks

Form.py

class DonneeForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        self.boitier = kwargs.pop("boitier", 1)  # client is the parameter passed from views.py
        super().__init__(*args, **kwargs)
        boitier = get_object_or_404(Boitier, pk=int(self.boitier))
        self.fields['connexion_donnee'].queryset = boitier.donnee

    class Meta:
        model = Donnee
        fields = ['utilise', 'connexion_donnee', 'nom', 'type_donnee', 'valeur_min', 'valeur_max', 'tolerance', 'afficher_valeur', 'inverse']
        labels = {
        }
        widgets = {
            'type_donnee': forms.Select(attrs={"readonly": "True"})
        }

View.py

type_capteur = get_object_or_404(TypeCapteur, pk=pk)
    capteur = get_object_or_404(Capteur, pk=article)
    type_capteur_donnees = type_capteur.donnee.all().count()
    print(DonneeForm(boitier=boitier.pk))
    form = DonneeForm(boitier=boitier.pk)
    donnee_form_set = formset_factory(form, extra=type_capteur_donnees, max_num=type_capteur_donnees,
                                      absolute_max=type_capteur_donnees)
    formset_donnee = donnee_form_set
    if request.method == 'POST':
        formset = donnee_form_set(request.POST, request.FILES)
        if formset.is_valid():
            for form in formset:
                if form.cleaned_data:
                    donnee = form.save(commit=False)
                    donnee.capteur = capteur
                    donnee.save()
                capteur.save()
            return redirect("smart_workshop_app:configuration_capteurs")
    else:
        initial = []
        for type_donnee in type_capteur.donnee.all():
            initial.append({'type_donnee': type_donnee, 'nom': type_donnee.nom})
        formset = formset_donnee(initial=initial)
        print(formset_donnee)
    context = {"formset": formset, "instance_id": pk, "instance_article": article}
    return render(request, 'smart_workshop_app/ajouter_donnees_capteur.html', context)

Error:

<tr>
    <th><label for="id_utilise">Donnée utilisée :</label></th>
    <td>
      
      <input type="checkbox" name="utilise" id="id_utilise">
      
      
    </td>
  </tr>

  <tr>
    <th><label for="id_connexion_donnee">Connexion donnee :</label></th>
    <td>
      
      <select name="connexion_donnee" id="id_connexion_donnee">
  <option value="" selected>---------</option>

  <option value="1">Capt_Distance_Dist_0</option>
 
      [...]
    </td>
  </tr>
Internal Server Error: /fr/ajouter_donnees_capteur/4/28
Traceback (most recent call last):
  File "C:\Users\regac\anaconda3\envs\smart_workshop\lib\site-packages\asgiref\sync.py", line 472, in thread_handler
    raise exc_info[1]
  File "C:\Users\regac\anaconda3\envs\smart_workshop\lib\site-packages\django\core\handlers\exception.py", line 38, in inner
    response = await get_response(request)
  File "C:\Users\regac\anaconda3\envs\smart_workshop\lib\site-packages\django\core\handlers\base.py", line 233, in _get_response_async
    response = await wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\regac\anaconda3\envs\smart_workshop\lib\site-packages\asgiref\sync.py", line 435, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "C:\Users\regac\anaconda3\envs\smart_workshop\lib\asyncio\tasks.py", line 408, in wait_for
    return await fut
  File "C:\Users\regac\anaconda3\envs\smart_workshop\lib\site-packages\asgiref\current_thread_executor.py", line 22, in run
    result = self.fn(*self.args, **self.kwargs)
  File "C:\Users\regac\anaconda3\envs\smart_workshop\lib\site-packages\asgiref\sync.py", line 476, in thread_handler
    return func(*args, **kwargs)
  File "C:\Users\regac\anaconda3\envs\smart_workshop\lib\site-packages\django\contrib\auth\decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "C:\Users\regac\anaconda3\envs\smart_workshop\lib\site-packages\django\utils\decorators.py", line 130, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "C:\Users\regac\PycharmProjects\djangoProject\smart_workshop\smart_workshop_app\views.py", line 268, in ajouter_donnees_capteur
    donnee_form_set = formset_factory(form, extra=type_capteur_donnees, max_num=type_capteur_donnees,
  File "C:\Users\regac\anaconda3\envs\smart_workshop\lib\site-packages\django\forms\formsets.py", line 495, in formset_factory
    return type(form.__name__ + 'FormSet', (formset,), attrs)
AttributeError: 'DonneeForm' object has no attribute '__name__'
HTTP GET /fr/ajouter_donnees_capteur/4/28?boitier=2 500 [0.26, 127.0.0.1:51847]
C:\Users\regac\PycharmProjects\djangoProject\smart_workshop\smart_workshop_app\views.py changed, reloading.

Solution

  • The issue is that you need to pass the form class to the formset_factory and pass your custom kwargs (in this case the boitier.pk) via the formset to the form.

    For that you can use the form_kwargs argument of the formset. Documented here in Django

        type_capteur = get_object_or_404(TypeCapteur, pk=pk)
        capteur = get_object_or_404(Capteur, pk=article)
        type_capteur_donnees = type_capteur.donnee.all().count()
        form = DonneeForm
        donnee_form_set = formset_factory(form, extra=type_capteur_donnees, max_num=type_capteur_donnees,
                                          absolute_max=type_capteur_donnees)
        formset_donnee = donnee_form_set
        if request.method == 'POST':
            # HERE WE PASS THE FORM_KWARGS
            formset = donnee_form_set(request.POST, request.FILES, form_kwargs={'boitier': boitier.pk})
            if formset.is_valid():
                for form in formset:
                    if form.cleaned_data:
                        donnee = form.save(commit=False)
                        donnee.capteur = capteur
                        donnee.save()
                    capteur.save()
                return redirect("smart_workshop_app:configuration_capteurs")
        else:
            initial = []
            for type_donnee in type_capteur.donnee.all():
                initial.append({'type_donnee': type_donnee, 'nom': type_donnee.nom})
            formset = formset_donnee(initial=initial)
            print(formset_donnee)
        context = {"formset": formset, "instance_id": pk, "instance_article": article}
        return render(request, 'smart_workshop_app/ajouter_donnees_capteur.html', context)