Standardized "save and add/continue" functions

This commit is contained in:
Jeremy Stretch 2018-08-13 12:37:57 -04:00
parent 2a6e0c178f
commit d6443f7b37
6 changed files with 74 additions and 11 deletions

View File

@ -5,7 +5,7 @@ from django.contrib.auth.decorators import permission_required
from django.contrib.auth.mixins import PermissionRequiredMixin from django.contrib.auth.mixins import PermissionRequiredMixin
from django.db import transaction from django.db import transaction
from django.db.models import Count from django.db.models import Count
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render, reverse
from django.views.generic import View from django.views.generic import View
from extras.models import Graph, GRAPH_TYPE_PROVIDER from extras.models import Graph, GRAPH_TYPE_PROVIDER
@ -261,6 +261,7 @@ class CircuitTerminationCreateView(PermissionRequiredMixin, ObjectEditView):
model = CircuitTermination model = CircuitTermination
model_form = forms.CircuitTerminationForm model_form = forms.CircuitTerminationForm
template_name = 'circuits/circuittermination_edit.html' template_name = 'circuits/circuittermination_edit.html'
enable_add_another = False
def alter_obj(self, obj, request, url_args, url_kwargs): def alter_obj(self, obj, request, url_args, url_kwargs):
if 'circuit' in url_kwargs: if 'circuit' in url_kwargs:

View File

@ -452,6 +452,9 @@ class RackReservationCreateView(PermissionRequiredMixin, ObjectEditView):
def get_return_url(self, request, obj): def get_return_url(self, request, obj):
return obj.rack.get_absolute_url() return obj.rack.get_absolute_url()
def get_add_url(self, obj):
return reverse('dcim:rack_add_reservation', kwargs={'rack': obj.rack.pk})
class RackReservationEditView(RackReservationCreateView): class RackReservationEditView(RackReservationCreateView):
permission_required = 'dcim.change_rackreservation' permission_required = 'dcim.change_rackreservation'

View File

@ -195,6 +195,7 @@ class ImageAttachmentEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'extras.change_imageattachment' permission_required = 'extras.change_imageattachment'
model = ImageAttachment model = ImageAttachment
model_form = ImageAttachmentForm model_form = ImageAttachmentForm
enable_add_another = False
def alter_obj(self, imageattachment, request, args, kwargs): def alter_obj(self, imageattachment, request, args, kwargs):
if not imageattachment.pk: if not imageattachment.pk:

View File

@ -983,6 +983,7 @@ class ServiceCreateView(PermissionRequiredMixin, ObjectEditView):
model = Service model = Service
model_form = forms.ServiceForm model_form = forms.ServiceForm
template_name = 'ipam/service_edit.html' template_name = 'ipam/service_edit.html'
enable_add_another = False
def alter_obj(self, obj, request, url_args, url_kwargs): def alter_obj(self, obj, request, url_args, url_kwargs):
if 'device' in url_kwargs: if 'device' in url_kwargs:

View File

@ -35,13 +35,25 @@
<div class="col-md-3"> <div class="col-md-3">
<div style="position: fixed"> <div style="position: fixed">
{% block buttons %} {% block buttons %}
{% if obj.pk %} <div class="btn-group">
<p><button type="submit" name="_save" class="btn btn-success"><i class="fa fa-save"></i> Save</button></p> <button type="submit" class="btn btn-primary">
{% else %} <i class="fa fa-save"></i> Save
<p><button type="submit" name="_create" class="btn btn-success"><i class="fa fa-plus"></i> Create</button></p> </button>
<p><button type="submit" name="_addanother" class="btn btn-primary"><i class="fa fa-plus"></i> Create and Add Another</button></p> <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{% endif %} <span class="caret"></span>
<p><a href="{{ return_url }}" class="btn btn-default"><i class="fa fa-ban"></i> Cancel</a></p> </button>
<ul class="dropdown-menu">
<li>
<button type="submit" name="_continue" class="btn btn-link">Save and Continue Editing</button>
{% if enable_add_another %}
<button type="submit" name="_addanother" class="btn btn-link">Save and Add Another</button>
{% endif %}
</li>
</ul>
</div>
<div style="margin-top: 12px">
<a href="{{ return_url }}" class="btn btn-default"><i class="fa fa-ban"></i> Cancel</a>
</div>
{% endblock %} {% endblock %}
</div> </div>
</div> </div>

View File

@ -15,7 +15,7 @@ from django.http import HttpResponseServerError
from django.shortcuts import get_object_or_404, redirect, render from django.shortcuts import get_object_or_404, redirect, render
from django.template import loader from django.template import loader
from django.template.exceptions import TemplateDoesNotExist, TemplateSyntaxError from django.template.exceptions import TemplateDoesNotExist, TemplateSyntaxError
from django.urls import reverse from django.urls import NoReverseMatch, reverse
from django.utils.html import escape from django.utils.html import escape
from django.utils.http import is_safe_url from django.utils.http import is_safe_url
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
@ -171,10 +171,14 @@ class ObjectEditView(GetReturnURLMixin, View):
model: The model of the object being edited model: The model of the object being edited
model_form: The form used to create or edit the object model_form: The form used to create or edit the object
template_name: The name of the template template_name: The name of the template
enable_continue_editing: Enable the option to save and continue editing the object
enable_add_another: Enable the option to save the object and create another
""" """
model = None model = None
model_form = None model_form = None
template_name = 'utilities/obj_edit.html' template_name = 'utilities/obj_edit.html'
enable_continue_editing = True
enable_add_another = True
def get_object(self, kwargs): def get_object(self, kwargs):
# Look up object by slug or PK. Return None if neither was provided. # Look up object by slug or PK. Return None if neither was provided.
@ -189,6 +193,36 @@ class ObjectEditView(GetReturnURLMixin, View):
# given some parameter from the request URL. # given some parameter from the request URL.
return obj return obj
def get_edit_url(self, obj):
"""
Return the URL for editing an existing object (used for "save and continue editing" button).
"""
url_name = '{}:{}_edit'.format(
self.model._meta.app_label,
self.model._meta.model_name
)
if hasattr(obj, 'slug'):
kwargs = {'slug': obj.slug}
else:
kwargs = {'pk': obj.pk}
try:
return reverse(url_name, kwargs=kwargs)
except NoReverseMatch:
return None
def get_add_url(self, obj):
"""
Return the URL for creating a new object (used for "save and add another" button).
"""
url_name = '{}:{}_add'.format(
self.model._meta.app_label,
self.model._meta.model_name
)
try:
return reverse(url_name)
except NoReverseMatch:
return None
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
obj = self.get_object(kwargs) obj = self.get_object(kwargs)
@ -201,6 +235,8 @@ class ObjectEditView(GetReturnURLMixin, View):
'obj': obj, 'obj': obj,
'obj_type': self.model._meta.verbose_name, 'obj_type': self.model._meta.verbose_name,
'form': form, 'form': form,
'enable_continue_editing': self.enable_continue_editing,
'enable_add_another': self.enable_add_another,
'return_url': self.get_return_url(request, obj), 'return_url': self.get_return_url(request, obj),
}) })
@ -224,8 +260,17 @@ class ObjectEditView(GetReturnURLMixin, View):
msg = '{} {}'.format(msg, escape(obj)) msg = '{} {}'.format(msg, escape(obj))
messages.success(request, mark_safe(msg)) messages.success(request, mark_safe(msg))
if '_addanother' in request.POST: # Continue editing the current object
return redirect(request.get_full_path()) if '_continue' in request.POST and self.enable_continue_editing:
edit_url = self.get_edit_url(obj)
if edit_url is not None:
return redirect(edit_url)
# Create another object of the same type
elif '_addanother' in request.POST and self.enable_add_another:
add_url = self.get_add_url(obj)
if add_url is not None:
return redirect(add_url)
return_url = form.cleaned_data.get('return_url') return_url = form.cleaned_data.get('return_url')
if return_url is not None and is_safe_url(url=return_url, host=request.get_host()): if return_url is not None and is_safe_url(url=return_url, host=request.get_host()):