adamghill / django-unicorn

The magical reactive component framework for Django ✨
https://www.django-unicorn.com
MIT License
2.33k stars 118 forks source link

Django Forms integration not working well #469

Open iwalucas opened 1 year ago

iwalucas commented 1 year ago

So I have a regular django form that I am porting to django-unicorn, so I can dynamically update the queryset.

Depending on the approach I have some strange errors.

Component

<div>
{{form}}
</div>

Unicorn View

from django_unicorn.components import UnicornView,QuerySetType 

class MyView(UnicornView):
    form = None
    class Meta:
        exclude = ()
        javascript_exclude = (
            "form",
        )

Django template {% unicorn 'myview' form=form %}

Then on any interaction I get:

Cannot cache component '<class 'project.components.myview.MyView'>' because it is not picklable: <class '_pickle.PicklingError'>: Can't pickle <function paginator_number at 0x1028d6170>: it's not the same object as django.contrib.admin.templatetags.admin_list.paginator_number

I left just the necessary to reproduce the issue....

The form_class documentation is not so clear on how to use that, and when trying, it gives a whole new set of issues.

(awesome project! I have been looking for this for years!)

adamghill commented 1 year ago

Hello! So, the root cause when this happens is because Unicorn is trying to pickle the UnicornView and store it in cache (this is used to speed up later instantiations of the same view and for state management purposes). I assume the form passed into {% unicorn 'myview' form=form %} is a form instance? I've tried to get around the non-pickleable errors in the past and run into a whole other host of challenges. I could investigate other ways to serialize/deserialize objects if pickle-ing fails maybe? Or fallbacks if the pickle-ing fails?

However, I would be curious what issues you are running into using form_class because that is the "supported" path to use forms, i.e. it's what I've tested the most. :) If there are improvements to the documentation to make it more clear, that would definitely be good to know. Just in case you haven't already seen it, there is an example site in this repo with a form_class example (although it's pretty minimal): form_class and html. The gist is that if the UnicornView and the form_class attributes match up, the form will get used for validation. If you fork this repo and add an example form that is causing issues that would be helpful. Or if you just put some example form code into this issue that would work, too.

There are some other issues in this repo about better integration with forms. I'd love to hear your feedback/thoughts about how to improve that experience. 👍

iwalucas commented 1 year ago

Hi @adamghill thanks for the quick response. Basically I was losing the initial field value when using form_class and accessing my data (update view)....

I tried to manually populate, but no good:

class MyView(UnicornView):
    form_class = MyForm 
    my_cool_field = None

    class Meta:
        exclude = ()
        javascript_exclude = (
            "form",
        )

    def mount(self): 
        print(self.form.instance)
        if self.form.instance.id:
            print(self.form.instance.my_cool_field)
            self. my_cool_field = self.form.instance.my_cool_field            

Maybe I am doing something wrong? The field is a dropdown, and the values are there, but it shows a blank entry

iwalucas commented 1 year ago

@adamghill some piece of information. If I remove the model from the unicornview, the value is kept and it works.... I think I will go this way

adamghill commented 1 year ago

Interesting! Ok, I'll do some more testing on my own and let you know what I discover/if I find bugs that I can fix.

I assume I could use something like this for MyForm for testing purposes?

class MyForm(forms.Form):
    my_cool_field = forms.CharField()
iwalucas commented 1 year ago

@adamghill yes, if you want to do a zoom or something, I am more than happy to help. Since I am new on django-unicorn, I cant help on fixing things, but I will get there :)

elya5 commented 7 months ago

I just ran into the same pickling error. I have a GET form that is validated in views.py. Then, it gets passed to the UnicornView.

This stackoverflow answer removed the warning. However, I'm not sure what information gets lost in the process.