Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

A Django plugin for creating AJAX driven forms in Bootstrap modal.

License

NotificationsYou must be signed in to change notification settings

trco/django-bootstrap-modal-forms

Repository files navigation

A Django plugin for creating AJAX driven forms in Bootstrap modal.

Test and experiment on your machine

This repository includesDockerfile anddocker-compose.yml files so you can easily setup and start to experiment withdjango-bootstrap-modal-forms running inside of a container on your local machine. Any changes you make inbootstrap_modal_forms,examples andtest folders are reflected in the container (see docker-compose.yml) and the data stored in sqlite3 database are persistent even if you remove stopped container.

Note thatmaster branch contains Bootstrap 4 examples, whilebootstrap5-examples branch contains Bootstrap 5 examples. To experiment with Bootstrap 5 examples simply switch the branch.

Follow the steps below to run the app:

$ clone repository$ cd django-bootstrap-modal-forms$ docker compose up (use -d flag to run app in detached mode in the background)$ visit 0.0.0.0:8000

General information

Opening an issue

When reporting an issue fordjango-bootstrap-modal-forms package, please prepare a publicly available repository having the issue you are reporting. The clear reproduce is the optimal way towards resolution.

Contribute

This is an Open Source project and any contribution is highly appreciated.

Tests

Run unit and functional tests inside of project folder:

$ python manage.py test

Installation

  1. Installdjango-bootstrap-modal-forms:

    $ pip install django-bootstrap-modal-forms
  2. Addbootstrap_modal_forms to your INSTALLED_APPS in settings.py:

    INSTALLED_APPS = [    ...    'bootstrap_modal_forms',    ...]
  3. Include Bootstrap, jQuery andjquery.bootstrap(5).modal.forms.js on every page where you would like to set up the AJAX driven Django forms in Bootstrap modal.IMPORTANT: Adjust Bootstrap and jQuery file paths to match yours, but includejquery.bootstrap.modal.forms.js exactly as in code bellow.

<head>    <linkrel="stylesheet"href="{% static 'assets/css/bootstrap.css' %}"></head><body>    <scriptsrc="{% static 'assets/js/bootstrap.js' %}"></script><!-- Bootstrap 4-->    <scriptsrc="{% static 'assets/js/jquery-3.2.1.min.js' %}"></script>    <scriptsrc="{% static 'assets/js/popper.min.js' %}"></script>    <scriptsrc="{% static 'assets/js/bootstrap.min.js' %}"></script><!-- You can alternatively load the minified version-->    <scriptsrc="{% static 'js/jquery.bootstrap.modal.forms.js' %}"></script><!-- Bootstrap 5-->    <scriptsrc="{% static 'assets/js/bootstrap.bundle.min.js' %}"></script>    <scriptsrc="{% static 'js/bootstrap5.modal.forms.js' %}"></script><!-- You can alternatively load the minified version-->    <scriptsrc="{% static 'js/bootstrap5.modal.forms.min.js' %}"></script></body>

How it works?

index.html<scripttype="text/javascript">// BS4$(document).ready(function(){$("#create-book").modalForm({formURL:"{% url 'create_book' %}"});});// BS5// instantiate single modal formdocument.addEventListener('DOMContentLoaded',(e)=>{modalForm(document.getElementById('create-book'),{formURL:"{% url 'create_book' %}"})});// BS5// instantiate multiple modal forms with unique formUrlsdocument.addEventListener('DOMContentLoaded',(e)=>{vardeleteButtons=document.getElementsByClassName("delete-book");for(varindex=0;index<deleteButtons.length;index++){modalForm(deleteButtons[index],{formURL:deleteButtons[index]["dataset"]["formUrl"],isDeleteForm:true});}});</script>
  1. Click event on html element instantiated withmodalForm opens modal
  2. Form atformURL is appended to the modal
  3. On submit the form is POSTed via AJAX request toformURL
  4. Unsuccessful POST request returns errors, which are shown in modal
  5. Successful POST request submits the form and redirects tosuccess_url and showssuccess_message, which are both defined in related Django view

Usage

1. Form

Define BookModelForm and inherit built-in formBSModalModelForm.

forms.pyfrom .modelsimportBookfrombootstrap_modal_forms.formsimportBSModalModelFormclassBookModelForm(BSModalModelForm):classMeta:model=Bookfields= ['title','author','price']

2. Form's html

Define form's html and save it as Django template.

  • Form will POST toformURL defined in #6.
  • Addclass="invalid" or customerrorClass (see paragraphOptions) to the elements that wrap the fields
  • class="invalid" acts as a flag for the fields having errors after the form has been POSTed.
  • IMPORTANT NOTE: Bootstrap 4 modal elements are used in this example.class="invalid" is the default for Bootstrap 4.class="is-invalid" is the default for Bootstrap 5.
book/create_book.html<formmethod="post"action="">  {% csrf_token %}<divclass="modal-header"><h5class="modal-title">Create new Book</h5><buttontype="button"class="close"data-dismiss="modal"aria-label="Close"><spanaria-hidden="true">&times;</span></button></div><divclass="modal-body">    {% for field in form %}<divclass="form-group{% if field.errors %} invalid{% endif %}"><labelfor="{{ field.id_for_label }}">{{ field.label }}</label>        {{ field }}        {% for error in field.errors %}<pclass="help-block">{{ error }}</p>        {% endfor %}</div>    {% endfor %}</div><divclass="modal-footer"><buttontype="button"class="btn btn-default"data-dismiss="modal">Close</button><buttontype="submit"class="btn btn-primary">Create</button></div></form>

3. Function-based view

Whilst django-boostrap-modal-forms is primarily designed for class based usage (see below), there may be reasons you wantto use its capabilities in classic function based views. To use them properly, you need to understand what exactly is going onand how you can adapt this mechanic into your own view.

Your regular function based view might look like this

...ifrequest.method=='POST':# do stuffelifrequest.method=='GET':# do other stuffelse:raiseNotImplementedError('No stuff')...

As you continue to develop your logic, you may see, that two POST requests are being send on your forms, even tho, the user only submitted it once:- Thefirst request can be used to verify your form's validity, let's call it the ajax request (you will see why).- Thesecond request can be used to save your form's data (depending on whether the validation was successful or not)

But how do you differentiate between these two requests? Using this handy method: is_ajax (

)

So, your code may now look like this and is capable of handling both POST requests:

...ifrequest.method=="POST":ifform.is_valid():ifnotis_ajax(request.META):form.save()messages.success(request,msg_success            )returnHttpResponseRedirect(redirect_url)...

4. Class-based view

Define a class-based view BookCreateView and inherit from built-in generic viewBSModalCreateView. BookCreateView processes the form defined in #1, uses the template defined in #2 and redirects tosuccess_url showingsuccess_message.

views.pyfromdjango.urlsimportreverse_lazyfrom .formsimportBookModelFormfrom .modelsimportBookfrombootstrap_modal_forms.genericimportBSModalCreateViewclassBookCreateView(BSModalCreateView):template_name='examples/create_book.html'form_class=BookModelFormsuccess_message='Success: Book was created.'success_url=reverse_lazy('index')

5. URL for the view

Define URL for the view in #3.

fromdjango.urlsimportpathfrombooksimportviewsurlpatterns= [path('',views.Index.as_view(),name='index'),path('create/',views.BookCreateView.as_view(),name='create_book'),]

6. Bootstrap modal and trigger element

Define the Bootstrap modal window and html element triggering modal opening.

  • Single modal can be used for multiplemodalForms in single template (see #6).
  • When usingmultiple modals on the same page each modal should have uniqueid and the same value should also be set asmodalID option when instantiatingmodalForm on trigger element.
  • Trigger element (in this example button withid="create-book") is used for instantiation ofmodalForm in #6.
  • Any element can be trigger element as long asmodalForm is bound to it.
  • Click event on trigger element loads form's html from #2 within<div></div> and sets action attribute of the form toformURL set in #6.
index.html<divclass="modal fade"tabindex="-1"role="dialog"id="modal">  <divclass="modal-dialog"role="document">    <divclass="modal-content"></div>  </div></div><!-- Create book button--><buttonid="create-book"class="btn btn-primary"type="button"name="button">Create book</button>

7. modalForm

Add script to the template from #5 and bind themodalForm to the trigger element. Set BookCreateView URL defined in #4 asformURL property ofmodalForm.

  • If you want to createmore modalForms in single template using the single modal window from #5, repeat steps #1 to #4, create new trigger element as in #5 and bind the newmodalForm with unique URL to it.
  • Default values formodalID,modalContent,modalForm anderrorClass are used in this example, whileformURL is customized. If you customize any other option adjust the code of the above examples accordingly.
index.html<scripttype="text/javascript">// BS4$(document).ready(function(){$("#create-book").modalForm({formURL:"{% url 'create_book' %}"});});// BS5document.addEventListener('DOMContentLoaded',(e)=>{modalForm(document.getElementById('create-book'),{formURL:"{% url 'create_book' %}"})});</script>

Async create/update with or without modal closing on submit

SetasyncUpdate andasyncSettings settings to create or update objects without page redirection tosuccessUrl and define whether a modal should close or stay opened after form submission. See comments in example below and paragraphmodalForm options for explanation ofasyncSettings.See examples on how to properly reinstantiate modal forms for all CRUD buttons when using async options.

index.html<!-- asyncSettings.dataElementId --><tableid="books-table"class="table"><thead>    ...</thead><tbody>  {% for book in books %}<tr>        ...<!-- Update book buttons --><buttontype="button"class="update-book btn btn-sm btn-primary"data-form-url="{% url 'update_book' book.pk %}"><spanclass="fa fa-pencil"></span></button>        ...</td></tr>  {% endfor %}</tbody></table><scripttype="text/javascript">$(function(){        ...        #asyncSettings.successMessagevarasyncSuccessMessage=["<div ","style='position:fixed;top:0;z-index:10000;width:100%;border-radius:0;' ","class='alert alert-icon alert-success alert-dismissible fade show mb-0' role='alert'>","Success: Book was updated.","<button type='button' class='close' data-dismiss='alert' aria-label='Close'>","<span aria-hidden='true'>&times;</span>","</button>","</div>","<script>","$('.alert').fadeTo(2000, 500).slideUp(500, function () {$('.alert').slideUp(500).remove();});","<\/script>"].join();        #asyncSettings.addModalFormFunctionfunctionupdateBookModalForm(){$(".update-book").each(function(){$(this).modalForm({formURL:$(this).data("form-url"),asyncUpdate:true,asyncSettings:{closeOnSubmit:false,successMessage:asyncSuccessMessagedataUrl:"books/",dataElementId:"#books-table",dataKey:"table",addModalFormFunction:updateBookModalForm}});});}updateBookModalForm();        ...});</script>
urls.pyfromdjango.urlsimportpathfrom .importviewsurlpatterns= [    ...# asyncSettings.dataUrlpath('books/',views.books,name='books'),    ...]
views.pyfromdjango.httpimportJsonResponsefromdjango.template.loaderimportrender_to_stringfrom .modelsimportBookdefbooks(request):data=dict()ifrequest.method=='GET':books=Book.objects.all()# asyncSettings.dataKey = 'table'data['table']=render_to_string('_books_table.html',            {'books':books},request=request        )returnJsonResponse(data)

modalForm options

modalID
Sets the custom id of the modal.Default: "#modal"
modalContent
Sets the custom class of the element to which the form's html is appended. If you changemodalContent to the custom class, you should also changemodalForm accordingly. To keep Bootstrap's modal style you should than copy Bootstrap's style formodal-content and set it to your new modalContent class.Default: ".modal-content"
modalForm
Sets the custom form selector.Default: ".modal-content form"
formURL
Sets the url of the form's view and html.Default: null
isDeleteForm
Defines if form is used for deletion. Should be set totrue for deletion forms.Default: false
errorClass
Sets the custom class for the form fields having errors.Default: ".invalid" for Boostrap 4 and ".is-invalid" for Bootstrap 5.
asyncUpdate
Sets asynchronous content update after form submission.Default: false
asyncSettings.closeOnSubmit
Sets whether modal closes or not after form submission.Default: false
asyncSettings.successMessage
Sets successMessage shown after succesful for submission. Should be set to string defining message element. SeeasyncSuccessMessage example above.Default: null
asyncSettings.dataUrl
Sets url of the view returning new queryset = all of the objects plus newly created or updated one after asynchronous update.Default: null
asyncSettings.dataElementId
Sets theid of the element which rerenders asynchronously updated queryset.Default: null
asyncSettings.dataKey
Sets the key containing asynchronously updated queryset in the data dictionary returned from the view providing updated queryset.Default: null
asyncSettings.addModalFormFunction
Sets the method needed for reinstantiation of event listeners on buttons (single or all CRUD buttons) after asynchronous update.Default: null

modalForm default settings object and it's structure

triggerElement.modalForm({    modalID: "#modal",    modalContent: ".modal-content",    modalForm: ".modal-content form",    formURL: null,    isDeleteForm: false,    // ".invalid" is the default for Bootstrap 4. ".is-invalid" is the default for Bootstrap 5.    errorClass: ".invalid",    asyncUpdate: false,    asyncSettings: {        closeOnSubmit: false,        successMessage: null,        dataUrl: null,        dataElementId: null,        dataKey: null,        addModalFormFunction: null    }});

Forms

Import forms withfrom bootstrap_modal_forms.forms import BSModalForm.

BSModalForm
Inherits PopRequestMixin and Django's forms.Form.
BSModalModelForm
Inherits PopRequestMixin, CreateUpdateAjaxMixin and Django's forms.ModelForm.

Mixins

Import mixins withfrom bootstrap_modal_forms.mixins import PassRequestMixin.

PassRequestMixin
Form Mixin which puts the request into the form's kwargs. Note: Using this mixin requires you to pop the request kwarg out of the dict in the super of your form's __init__. See PopRequestMixin.
PopRequestMixin
Form Mixin which pops request out of the kwargs and attaches it to the form's instance. Note: This mixin must precede forms.ModelForm/forms.Form. The form is not expecting these kwargs to be passed in, so they must be popped off before anything else is done.
CreateUpdateAjaxMixin
ModelForm Mixin which passes or saves object based on request type.
DeleteMessageMixin
Generic View Mixin which adds message to BSModalDeleteView and only calls the post method if request is not ajax request. In case request is ajax post method calls delete method, which redirects to success url.
FormValidationMixin
Generic View Mixin which saves object and redirects to success_url if request is not ajax request. Otherwise response 204 No content is returned.
LoginAjaxMixin
Generic View Mixin which authenticates user if request is not ajax request.

Generic views

Import generic views withfrom bootstrap_modal_forms.generic import BSModalFormView.

BSModalLoginView
Inhertis LoginAjaxMixin and Django's LoginView.
BSModalFormView
Inherits PassRequestMixin and Django's generic.FormView.
BSModalCreateView
Inherits PassRequestMixin, FormValidationMixin and generic.CreateView.
BSModalUpdateView
Inherits PassRequestMixin, FormValidationMixin and generic.UpdateView.
BSModalReadView
Inherits Django's generic.DetailView.
BSModalDeleteView
Inherits DeleteMessageMixin and Django's generic.DeleteView.

Examples

To seedjango-bootstrap-modal-forms in action clone the repository and run the examples locally:

$ git clone https://github.com/trco/django-bootstrap-modal-forms.git$ cd django-bootstrap-modal-forms$ pip install -r requirements.txt$ python manage.py migrate$ python manage.py runserver

Example 1: Signup form in Bootstrap modal

For explanation how all the parts of the code work together see paragraphUsage. To test the working solution presented here clone and runExamples.

forms.pyfromdjango.contrib.auth.formsimportUserCreationFormfromdjango.contrib.auth.modelsimportUserfrombootstrap_modal_forms.mixinsimportPopRequestMixin,CreateUpdateAjaxMixinclassCustomUserCreationForm(PopRequestMixin,CreateUpdateAjaxMixin,UserCreationForm):classMeta:model=Userfields= ['username','password1','password2']
signup.html{% load widget_tweaks %}<formmethod="post"action="">  {% csrf_token %}<divclass="modal-header"><h3class="modal-title">Sign up</h3><buttontype="button"class="close"data-dismiss="modal"aria-label="Close"><spanaria-hidden="true">&times;</span></button></div><divclass="modal-body"><divclass="{% if form.non_field_errors %}invalid{% endif %} mb-2">      {% for error in form.non_field_errors %}        {{ error }}      {% endfor %}</div>    {% for field in form %}<divclass="form-group"><labelfor="{{ field.id_for_label }}">{{ field.label }}</label>        {% render_field field placeholder=field.label %}<divclass="{% if field.errors %} invalid{% endif %}">          {% for error in field.errors %}<pclass="help-block">{{ error }}</p>          {% endfor %}</div></div>    {% endfor %}</div><divclass="modal-footer"><buttontype="submit"class="btn btn-primary">Sign up</button></div></form>
views.pyfromdjango.urlsimportreverse_lazyfrombootstrap_modal_forms.genericimportBSModalCreateViewfrom .formsimportCustomUserCreationFormclassSignUpView(BSModalCreateView):form_class=CustomUserCreationFormtemplate_name='examples/signup.html'success_message='Success: Sign up succeeded. You can now Log in.'success_url=reverse_lazy('index')
urls.pyfromdjango.urlsimportpathfrom .importviewsapp_name='accounts'urlpatterns= [path('signup/',views.SignUpView.as_view(),name='signup')]
.html file containing modal, trigger element and script instantiating modalForm<divclass="modal fade"tabindex="-1"role="dialog"id="modal"><divclass="modal-dialog"role="document"><divclass="modal-content"></div></div></div><buttonid="signup-btn"class="btn btn-primary"type="button"name="button">Sign up</button><scripttype="text/javascript">$(function(){// Sign up button$("#signup-btn").modalForm({formURL:"{% url 'signup' %}"});});</script>

Example 2: Login form in Bootstrap modal

For explanation how all the parts of the code work together see paragraphUsage. To test the working solution presented here clone and runExamples.

You can set the login redirection by setting theLOGIN_REDIRECT_URL insettings.py.

You can also set the custom login redirection by:

  1. Addingsuccess_url to theextra_context ofCustomLoginView
  2. Setting thissuccess_url variable as a value of thehidden input field withname="next" within the Login form html
forms.pyfromdjango.contrib.auth.formsimportAuthenticationFormfromdjango.contrib.auth.modelsimportUserclassCustomAuthenticationForm(AuthenticationForm):classMeta:model=Userfields= ['username','password']
login.html{% load widget_tweaks %}<formmethod="post"action="">  {% csrf_token %}<divclass="modal-header"><h3class="modal-title">Log in</h3><buttontype="button"class="close"data-dismiss="modal"aria-label="Close"><spanaria-hidden="true">&times;</span></button></div><divclass="modal-body"><divclass="{% if form.non_field_errors %}invalid{% endif %} mb-2">      {% for error in form.non_field_errors %}        {{ error }}      {% endfor %}</div>    {% for field in form %}<divclass="form-group"><labelfor="{{ field.id_for_label }}">{{ field.label }}</label>        {% render_field field placeholder=field.label %}<divclass="{% if field.errors %} invalid{% endif %}">          {% for error in field.errors %}<pclass="help-block">{{ error }}</p>          {% endfor %}</div></div>    {% endfor %}<!-- Hidden input field for custom redirection after successful login --><inputtype="hidden"name="next"value="{{ success_url }}"></div><divclass="modal-footer"><buttontype="submit"class="btn btn-primary">Log in</button></div></form>
views.pyfromdjango.urlsimportreverse_lazyfrombootstrap_modal_forms.genericimportBSModalLoginViewfrom .formsimportCustomAuthenticationFormclassCustomLoginView(BSModalLoginView):authentication_form=CustomAuthenticationFormtemplate_name='examples/login.html'success_message='Success: You were successfully logged in.'extra_context=dict(success_url=reverse_lazy('index'))
urls.pyfromdjango.urlsimportpathfrom .importviewsapp_name='accounts'urlpatterns= [path('login/',views.CustomLoginView.as_view(),name='login')]
.html file containing modal, trigger element and script instantiating modalForm<divclass="modal fade"tabindex="-1"role="dialog"id="modal"><divclass="modal-dialog"role="document"><divclass="modal-content"></div></div></div><buttonid="login-btn"class="btn btn-primary"type="button"name="button">Sign up</button><scripttype="text/javascript">$(function(){// Log in button$("#login-btn").modalForm({formURL:"{% url 'login' %}"});});</script>

Example 3: Django's forms.ModelForm (CRUD forms) in Bootstrap modal

For explanation how all the parts of the code work together see paragraphUsage. To test the working solution presented here clone and runExamples.

forms.pyfrom .modelsimportBookfrombootstrap_modal_forms.formsimportBSModalModelFormclassBookModelForm(BSModalModelForm):classMeta:model=Bookexclude= ['timestamp']
create_book.html{% load widget_tweaks %}<formmethod="post"action="">  {% csrf_token %}<divclass="modal-header"><h3class="modal-title">Create Book</h3><buttontype="button"class="close"data-dismiss="modal"aria-label="Close"><spanaria-hidden="true">&times;</span></button></div><divclass="modal-body"><divclass="{% if form.non_field_errors %}invalid{% endif %} mb-2">      {% for error in form.non_field_errors %}        {{ error }}      {% endfor %}</div>    {% for field in form %}<divclass="form-group"><labelfor="{{ field.id_for_label }}">{{ field.label }}</label>        {% render_field field placeholder=field.label %}<divclass="{% if field.errors %} invalid{% endif %}">          {% for error in field.errors %}<pclass="help-block">{{ error }}</p>          {% endfor %}</div></div>    {% endfor %}</div><divclass="modal-footer"><buttontype="submit"class="btn btn-primary">Create</button></div></form>
update_book.html{% load widget_tweaks %}<formmethod="post"action="">  {% csrf_token %}<divclass="modal-header"><h3class="modal-title">Update Book</h3><buttontype="button"class="close"data-dismiss="modal"aria-label="Close"><spanaria-hidden="true">&times;</span></button></div><divclass="modal-body"><divclass="{% if form.non_field_errors %}invalid{% endif %} mb-2">      {% for error in form.non_field_errors %}        {{ error }}      {% endfor %}</div>    {% for field in form %}<divclass="form-group"><labelfor="{{ field.id_for_label }}">{{ field.label }}</label>        {% render_field field placeholder=field.label %}<divclass="{% if field.errors %} invalid{% endif %}">          {% for error in field.errors %}<pclass="help-block">{{ error }}</p>          {% endfor %}</div></div>    {% endfor %}</div><divclass="modal-footer"><buttontype="submit"class="btn btn-primary">Update</button></div></form>
read_book.html{% load widget_tweaks %}<divclass="modal-header"><h3class="modal-title">Book details</h3><buttontype="button"class="close"data-dismiss="modal"aria-label="Close"><spanaria-hidden="true">&times;</span></button></div><divclass="modal-body"><divclass="">    Title: {{ book.title }}</div><divclass="">    Author: {{ book.author }}</div><divclass="">    Price: {{ book.price }} €</div></div><divclass="modal-footer"><buttontype="button"class="btn btn-default"data-dismiss="modal">Close</button></div>
{% load widget_tweaks %}<formmethod="post"action="">  {% csrf_token %}<divclass="modal-header"><h3class="modal-title">Delete Book</h3><buttontype="button"class="close"data-dismiss="modal"aria-label="Close"><spanaria-hidden="true">&times;</span></button></div><divclass="modal-body"><p>Are you sure you want to delete book with title<strong>{{ book.title }}</strong>?</p></div><divclass="modal-footer"><buttontype="submit"class="btn btn-danger">Delete</button></div></form>
views.pyfromdjango.urlsimportreverse_lazyfromdjango.viewsimportgenericfrom .formsimportBookModelFormfrom .modelsimportBookfrombootstrap_modal_forms.genericimport (BSModalCreateView,BSModalUpdateView,BSModalReadView,BSModalDeleteView)classIndex(generic.ListView):model=Bookcontext_object_name='books'template_name='index.html'# CreateclassBookCreateView(BSModalCreateView):template_name='examples/create_book.html'form_class=BookModelFormsuccess_message='Success: Book was created.'success_url=reverse_lazy('index')# UpdateclassBookUpdateView(BSModalUpdateView):model=Booktemplate_name='examples/update_book.html'form_class=BookModelFormsuccess_message='Success: Book was updated.'success_url=reverse_lazy('index')# ReadclassBookReadView(BSModalReadView):model=Booktemplate_name='examples/read_book.html'# DeleteclassBookDeleteView(BSModalDeleteView):model=Booktemplate_name='examples/delete_book.html'success_message='Success: Book was deleted.'success_url=reverse_lazy('index')
urls.pyfromdjango.urlsimportpathfrombooksimportviewsurlpatterns= [path('',views.Index.as_view(),name='index'),path('create/',views.BookCreateView.as_view(),name='create_book'),path('update/<int:pk>',views.BookUpdateView.as_view(),name='update_book'),path('read/<int:pk>',views.BookReadView.as_view(),name='read_book'),path('delete/<int:pk>',views.BookDeleteView.as_view(),name='delete_book')]
.html file containing modal, trigger elements and script instantiating modalForms<!-- Modal 1 with--><divclass="modal fade"id="create-modal"tabindex="-1"role="dialog"aria-hidden="true"><divclass="modal-dialog"><divclass="modal-content"></div></div></div><!-- Modal 2 with --><divclass="modal fade"tabindex="-1"role="dialog"id="modal"><divclass="modal-dialog"role="document"><divclass="modal-content"></div></div></div><!-- Create book button --><buttonid="create-book"class="btn btn-primary"type="button"name="button">Create book</button>{% for book in books %}<divclass="text-center"><!-- Read book buttons --><buttontype="button"class="read-book bs-modal btn btn-sm btn-primary"data-form-url="{% url 'read_book' book.pk %}"><spanclass="fa fa-eye"></span></button><!-- Update book buttons --><buttontype="button"class="update-book bs-modal btn btn-sm btn-primary"data-form-url="{% url 'update_book' book.pk %}"><spanclass="fa fa-pencil"></span></button><!-- Delete book buttons --><buttontype="button"class="delete-book bs-modal btn btn-sm btn-danger"data-form-url="{% url 'delete_book' book.pk %}"><spanclass="fa fa-trash"></span></button></div>{% endfor %}<scripttype="text/javascript">$(function(){// Read book buttons$(".read-book").each(function(){$(this).modalForm({formURL:$(this).data("form-url")});});// Delete book buttons - formURL is retrieved from the data of the element$(".delete-book").each(function(){$(this).modalForm({formURL:$(this).data("form-url"),isDeleteForm:true});});// Create book button opens form in modal with$("#create-book").modalForm({formURL:"{% url 'create_book' %}",modalID:"#create-modal"});});</script>
  • See the difference between button triggering Create action and buttons triggering Read, Update and Delete actions.
  • Within the for loop in .html file thedata-form-url attribute of each Update, Read and Delete button should be set to relevant URL with pk argument of the object to be updated, read or deleted.
  • Thesedata-form-url URLs should than be set asformURLs formodalForms bound to the buttons.

Example 4: Django's forms.Form in Bootstrap modal

For explanation how all the parts of the code work together see paragraphUsage. To test the working solution presented here clone and runExamples.

forms.pyfrombootstrap_modal_forms.formsimportBSModalFormclassBookFilterForm(BSModalForm):type=forms.ChoiceField(choices=Book.BOOK_TYPES)classMeta:fields= ['type']
filter_book.html{% load widget_tweaks %}<formmethod="post"action="">  {% csrf_token %}<divclass="modal-header"><h3class="modal-title">Filter Books</h3><buttontype="button"class="close"data-dismiss="modal"aria-label="Close"><spanaria-hidden="true">&times;</span></button></div><divclass="modal-body"><divclass="{% if form.non_field_errors %}invalid{% endif %} mb-2">      {% for error in form.non_field_errors %}        {{ error }}      {% endfor %}</div>    {% for field in form %}<divclass="form-group"><labelfor="{{ field.id_for_label }}">{{ field.label }}</label>        {% render_field field placeholder=field.label %}<divclass="{% if field.errors %} invalid{% endif %}">          {% for error in field.errors %}<pclass="help-block">{{ error }}</p>          {% endfor %}</div></div>    {% endfor %}</div><divclass="modal-footer"><buttontype="submit"class="btn btn-primary">Filter</button></div></form>
views.pyclassBookFilterView(BSModalFormView):template_name='examples/filter_book.html'form_class=BookFilterFormdefform_valid(self,form):self.filter='?type='+form.cleaned_data['type']response=super().form_valid(form)returnresponsedefget_success_url(self):returnreverse_lazy('index')+self.filter
urls.pyfromdjango.urlsimportpathfrom .importviewsapp_name='accounts'urlpatterns= [path('filter/',views.BookFilterView.as_view(),name='filter_book'),]
index.html  ...<buttonid="filter-book"class="filter-book btn btn-primary"type="button"name="button"data-form-url="{% url 'filter_book' %}"><spanclass="fa fa-filter mr-2"></span>Filter books</button>  ...<scripttype="text/javascript">$(function(){      ...$("#filter-book").each(function(){$(this).modalForm({formURL:$(this).data('form-url')});});      ...});</script>

License

This project is licensed under the MIT License.

Packages

No packages published

Contributors10


[8]ページ先頭

©2009-2025 Movatter.jp