201 lines
8.1 KiB
Python
201 lines
8.1 KiB
Python
from django.core.xheaders import populate_xheaders
|
|
from django.template import loader
|
|
from django import forms
|
|
from django.db.models import FileField
|
|
from django.contrib.auth.views import redirect_to_login
|
|
from django.template import RequestContext
|
|
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
|
from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
|
|
from django.utils.translation import gettext
|
|
|
|
def create_object(request, model, template_name=None,
|
|
template_loader=loader, extra_context=None, post_save_redirect=None,
|
|
login_required=False, follow=None, context_processors=None):
|
|
"""
|
|
Generic object-creation function.
|
|
|
|
Templates: ``<app_label>/<model_name>_form.html``
|
|
Context:
|
|
form
|
|
the form wrapper for the object
|
|
"""
|
|
if extra_context is None: extra_context = {}
|
|
if login_required and not request.user.is_authenticated():
|
|
return redirect_to_login(request.path)
|
|
|
|
manipulator = model.AddManipulator(follow=follow)
|
|
if request.POST:
|
|
# If data was POSTed, we're trying to create a new object
|
|
new_data = request.POST.copy()
|
|
|
|
if model._meta.has_field_type(FileField):
|
|
new_data.update(request.FILES)
|
|
|
|
# Check for errors
|
|
errors = manipulator.get_validation_errors(new_data)
|
|
manipulator.do_html2python(new_data)
|
|
|
|
if not errors:
|
|
# No errors -- this means we can save the data!
|
|
new_object = manipulator.save(new_data)
|
|
|
|
if request.user.is_authenticated():
|
|
request.user.message_set.create(message=gettext("The %(verbose_name)s was created successfully.") % {"verbose_name": model._meta.verbose_name})
|
|
|
|
# Redirect to the new object: first by trying post_save_redirect,
|
|
# then by obj.get_absolute_url; fail if neither works.
|
|
if post_save_redirect:
|
|
return HttpResponseRedirect(post_save_redirect % new_object.__dict__)
|
|
elif hasattr(new_object, 'get_absolute_url'):
|
|
return HttpResponseRedirect(new_object.get_absolute_url())
|
|
else:
|
|
raise ImproperlyConfigured("No URL to redirect to from generic create view.")
|
|
else:
|
|
# No POST, so we want a brand new form without any data or errors
|
|
errors = {}
|
|
new_data = manipulator.flatten_data()
|
|
|
|
# Create the FormWrapper, template, context, response
|
|
form = forms.FormWrapper(manipulator, new_data, errors)
|
|
if not template_name:
|
|
template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower())
|
|
t = template_loader.get_template(template_name)
|
|
c = RequestContext(request, {
|
|
'form': form,
|
|
}, context_processors)
|
|
for key, value in extra_context.items():
|
|
if callable(value):
|
|
c[key] = value()
|
|
else:
|
|
c[key] = value
|
|
return HttpResponse(t.render(c))
|
|
|
|
def update_object(request, model, object_id=None, slug=None,
|
|
slug_field=None, template_name=None, template_loader=loader,
|
|
extra_context=None, post_save_redirect=None,
|
|
login_required=False, follow=None, context_processors=None,
|
|
template_object_name='object'):
|
|
"""
|
|
Generic object-update function.
|
|
|
|
Templates: ``<app_label>/<model_name>_form.html``
|
|
Context:
|
|
form
|
|
the form wrapper for the object
|
|
object
|
|
the original object being edited
|
|
"""
|
|
if extra_context is None: extra_context = {}
|
|
if login_required and not request.user.is_authenticated():
|
|
return redirect_to_login(request.path)
|
|
|
|
# Look up the object to be edited
|
|
lookup_kwargs = {}
|
|
if object_id:
|
|
lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
|
|
elif slug and slug_field:
|
|
lookup_kwargs['%s__exact' % slug_field] = slug
|
|
else:
|
|
raise AttributeError("Generic edit view must be called with either an object_id or a slug/slug_field")
|
|
try:
|
|
object = model.objects.get(**lookup_kwargs)
|
|
except ObjectDoesNotExist:
|
|
raise Http404, "No %s found for %s" % (model._meta.verbose_name, lookup_kwargs)
|
|
|
|
manipulator = model.ChangeManipulator(getattr(object, object._meta.pk.attname), follow=follow)
|
|
|
|
if request.POST:
|
|
new_data = request.POST.copy()
|
|
if model._meta.has_field_type(FileField):
|
|
new_data.update(request.FILES)
|
|
errors = manipulator.get_validation_errors(new_data)
|
|
manipulator.do_html2python(new_data)
|
|
if not errors:
|
|
object = manipulator.save(new_data)
|
|
|
|
if request.user.is_authenticated():
|
|
request.user.message_set.create(message=gettext("The %(verbose_name)s was updated successfully.") % {"verbose_name": model._meta.verbose_name})
|
|
|
|
# Do a post-after-redirect so that reload works, etc.
|
|
if post_save_redirect:
|
|
return HttpResponseRedirect(post_save_redirect % object.__dict__)
|
|
elif hasattr(object, 'get_absolute_url'):
|
|
return HttpResponseRedirect(object.get_absolute_url())
|
|
else:
|
|
raise ImproperlyConfigured("No URL to redirect to from generic create view.")
|
|
else:
|
|
errors = {}
|
|
# This makes sure the form acurate represents the fields of the place.
|
|
new_data = manipulator.flatten_data()
|
|
|
|
form = forms.FormWrapper(manipulator, new_data, errors)
|
|
if not template_name:
|
|
template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower())
|
|
t = template_loader.get_template(template_name)
|
|
c = RequestContext(request, {
|
|
'form': form,
|
|
template_object_name: object,
|
|
}, context_processors)
|
|
for key, value in extra_context.items():
|
|
if callable(value):
|
|
c[key] = value()
|
|
else:
|
|
c[key] = value
|
|
response = HttpResponse(t.render(c))
|
|
populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname))
|
|
return response
|
|
|
|
def delete_object(request, model, post_delete_redirect,
|
|
object_id=None, slug=None, slug_field=None, template_name=None,
|
|
template_loader=loader, extra_context=None,
|
|
login_required=False, context_processors=None, template_object_name='object'):
|
|
"""
|
|
Generic object-delete function.
|
|
|
|
The given template will be used to confirm deletetion if this view is
|
|
fetched using GET; for safty, deletion will only be performed if this
|
|
view is POSTed.
|
|
|
|
Templates: ``<app_label>/<model_name>_confirm_delete.html``
|
|
Context:
|
|
object
|
|
the original object being deleted
|
|
"""
|
|
if extra_context is None: extra_context = {}
|
|
if login_required and not request.user.is_authenticated():
|
|
return redirect_to_login(request.path)
|
|
|
|
# Look up the object to be edited
|
|
lookup_kwargs = {}
|
|
if object_id:
|
|
lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id
|
|
elif slug and slug_field:
|
|
lookup_kwargs['%s__exact' % slug_field] = slug
|
|
else:
|
|
raise AttributeError("Generic delete view must be called with either an object_id or a slug/slug_field")
|
|
try:
|
|
object = model._default_manager.get(**lookup_kwargs)
|
|
except ObjectDoesNotExist:
|
|
raise Http404, "No %s found for %s" % (model._meta.app_label, lookup_kwargs)
|
|
|
|
if request.method == 'POST':
|
|
object.delete()
|
|
if request.user.is_authenticated():
|
|
request.user.message_set.create(message=gettext("The %(verbose_name)s was deleted.") % {"verbose_name": model._meta.verbose_name})
|
|
return HttpResponseRedirect(post_delete_redirect)
|
|
else:
|
|
if not template_name:
|
|
template_name = "%s/%s_confirm_delete.html" % (model._meta.app_label, model._meta.object_name.lower())
|
|
t = template_loader.get_template(template_name)
|
|
c = RequestContext(request, {
|
|
template_object_name: object,
|
|
}, context_processors)
|
|
for key, value in extra_context.items():
|
|
if callable(value):
|
|
c[key] = value()
|
|
else:
|
|
c[key] = value
|
|
response = HttpResponse(t.render(c))
|
|
populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname))
|
|
return response
|