Hi. Client-side implementation of fields visual behavior and their validation should be hooked up via document.ready custom JS scripts via form ID or form class. There is no universal solution for that.
When using pure client-side forms from npm, it is possible to map these to Django models via DRF, however there will be no custom server-side widgets then. To me one of the most important parts of Django Forms is the ability to develop your own custom widgets. Server-side validation of forms can be processed with AJAX, there are few implementations of that, including mine: https://github.com/Dmitri-Sintsov/django-jinja-knockout/blob/master/docs/forms.rst#ajax-forms-processing It saves quite enough ot HTTP traffic, because instead of complete re-rendering of submitted form HTML page, only the list of field ID's and their error messages are returned to be highlighed by client-side Javascript code. It also allows to submit forms in AJAX "popup-like" dialogs: https://github.com/Dmitri-Sintsov/django-jinja-knockout/blob/db4beeb18296c87af8626980b6a0c91e16f80863/django_jinja_knockout/views/ajax.py#L203 It supports file upload progress bar automatically as well: https://github.com/Dmitri-Sintsov/django-jinja-knockout/blob/db4beeb18296c87af8626980b6a0c91e16f80863/django_jinja_knockout/static/djk/js/app.js#L1568 It's not so flexible (tied to Bootstrap 3 via Jinja2 macros) but it's possible to generalize such approach. With client-side Javascript there is always the trouble which library to chose - Angular / Vue / React - cannot suit everyone. I use Knockout.js which is outdated but requires no webpack / npm and works with ES5. It is also fully compatible to server-side DTL / Jinja2 templates (it does not use double curly braces, thus causes no syntax clashes). Dmitriy On Wednesday, January 31, 2018 at 6:31:56 PM UTC+3, Robert Roskam wrote: > > Hey All, > > Something I've regularly run into as a challenge is the implementation of > Django forms work well in the simple use cases, but as the use case grows > in complexity, Django forms become more difficult to work with. > > I know that's a super general statement, but here's the simplest complex > example I can give you. Lets say you're making an application for a home > builder, so that their Project Managers can better coordinate the builds. > One of the features is the ability to take notes and pictures on anything > that's not yet done and specifically if it relates to a specific piece of > equipment (AC, furnace, water pump, etc), they can add that too. Below is a > moderately simplistic example: > > class Note(models.Model): > project = models.ForeignKey('project_management.Project', > related_name="notes") > equipment = models.ForeignKey('equipment.Equipment', null=True, > blank=True, related_name="notes") > picture = models.FileField(null=True, blank=True) > is_blocker = models.BooleanField(default=True) > comment = models.TextField() > created_by = models.ForeignKey('users.User', verbose_name="Created By") > created_date = models.DateTimeField(default=timezone.now, > verbose_name="Created Date") > > > class NoteModalForm(forms.ModelForm): > class Meta: > fields = ('comment', 'is_blocker','equipment', 'picture') > model = Note > labels = { > 'comment': 'Note', > 'is_blocker': 'Blocking Issue', > 'picture': 'Picture', > } > widgets = { > 'picture': DragNDropFileButtonInput(button_text='Select file > to Upload', > button_classes='btn > btn-bordered uploader'), > } > > > > General comments first: > > 1. I would say there's no better way to accomplish what is currently > on that form given the current Form Meta API. (Willing to be challenged on > this point, btw.) > 2. The repetition of picture 3 times over (fields tuple, labels dict, > widgets, dict) seems to be inherently not DRY. If this gets very long, > then > it becomes harder to manage. > 3. The API on the Model Form itself behaves not quite like you'd > expect initially. You'd expect redeclaring fields directly on a form for > it > to function like a dictionary update, if the value doesn't exist in the > incoming dictionary, it keeps what's there. It actually behaves like > re-declaration. This very significant behavior is buried in a note ( > > https://docs.djangoproject.com/en/2.0/topics/forms/modelforms/#overriding-the-default-fields). > > Additionally, you'll have sources like pydanny basically tell you this is > an anti-pattern: https://www.pydanny.com/overloading-form-fields.html > 4. The API on Meta leads you to believe initially that you can > override lots of things via Meta, and it's difficult to discover what is > or > is not supported. (I usually dig into django.forms.models, and then wander > around until I get to ModelForm.) > - Here's the list: *model, fields, exclude, widgets, > localized_fields, labels, help_texts, error_messages, field_classes.* > > - What's missing that's on a *default* field? *Required, > initial, show_hidden_initial, validators, disabled, label_suffix. * > - Anything not on this list you basically need to override in > __init__ > 5. The Django Form API both does and does not care about the client > side implementation. I say it does care because it sets the default values > in the DOM if you use the form as recommended in the docs. However, there > is no recommended approach for anything beyond this. > > Here are some simple scenarios that are made difficult: > > Scenario #1 > If I'd like on this form--and this form only--to make *picture* always > required or change the default value of *is_blocker, *we have to override > __init__. And generally it looks like this: > > def __init__(self, *args, **kwargs): > super(NoteModalForm, self).__init__(*args, **kwargs) > self.fields['picture'].required = True > self.fields['is_blocker'].initial = False > > > Scenario #2 > If I have the feature request that notes that are blockers require > pictures or notes that have equipment requires pictures, then you have to > implement this pattern: > > > https://docs.djangoproject.com/en/2.0/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other > > Oh, but wait! The best in class approach to this problem would be to > inform the user before they submit the form that this is a problem. This > catches it only on the server side. How should we implement that? You're on > your own to figure it out. > > > So in summary, I feel like this could be improved. And I'd like to take an > whack at it! > > > > Robert Roskam > -- You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/django-developers. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/4951bf5a-e526-4322-83fe-6129e3138bc9%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
