Processing a Django Form in a Celery Task - How can the celery task see the form?

Viewed 440

The use case is rather simple. That of a background transaction manager, which requires that this classic type of post handler:

class MyCreate(CreateView):
    model = MyModel
    fields = '__all__'

    def post(self, request, *args, **kwargs):
        self.form = self.get_form()

        if self.form.is_valid():
            self.object = self.form.save(commit=True)
            return self.form_valid(self.form)
        else:
            return self.form_invalid(self.form)

doesn't save the form with form.save(), but rather saves the form object somewhere (to the session?) starts a Celery task which will then be responsible for running form.save()

The problem I'm facing is that the form object is refusing to serialize at all, with JSON or pickle, it's just too rich an object, and starting a Celery task requires the arguments to be serialized. I can serialize just the POST data (request.POST) which is doable, and pass it to the Celery task as an argument which works but I can't from that find any way to re-instantiate a form, let alone a formset.

if I want to start the Celery task from a view I redirect to (that implements a progress bar say) then I have the even bigger challenge of passing the form to a whole new Django view. The obvious candidate is to save it to session:

self.request.session["my_form_data"] = self.request.POST

But then in the Celery task, I can't even load that session data (I can possibly wrangle it using out of view sessions), or in the view load, it then passes it as an argument.

The aim though is that the Celery task has a Form object that we can call the save() method on, from the posted data, and generally manage and manipulate as we do a Form. One possibility is to instantiate a ModelForm using the POST data as Initial data then saving that but that's not obviously a solution and may or may not work.

In short, I'm trying to recreate a small part of the view context inside a Celery task, and given how often I see Django and Celery mentioned on-line together (and they seem to work well together) I'm really wondering before I experiment this to death with a hacked up solution, if there are not some simple or canonical means of doing this that I am missing.

I see hints of solutions all over the place. There is the django-remote-forms which promises to serialize a form but offers no means of recreating a Form object or objects (given we maybe use FormSets) from such serialized data. And there's the hint of a FormSerializer in the Django REST framework, but that's a big bundle of package and learning with lots of baggage that may not even do what I need by the time I'm done.

There's even good documentation of serializing Django objects, but not Forms.

It would be a dream if there was a simple, canonical method of passing a Django Form object to a Celery Task so it can work with it just as the Django view might.

0 Answers
Related