معرفی شرکت ها


django-frontend-forms-0.2.9


Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر
Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر
Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر
Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر
Card image cap
تبلیغات ما

مشتریان به طور فزاینده ای آنلاین هستند. تبلیغات می تواند به آنها کمک کند تا کسب و کار شما را پیدا کنند.

مشاهده بیشتر

توضیحات

A Django helper app to add editing capabilities to the frontend using modal forms
ویژگی مقدار
سیستم عامل -
نام فایل django-frontend-forms-0.2.9
نام django-frontend-forms
نسخه کتابخانه 0.2.9
نگهدارنده []
ایمیل نگهدارنده []
نویسنده Mario Orlandi
ایمیل نویسنده morlandi@brainstorm.it
آدرس صفحه اصلی http://github.com/morlandi/django-frontend-forms
آدرس اینترنتی https://pypi.org/project/django-frontend-forms/
مجوز MIT
django-frontend-forms ===================== A Django helper app to add editing capabilities to the frontend using modal forms. An accompaning `Demo site <http://frontend-forms.brainstorm.it/>`_ provides: - usage instructions and suggestions - a detailed description of the techniques used under the hood - a list of working code samples (source: https://github.com/morlandi/django-frontend-forms/tree/master/example/samples) Bases on my previous research as documented here: `Editing Django models in the front end <https://editing-django-models-in-the-frontend.readthedocs.io/en/latest/>`_ .. image:: screenshots/main_screen.png .. contents:: .. sectnum:: Installation ------------ Install the package by running: .. code:: bash pip install django-frontend-forms or: pip install git+https://github.com/morlandi/django-frontend-forms In your settings, add: .. code:: python INSTALLED_APPS = [ ... 'frontend_forms', ] Include library's views mapping (file `urls.py`): .. code:: python urlpatterns = [ ... path('frontend_forms/', include('frontend_forms.urls', namespace='frontend_forms')), ... In your base template, include: the default styles, the javascript support, the javascript messaeg catalog, and optionally the sample HTML template: .. code:: html <link rel='stylesheet' href="{% static 'frontend_forms/css/frontend_forms.css' %}"> <script src="{% static 'frontend_forms/js/frontend_forms.js' %}"></script> <script src="{% url 'frontend_forms:javascript-catalog' %}"></script> {% include 'frontend_forms/dialogs.html' %} How to use it ------------- Follow the intructions given on the `Demo site <http://frontend-forms.brainstorm.it/>`_ Basic example ............. In the following example, we build a Dialog() object providing some custom options; then, we use it to open a modal dialog and load it from the specified url. For demonstration purposes, we also subscribe the 'created' notification. .. code:: html <script language="javascript"> $(document).ready(function() { dialog1 = new Dialog({ html: '<h1>Loading ...</h1>', url: '{% url 'frontend:j_object' %}', width: '400px', min_height: '200px', title: '<i class="fa fa-calculator"></i> Selezione Oggetto', footer_text: 'testing dialog ...', enable_trace: true, callback: function(event_name, dialog, params) { switch (event_name) { case "created": console.log('Dialog created: dialog=%o, params=%o', dialog, params); break; } } }); }); </script> <a href="#" class="btn btn-primary pull-right" onclick="dialog1.open(event); return false;"> <i class="fa fa-plus-circle"></i> Test Popup </a> Dialog methods .............. =============================== =================================================================================================================== Method Effects ------------------------------- ------------------------------------------------------------------------------------------------------------------- constructor(options={}) See `options` list below open(event=null, show=true) Open the dialog 1. the dialog body will be immediately loaded with static content provided by option "html" 2. then the dialog is shown (unless the "show" parameter is false) 3. finally, dynamic content will be loaded from remote address provided by option "url" (if supplied) 4. if successfull, a 'loaded.dialog' event is fired; you can use it to perform any action required after loading close() Close (hide) the dialog show() Make the dialog visible =============================== =================================================================================================================== Dialog options .............. =============================== ========================== =============================================================== Option Default value Notes ------------------------------- -------------------------- --------------------------------------------------------------- dialog_selector '#dialog_generic' The selector for HTML dialog template open_event null Used to "remember" the event which triggered Dialog opening html '' Static content to display in dialog body url '' Optional url to retrieve dialog content via Ajax width null min_width null max_width null height null min_height null max_height null button_save_label 'Save' button_save_initially_hidden false Will be shown after form rendering button_close_label 'Cancel' title '' subtitle '' footer_text '' enable_trace false show notifications in debug console callback null a callback to receive events autofocus_first_visible_input true =============================== ========================== =============================================================== Unspecified options will be retrieved from corresponding HTML attributes on the element which fires the dialog opening; for example: .. code:: html <a href="{% url 'frontend:whatever' object.id %}" data-title="My title" data-subtitle="My Subtitle" onclick="new Dialog().open(event); return false;"> Open </a> =============================== ========================== Option HTML attribute ------------------------------- -------------------------- url href html data-html width data-width min_width data-min-width max_width data-max-width height data-height min_height data-min-height max_height data-max-height button_save_label data-button-save-label button_close_label data-button-close-label title data-title subtitle data-subtitle footer_text data-footer-text =============================== ========================== Dialog notifications .................... ============================ ================================ event_name params ============================ ================================ created options closed initialized shown loading url loaded url, data loading_failed jqXHR, textStatus, errorThrown open submitting method, url, data submission_failure method, url, data submitted method, url, data ============================ ================================ During it's lifetime, the Dialog will notify all interesting events to the caller, provided he supplies a suitable callback in the contructor: self.options.callback(event_name, dialog, params) Example: .. code:: javascript dialog1 = new Dialog({ ... callback: function(event_name, dialog, params) { console.log('event_name: %o, dialog: %o, params: %o', event_name, dialog, params); } }); Result:: event_name: "created", dialog: Dialog {options: {…}, element: …}, params: {options: {…}} event_name: "initialized", dialog: Dialog {options: {…}, element: …}, params: {} event_name: "open", dialog: Dialog {options: {…}, element: …}, params: {} event_name: "shown", dialog: Dialog {options: {…}, element: …}, params: {} event_name: "loading", dialog: Dialog {options: {…}, element: …}, params: {url: "/admin_ex/popup/"} event_name: "loaded", dialog: Dialog {options: {…}, element: …}, params: {url: "/admin_ex/popup/"} event_name: "submitting", dialog: Dialog {options: {…}, element: …}, params: {method: "post", url: "/admin_ex/popup/", data: "text=&number=aaa"} event_name: "submitted", dialog: Dialog {options: {…}, element: …}, params: {method: "post", url: "/admin_ex/popup/", data: "text=111&number=111"} event_name: "closed", dialog: Dialog {options: {…}, element: …}, params: {} You can also trace all events in the console setting the boolean flag `enable_trace`. Handling form submission ------------------------ When a form submission is involved, the modal life cycle has to be modified as follows: - First and foremost, we need to **prevent the form from performing its default submit**. If not, after submission we'll be redirected to the form action, outside the context of the dialog. We'll do this binding to the form's submit event, where we'll serialize the form's content and sent it to the view for validation via an Ajax call. - Then, upon a successufull response from the server, **we'll need to further investigate the HTML received**: + if it contains any field error, the form did not validate successfully, so we update the modal body with the new form and its errors + otherwise, user interaction is completed, and we can finally close the modal `django-frontend-forms`, upon detecting a form in the content downloaded from the server, already takes care of all these needs automatically, and keeps refreshing the modal after each submission until the form validation succeedes. Giving a feedback after successful form submission -------------------------------------------------- Sometimes, you might want to notify the user after successful form submission. To obtain this, all you have to do, after the form has been validated and saved, is to return an HTML fragment with no forms in it; in this case: - the popup will not close - the "save" button will be hidden thus giving to the user a chance to read your feedback. .. code:: bash def form_validation_with_feedback(request): assert request.is_ajax() if request.method == 'POST': form = MyForm(data=request.POST) if form.is_valid(): form.save() return HttpResponse("<h1>Great !</h1> Your form has been validated") else: form = MyForm() return render(request, "my_form.html", { 'form': form, }) Logging in with a modal form ---------------------------- If you're trying to minimize page switching and reduce navigation in your frontend, why not provide a modal window for login as well ? The library contains a login view adapted from the standard (function based) Django login view, which can be used for either a standalone HTML page or in a Dialog. For example: .. code:: html <a id="login_with_dialog" href="{% url 'frontend_forms:login' %}"> <i class="fa fa-sign-in"></i> Login </a> <script language="javascript"> $(document).ready(function() { $('#login_with_dialog').on('click', function(event) { event.preventDefault(); var target = $(event.target); var url = target.attr('href'); var logged_in = false; var login_dialog = new Dialog({ url: url, width: '400px', min_height: '200px', title: '<i class="fa fa-sign-in"></i> Login ...', button_save_label: "Login", button_close_label: "Close", callback: function(event_name, dialog, params) { switch (event_name) { case "submitted": logged_in = true; break; case "closed": if (logged_in) { FrontendForms.redirect('/', true); } break; } } }); login_dialog.open(event); }); }); </script> .. image:: screenshots/login-dialog.png You can customize the following templates: - frontend_forms/login.html - frontend_forms/login_inner.html - frontend_forms/login_successful_message.html Replacing login_required ------------------------ A decorator suitable for modal forms is provided to replace login_required(): .. code:: python from frontend_forms.decorators import check_logged_in @check_logged_in() def my_view(request, ...): ... It checks that the user is logged in, showing an error message in place if not. You can customize the following template: - frontend_forms/check_logged_in_failed.html A full, real example for a Django Form submission from a Dialog --------------------------------------------------------------- .. image:: screenshots/contract-form.png We start by creating a view for form rendering and submission: file `ajax.py`: .. code:: python import time from frontend_forms.decorators import check_logged_in from django.views.decorators.cache import never_cache from django.core.exceptions import PermissionDenied from django.http import HttpResponseRedirect @check_logged_in() @never_cache def select_contract(request): # if settings.DEBUG: # time.sleep(0.5); if not request.user.has_perm('backend.view_contract') or not request.is_ajax(): raise PermissionDenied #template_name = 'frontend/dialogs/generic_form_inner_with_video.html' template_name = 'dashboard/dialogs/select_contract.html' object = None if request.method == 'POST': form = SelectContractForm(request=request, data=request.POST) if form.is_valid(): object = form.save(request) if not request.is_ajax(): # reload the page next = request.META['PATH_INFO'] return HttpResponseRedirect(next) # if is_ajax(), we just return the validated form, so the modal will close else: form = SelectContractForm(request=request) return render(request, template_name, { 'form': form, 'object': object, # unused, but armless }) and provide an endpoint to it for ajax call: file `urls.py` .. code:: python from django.urls import path from . import ajax app_name = 'dashboard' urlpatterns = [ ... path('j/select_contract/', ajax.select_contract, name='j_select_contract'), ... ] The Form in this example does a few interesting things: - includes some specific assets declaring an inner Media class - receives the request upon construction - uses it to provide specific initial values to the widgets - provides some specific validations with `clean()` - encapsulates in `save()` all actions required after successfull submission file `forms.py`: .. code:: python import json import datetime from django import forms from selectable.forms import AutoCompleteWidget, AutoCompleteSelectWidget, AutoComboboxSelectWidget from backend.models import Contract from django.utils.safestring import mark_safe from .lookups import ContractLookup class SelectContractForm(forms.Form): contract = forms.CharField( label='Contract', widget=AutoComboboxSelectWidget(ContractLookup, limit=10), required=True, help_text=mark_safe("&nbsp;"), ) today = forms.BooleanField(label="Oggi", required=False) date = forms.DateField(widget=forms.DateInput(), label='', required=False) class Media: css = { 'screen': ('dashboard/css/select_contract_form.css', ) } js = ('dashboard/js/select_contract_form.js', ) def __init__(self, request, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['date'].widget = forms.DateInput(attrs={'class': 'datepicker'}) assert request.user.is_authenticated and request.user.is_active self.fields['contract'].initial = request.user.contract_attivo self.fields['date'].initial = request.user.data_attiva self.fields['today'].initial = request.user.data_attiva is None def lookup_contract(self): try: contract = Contract.objects.get( id=self.cleaned_data['contract'] ) except Contract.DoesNotExist: contract = None return contract def clean(self): cleaned_data = self.cleaned_data if not cleaned_data['today'] and not cleaned_data['date']: raise forms.ValidationError({ 'date': 'Questo campo è obbligatorio' }) return cleaned_data def save(self, request): user = request.user assert request.user.is_authenticated and request.user.is_active user.contract_attivo = self.lookup_contract() if self.cleaned_data['today']: user.data_attiva = None else: user.data_attiva = self.cleaned_data['date'] user.save(update_fields=['contract_attivo', 'data_attiva', ]) The javascript and css assets are used for specific needs of this form: .. code:: javascript function onChangeToday(event) { var controller = $('#id_today'); var value = controller.is(":checked"); $('#id_date').prop('disabled', value); $('.field-date .ui-datepicker-trigger').prop('disabled', value); if (value) { $('#id_date').datepicker('setDate', null); } } $(document).ready(function() { $('#id_today').on('change', onChangeToday); onChangeToday(); }); In the template, remember to include the Form's assets: .. code:: html {% load i18n frontend_forms_tags %} {{ form.media.css }} <div class="row"> <div class="col-sm-12"> <form action="{{ action }}" method="post" class="form {{form.form_class}}" novalidate autocomplete="off"> {% csrf_token %} {% if form.errors or form.non_field_errors %} <p class="errornote">{% trans 'Please correct the error below.' %}</p> {% endif %} {% if form.non_field_errors %} <ul class="errorlist"> {% for error in form.non_field_errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} {% for hidden_field in form.hidden_fields %} {{ hidden_field }} {% endfor %} <fieldset> {% render_form_field form.contract %} <div>Data di riferimento:</div> <div class="data-selection-block"> {% render_form_field form.today %} {% render_form_field form.date %} </div> </fieldset> <input type="hidden" name="object_id" value="{{ object.id|default:'' }}"> <div class="form-submit-row"> <input type="submit" value="Save" /> </div> </form> </div> </div> {% if request.is_ajax %} {{ form.media.js }} {% endif %} And finally, the Dialog itself; please note that we use the `loaded` event notification to rebind the widgets after form rendering. .. code:: html {% block extrajs %} <script language="javascript"> $(document).ready(function() { dialog1 = new Dialog({ dialog_selector: '#dialog_generic', html: '', url: "{% url 'dashboard:j_select_contract' %}", width: '80%', max_width: '400px', min_height: '200px', button_save_label: 'Salva', button_close_label: 'Annulla', title: '<i class="fa fa-file-o"></i> Selezione Contract', footer_text: '', enable_trace: true, callback: function(event_name, dialog, params) { switch (event_name) { case "loaded": bindSelectables(); dialog.element.find(".datepicker").datepicker({}); break; case "submitted": FrontendForms.reload_page(show_layer=true); break; } } }); $('.btn-cambia-contract').off().on('click', function(event) { event.preventDefault(); dialog1.open(); }) }); </script> {% endblock extrajs %} Editing a Django Model from a Dialog ------------------------------------ TODO: TO BE REFINED ... AND VERIFIED ;) First of all, we need a view for form rendering and submission. For example: .. code:: python @check_logged_in() @never_cache def edit_something(request, id_object=None): # if not request.user.has_perm('backend.view_something') or not request.is_ajax(): # raise PermissionDenied if id_object is not None: object = get_object_or_404(Something, id=id_object) else: object = None template_name = 'frontend_forms/generic_form_inner.html' if request.method == 'POST': form = SomethingForm(data=request.POST, instance=object) if form.is_valid(): object = form.save(request) if not request.is_ajax(): # reload the page next = request.META['PATH_INFO'] return HttpResponseRedirect(next) # if is_ajax(), we just return the validated form, so the modal will close else: form = SomethingForm() return render(request, template_name, { 'form': form, 'object': object, # unused, but armless }) where: .. code:: python class SomethingForm(forms.ModelForm): class Meta: model = Someghing exclude = [] ... and an endpoint for Ajax call: File "urls.py" ... .. code:: python path('j/edit_something/<int:id_object>/', ajax.edit_something, name='j_edit_something'), We can finally use the form in a Dialog: .. code:: javascript $(document).ready(function() { dialog1 = new Dialog({ dialog_selector: '#dialog_generic', html: '<h1>Loading ...</h1>', url: '/j/edit_something/{{ object.id }}/', width: '400px', min_height: '200px', title: '<i class="fa fa-add"></i> Edit', footer_text: '', enable_trace: true, callback: function(event_name, dialog, params) { switch (event_name) { case "created": console.log('Dialog created: dialog=%o, params=%o', dialog, params); break; case "submitted": FrontendForms.hide_mouse_cursor(); FrontendForms.reload_page(true); break; } } }); }); Default dialog layout --------------------- When contructing a Dialog, you can use the `dialog_selector` option to select which HTML fragment of the page will be treated as the dialog to work with. It is advisable to use an HTML structure similar to the default layout: .. code:: html <div id="dialog_generic" class="dialog draggable"> <div class="dialog-dialog"> <div class="dialog-content"> <div class="dialog-header"> <span class="spinner"> <i class="fa fa-spinner fa-spin"></i> </span> <span class="close">&times;</span> <div class="title">Title</div> </div> <div class="dialog-body ui-front"> </div> <div class="dialog-footer"> <input type="submit" value="Close" class="btn btn-close" /> <input type="submit" value="Save" class="btn btn-save" /> <div class="text">footer</div> </div> </div> </div> </div> Notes: - ".draggable" make the Dialog draggable - adding ".ui-front" to the ".dialog-box" element helps improving the behaviour of the dialog on a mobile client App Settings ------------ =========================================== =============================================================== Option Accepted values ------------------------------------------- --------------------------------------------------------------- FRONTEND_FORMS_FORM_LAYOUT_FLAVOR "generic", "bs4" FRONTEND_FORMS_FORM_LAYOUT_DEFAULT "vertical", "horizontal" FRONTEND_FORMS_MODEL_FORMS_MODULES =========================================== =============================================================== Default values:: FRONTEND_FORMS_FORM_LAYOUT_FLAVOR = "generic" FRONTEND_FORMS_FORM_LAYOUT_DEFAULT = "vertical" FRONTEND_FORMS_MODEL_FORMS_MODULES = ['frontend.forms', ] "bs4" flavor ------------ Add the .compact-fields class to the form to modify the layout as in the right picture below: .. image:: screenshots/bs4-forms.png Utilities (module FrontendForms) -------------------------------- ======================================================= ======================================================================================== Helper Purpose ------------------------------------------------------- ---------------------------------------------------------------------------------------- display_server_error(errorDetails) Display an error message using SweetAlert2; failing that, uses a simple alert instead display_message(html_content) Display a message using SweetAlert2; failing that, uses a simple alert instead redirect(url, show_overlay=False) Similar behavior as an HTTP redirect; optionally calls overlay_show('body') gotourl(url, show_overlay=False) Similar behavior as clicking on a link; optionally calls overlay_show('body') reload_page(show_overlay=False) Reload the current page; optionally calls overlay_show('body') overlay_show(element) Show overlay on given element; Requires: gasparesganga-jquery-loading-overlay overlay_hide(element) Hide overlay on given element; Requires: gasparesganga-jquery-loading-overlay hide_mouse_cursor Hide the mouse cursor dumpObject(obj, max_depth) Serialize the given dictionary up to `max_depth` levels logObject(element, obj) Render `obj` content as HTML table an assign to given element isEmptyObject(obj) Check if given `obj` is empty cloneObject(obj) Deep clone an object in JavaScript lookup(array, prop, value) Find an Object by attribute in an Array formdata_serialize(formData) Serializing form data with the vanilla JS FormData() object formdata_to_querystring(formData) Transform FormData into query string adjust_canvas_size(id) Adapts canvas size to desired size getCookie(name) Add to POST headers as follows: FrontendForms.getCookie('csrftoken') confirmRemoteAction(url, options, afterDoneCallback) Invoke remote action upon user confirmation. downloadFromAjaxPost(url, params, headers, callback) Handle file download from ajax post querystring_parse(qs, sep, eq, options) Parse query string set_datepicker_defaults(language_code) Set datepicker defaults, and optionally select language ("it" or "es" for now) apply_multiselect(elements) Bind MultiSelect widget ======================================================= ======================================================================================== Form rendering helpers ---------------------- A **render_form(form, flavor=None, layout=FORM_LAYOUT_DEFAULT)** template tag is available for form rendering: .. code:: html {% load frontend_forms_tags ... %} <form method="post"> {% csrf_token %} {% render_form form %} <div class="form-group form-submit-row"> <button type="submit" class="btn btn-lg btn-primary btn-block">{% trans 'Submit' %}</button> </div> </form> For more a more advanced customization, you can use **render_form_field(field, flavor=None, extra_attrs='', layout=FORM_LAYOUT_DEFAULT, index=0, addon='')** instead: .. code:: html {% load frontend_forms_tags ... %} <form method="post"> {% csrf_token %} {% if form.non_field_errors %} <ul class="errorlist"> {% for error in form.non_field_errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} {% for hidden_field in form.hidden_fields %} {{ hidden_field }} {% endfor %} <fieldset> {% render_form_field form.username extra_attrs="autocomplete=^off,role=presentation,autocorrect=off,autocapitalize=none" %} {% render_form_field form.password extra_attrs="autocomplete=^off,role=presentation,autocorrect=off,autocapitalize=none" addon='<i class="fa fa-user"></i>' %} </fieldset> <div class="form-group form-submit-row"> <button type="submit" class="btn btn-lg btn-primary btn-block">{% trans 'Submit' %}</button> </div> </form> In this second example, we supply `extra_attrs` attributes to each form field; these will be added to the attributes already derived from the Django Form field definitions. The special prefix `^` will be removed from the attribute, and interpreted as "replace" instead of "append". A generic template is also available: `generic_form_inner.html`: .. code:: html {% load i18n frontend_forms_tags %} <div class="row"> <div class="col-sm-12"> <form action="{{ action }}" method="post" class="form" novalidate autocomplete="off"> {% csrf_token %} {% render_form form %} <input type="hidden" name="object_id" value="{{ object.id|default:'' }}"> <div class="form-submit-row"> <input type="submit" value="Save" /> </div> </form> </div> </div> Please note that, as a convenience when editing a Django Model, we've added an hidden field `object_id`; in other occasions, this is useless (but also armless, as long as the form doesn't contain a field called "object"). Datepicker support ------------------ A basic support is provided for jquery-ui datepicker. Follow these steps: (1) Initialize datepicker default by calling `FrontendForms.set_datepicker_defaults(language_code)` once: .. code:: javascript <script language="javascript"> $(document).ready(function() { moment.locale('it'); FrontendForms.set_datepicker_defaults('{{LANGUAGE_CODE}}'); <------------- ... (2) In your form, make sure that the `datepicker` class is assigned to the input element; for example: .. code:: python class MyForm(forms.Form): date = forms.DateField(widget=forms.DateInput()) ... def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['date'].widget = forms.DateInput(attrs={'class': 'datepicker'}) (3) If loading the form in a dialog, rebind as necessary: .. code:: javascript dialog1 = new Dialog({ ... callback: function(event_name, dialog, params) { switch (event_name) { case "loaded": bindSelectables(); dialog.element.find(".datepicker").datepicker({}); <------------- break; ... } } }); jQuery MultiSelect support -------------------------- Requirements:: <link rel="stylesheet" type="text/css" href="{% static 'multiselect/css/multi-select.css' %}" /> <script src="{% static 'multiselect/js/jquery.multi-select.js' %}"></script> <script src="{% static 'jquery.quicksearch/dist/jquery.quicksearch.min.js' %}"></script> Follow these steps: (1) In your form, add the `multiselect` class to the SelectMultiple() widget .. code:: python class MyForm(forms.ModelForm): ... def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['operators'].widget.attrs = {'class': 'multiselect'} (2) Later on, bind the widget using `apply_multiselect()` helper: .. code:: javascript dialog1 = new Dialog({ ... callback: function(event_name, dialog, params) { switch (event_name) { case "loaded": FrontendForms.apply_multiselect(dialog.element.find('.multiselect')); break; ... } } }); django-select2 support ---------------------- Requirements:: pip install django-select2 npm install select2 Changes to "settings.py":: INSTALLED_APPS = [ ... 'django_select2', ... Changes to "base.html":: <link rel="stylesheet" type="text/css" href="{% static 'select2/dist/css/select2.min.css' %}" /> <script src="{% static 'select2/dist/js/select2.min.js' %}"></script> <script src="{% static 'select2/dist/js/i18n/it.js' %}"></script> <script language="javascript"> $.fn.select2.defaults.set('language', 'it'); </script> <script src="{% static 'django_select2/django_select2.js' %}"></script> Follow these steps: (1) In your form, use one or more Select2Widget(): .. code:: python from django_select2.forms import HeavySelect2Widget class MyForm(forms.ModelForm): ... class Meta: ... widgets = { 'fieldname': HeavySelect2Widget( data_url='/url/to/json/response' ) } (2) Later on, bind the widgets using `djangoSelect2()` helper: .. code:: javascript dialog1 = new Dialog({ ... callback: function(event_name, dialog, params) { switch (event_name) { case "loaded": dialog.element.find('.django-select2').djangoSelect2({ // "dropdownParent" is required for Bootstrap; see: // https://select2.org/troubleshooting/common-problems#select2-does-not-function-properly-when-i-use-it-inside-a-bootst dropdownParent: dialog.element }); break; ... } } }); I normally opt to include all required static files in "base.hmtml", since I'm already including so much javascript stuff. In this case, make sure django-select2 won't istall them twice; for example: .. code:: python class MySelect2Widget(): """ Avoid inclusion of select2 by django-select2 as a result of {{form.media}}, since we're already including everything in base.html """ def _get_media(self): return None media = property(_get_media) class AlbumWidget(MySelect2Widget, ModelSelect2Widget): model = Album search_fields = [ 'name__istartswith', ] def build_attrs(self, base_attrs, extra_attrs=None): attrs = super().build_attrs(base_attrs=base_attrs, extra_attrs=extra_attrs) # "data-minimum-input-length"; # - either override build_attrs() here, # - or provide as attr in the instance; for example: # 'album': AlbumWidget(attrs={'data-minimum-input-length': 0,}), attrs['data-minimum-input-length'] = 0 return attrs History ======= v0.2.20 ------- - generic_edit_view() now treats request.FILES v0.2.19 ------- - [fix] frontend_forms.js was out of sync with frontend_forms.jsx v0.2.18 ------- - [fix] "it" language selection for datepicker - formdata_serialize() and formdata_to_querystring() helpers added v0.2.17 ------- * diplay_message() helper added v0.2.16 ------- * small style fix for checkbox in horizontal generic form rendering v0.2.15 ------- * revised example project v0.2.14 ------- * Prepare for Django 4.0 v0.2.13 ------- * POSSIBLE INCOMPATIBLE CHANGE: Radio button layout refactored in "render_form_field.html" * send "submission_failure" notification * package up data from form with FormData (instead of form.serialize()) to allow files upload * allow customization of `enctype` in generic form template * send "submission_failure" notification v0.2.12 ------- * Prevent default on close button submission v0.2.11 ------- * Replace $() with jQuery() for higher compatibility v0.2.10 ------- * Add never cache to all views for extra safeness v0.2.9 ------ * [fix] Properly hide btn_save and btn_close when corresponding label is empty v0.2.8 ------ * [fix] frontend_forms.js was out of sync with frontend_forms.jsx v0.2.7 ------ * Removed wrong [fix] render_form_field rendering for bootstrap v0.2.6 ------ * Update Pillow (example project) v0.2.5 ------ * Upgrade Django (in example project) * [fix] render_form_field rendering for bootstrap * Optionally retrieve missing Dialog options from HTML attributes * subtitle added to dialog_generic v0.2.4 ------ * in case of form errors, autofocus now selects the first editable invalid field v0.2.3 ------ * transpile frontend_forms.jsx v0.2.2 ------ * non-destructive form_class annotation v0.2.1 ------ * POSSIBLE INCOMPATIBLE CHANGE: Added javascript catalog for translating messages in JS code * Italian transation added * Example: chain selection sample * [fix] Send missing "submitted" notification v0.2.0 ------ * Login view suitable for modal forms * check_logged_in() decorator * fix format_datetime * POSSIBLE INCOMPATIBLE CHANGE: provided templates now extend "base.html" instead of "frontend/base.html" v0.1.13 ------- * Improved example project (Creating or updating a Django Model from the front-end) * revised confirmRemoteAction() helper v0.1.12 ------- * Make sure invalid-tooltip is visible with BS4 v0.1.11 ------- * Select2 support and examples v0.1.10 ------- * Small adjustments to default styles; "important" removed where possible * Partial support for Bootstrap's "input-group-addon" * Example updated v0.1.9 ------ * Giving a feedback after successful form submission v0.1.8 ------ * Make sure Sweetalert2 pops up above modal dialog v0.1.7 ------ * render_form_field: show errors for radio groups v0.1.6 ------ * example django project added v0.1.5 ------ * autofocus_first_visible_input option added v0.1.4 ------ * generic Form submission from a Dialog example added to Readme * fix horizontal forms for BS4 * add even/odd class to form groups v0.1.3 ------ * Display checkbox fields errors * Adjust errors styles v0.1.2 ------ * Optionally provide the `request` to the Form constructor * Add a class attribute 'form-app_label-model_name' to the rendered form * django-select2 support * jQuery MultiSelect support v0.1.1 ------ * ModalForms module renamed as FrontendForms * optional parameter `event` added to open() v0.1.0 ------ * Module renamed from "django-modal-forms" to "django-frontend-forms" v0.0.14 ------- * Fixes for Django 3; support both int and uuid PKs v0.0.13 ------- * Configurable FRONTEND_FORMS_FORM_LAYOUT_DEFAULT v0.0.12 ------- * Support for model forms in a Dialog (undocumented) v0.0.11 ------- * Datepicker support v0.0.10 ------- * optional extra_attrs added to render_form_field template tag v0.0.9 ------ * fix confirmRemoteAction() v0.0.8 ------ * fix v0.0.7 ------ * add custom widget attrs when rendering a field with render_form_fields() v0.0.6 ------ * add "has-error" class when appropriate in render_form_field tag, to trigger errors in modal forms v0.0.5 ------ * "simpletable" fix v0.0.4 ------ * "simpletable" styles v0.0.3 ------ * downloadFromAjaxPost helper JS function added * Display non_field_errors in BS4 form * Prepend fields' class with 'field-' prefix, as Django admin does * Radio buttons and Checkboxs rendering for Bootstrap 4 * bs4 form rendering * querystring_parse() utility added * Add object_id hidden field to generic form * .ui-front added to .dialog-body for bette behaviour on mobiles * notify "loaded" event in _form_ajax_submit() when approriate v0.0.2 ------ * First working release v0.0.1 ------ * Project start


نحوه نصب


نصب پکیج whl django-frontend-forms-0.2.9:

    pip install django-frontend-forms-0.2.9.whl


نصب پکیج tar.gz django-frontend-forms-0.2.9:

    pip install django-frontend-forms-0.2.9.tar.gz