Friday, December 31, 2021

Re: Eliminating inter-request race conditions

Good to hear from you Carsten. Thanks in advance for your comments. I'll see what I can address now:

> *2)* Not being able to safely lock a model/queryset beyond the lifetime of the request. 
I don't quite understand this. It sounds like pessimistic locking?
Correct. To be clear, I am not advocating this behaviour by default, but making it as seamless as possible to enable when required, rather than needing to attempt to hand-roll safe locking semantics each time it's needed.
 
> *3)* Not knowing that data has changed on the server until you submit a form.
> *4)* Smarter form validation

Well, this comes at the cost of the complexity to implement this. For me, at least at this time, the cost is much to high to consider this.
Certainly there is increased complexity. For the websites I am involved in (primarily health-related ones), if I don't end up providing a django-based solution, product owners end up demanding a SPA-based solution or similar, with the even-greater complexity to the development stack, not to mention testing. 

 
> *The solutions*
>
> *Enhanced forms*
> - when rendering a form (using e.g. as_p()), alongside the normal INPUT DOM elements, include additional hidden fields which store a copy of each form field's initial value.

I don't think that having hidden fields with the initial values is necessary: In your view, you can initialize the form like this:

if request.method == 'POST':
form = SomeForm(request.POST, initial=init)
...

Note the `initial` parameter: It is used just as it is in the GET request. This allows you to use `form.changed_data` and `form.has_changed()` in form validation.
But where does "init" come from? How can you know what version of the model instance was shown to the user when the form was rendered? There are only two ways I can see of to achieve this: use a full-blown "rowversion" CAS pattern, where there is a dedicated monotonic column on each table which automatically increases with each update, or the method I propose/use, where the original form values are provided via the user agent when the form is POSTed. I guess a third option would be to cache the form values server-side using redis each time a form a served, and provide an ID to it, perhaps even using the CSRF token as the key.

Perhaps I am missing something - if there is a way to retrieve the initial value of the form automatically, I would love to use it.

Regarding formsets, the same applies, I agree it needs to support that, and by embedding the original values into each form in the formset, it should correctly respect those values when the formset is submitted. 

If it's of any assistance, I can push some code and provide some examples for you to try out. The same app I am using now should be quite easy to clone and evaluate. 

Best regards,
Carsten
 
Gute Rutsch.

Nick 

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/cafc7989-44de-4035-88d1-c9d010946ed3n%40googlegroups.com.

No comments:

Post a Comment