Search code examples
pythondjangoclassdjango-class-based-views

I cannot pass the values between the methods in classBasedView


I need to pass the bundle and the message values to get_context_data() method, but I cannot figure out how to do it. In this instance the form is valid when I pass it (I can add the better error handling when I figure out why the data gets updated in the post method, but doesn't in the get_context_data()). The form has just 1 filed and it takes the file.

Please help.

class FirmwareView(FormView, TemplateView):
    template_name = "dev_tools/firmware_cbv2.html"
    form_class = forms.InitialFirmwareForm2

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.bundle = {}
        self.message = {}

    def get_success_url(self):
        return self.request.path

    def post(self, request, *args, **kwargs):
        form = self.get_form()
        if form.is_valid():
            if request.FILES:
                if "file" in request.FILES:
                    file = request.FILES["file"]
                    try:
                        content = json.loads(file.read().decode('utf-8'))
                        folder_name = utils.format_folder_name(content["title"])
                        units = []
                        for unit in content["units"]:
                            units.append(unit)
                        self.bundle["units"] = units
                        self.bundle["file"] = {
                            "name": folder_name,
                            "content": json.dumps(content)
                        }
                        self.message = {
                            "type": "info",
                            "content": "The form was parsed successfully"
                        }
                    except Exception as e:
                        print("there was an error", e)
            return self.form_valid(form)
        else:
            print("the form is invalid")
            return self.form_invalid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context["bundle"] = self.bundle
        context["msg"] = self.message
        return context

    def form_valid(self, form):
        if isinstance(form, forms.InitialFirmwareForm2):
            return super().form_valid(form)

Solution

  • I'd recommend the following:

    1. Move most of your post() method to form_valid() method. It does not make sense to create the if form.is_valid() statement inside of your post() because exactly that logic is the default step between post and form_valid in class-based-views.
    2. Remove the entire __init__() method and pass message and bundle dicts directly to the get_context() method
    3. Remove the inheritance of TemplateView. FormView already has the template handling mixed in as a mixin because it is obvious that you want to show a template in the end.
    4. You might also want to remove the if isinstance(form, forms.InitialFirmwareForm2)... I mean you are defining the form for this view via form_class = .... So why are you doubting it takes the correct form?
    class FirmwareView(FormView, TemplateView):
        template_name = "dev_tools/firmware_cbv2.html"
        form_class = forms.InitialFirmwareForm2
    
        def get_success_url(self):
            return self.request.path
    
        def form_invalid(self, form):
            print("the form is invalid")
            return super().form_invalid(form)
    
        def get_context_data(self, message=None, bundle=None,**kwargs):
            context = super().get_context_data(**kwargs)
            context['bundle'] = bundle
            context['message'] = message
            return context
    
        def form_valid(self, form):
            bundle, message = {}, {}
            if isinstance(form, forms.InitialFirmwareForm2):  # why this?
                if request.FILES:
                    if "file" in request.FILES:
                        file = request.FILES["file"]
                        try:
                            content = json.loads(file.read().decode('utf-8'))
                            folder_name = utils.format_folder_name(content["title"])
                            units = []
                            for unit in content["units"]:
                                units.append(unit)
                            bundle["units"] = units
                            bundle["file"] = {
                                "name": folder_name,
                                "content": json.dumps(content)
                            }
                            message.update({
                                "type": "info",
                                "content": "The form was parsed successfully"
                            })
                        except Exception as e:
                            print("there was an error", e)
                    else:
                        print("No files in request.FILES - this situation is not handled.")
                else:
                    print("request.FILES does not evaluate to True")
            return render(self.request, self.template_name, context=self.get_context_data(message=message, bundle=bundle))
    

    Of course you have to get rid of the print statements. But they hint you to situations that are not covered by your code right now.

    Let me know if this works out for you.