Changeset 7954 for django/branches/newforms-admin/django/views/generic
- Timestamp:
- 07/18/08 16:42:08 (6 months ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/newforms-admin
- Property svnmerge-integrated changed from /django/trunk:1-4345,4350-4357,4359-4365,4371-4372,4374-4377,4380-4386,4388,4390-4391,4400-4402,4404-4408,4410,4412-4419,4426-4427,4430-4432,4434,4441,4443-4444,4446-4447,4450,4452-4453,4455-4458,4476,4503,4546,4564-4569,4580-4586,4617,4630,4641-6390,6392-7950 to /django/trunk:1-4345,4350-4357,4359-4365,4371-4372,4374-4377,4380-4386,4388,4390-4391,4400-4402,4404-4408,4410,4412-4419,4426-4427,4430-4432,4434,4441,4443-4444,4446-4447,4450,4452-4453,4455-4458,4476,4503,4546,4564-4569,4580-4586,4617,4630,4641-6390,6392-7953
django/branches/newforms-admin/django/views/generic/create_update.py
r5918 r7954 1 from django.newforms.models import ModelFormMetaclass, ModelForm 2 from django.template import RequestContext, loader 3 from django.http import Http404, HttpResponse, HttpResponseRedirect 1 4 from django.core.xheaders import populate_xheaders 2 from django.template import loader3 from django import oldforms4 from django.db.models import FileField5 from django.contrib.auth.views import redirect_to_login6 from django.template import RequestContext7 from django.http import Http404, HttpResponse, HttpResponseRedirect8 5 from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured 9 6 from django.utils.translation import ugettext 10 11 def create_object(request, model, template_name=None, 7 from django.contrib.auth.views import redirect_to_login 8 from django.views.generic import GenericViewError 9 10 def deprecate_follow(follow): 11 """ 12 Issues a DeprecationWarning if follow is anything but None. 13 14 The old Manipulator-based forms used a follow argument that is no longer 15 needed for newforms-based forms. 16 """ 17 if follow is not None: 18 import warning 19 msg = ("Generic views have been changed to use newforms, and the" 20 "'follow' argument is no longer used. Please update your code" 21 "to not use the 'follow' argument.") 22 warning.warn(msg, DeprecationWarning, stacklevel=3) 23 24 def apply_extra_context(extra_context, context): 25 """ 26 Adds items from extra_context dict to context. If a value in extra_context 27 is callable, then it is called and the result is added to context. 28 """ 29 for key, value in extra_context.iteritems(): 30 if callable(value): 31 context[key] = value() 32 else: 33 context[key] = value 34 35 def get_model_and_form_class(model, form_class): 36 """ 37 Returns a model and form class based on the model and form_class 38 parameters that were passed to the generic view. 39 40 If ``form_class`` is given then its associated model will be returned along 41 with ``form_class`` itself. Otherwise, if ``model`` is given, ``model`` 42 itself will be returned along with a ``ModelForm`` class created from 43 ``model``. 44 """ 45 if form_class: 46 return form_class._meta.model, form_class 47 if model: 48 # The inner Meta class fails if model = model is used for some reason. 49 tmp_model = model 50 # TODO: we should be able to construct a ModelForm without creating 51 # and passing in a temporary inner class. 52 class Meta: 53 model = tmp_model 54 class_name = model.__name__ + 'Form' 55 form_class = ModelFormMetaclass(class_name, (ModelForm,), {'Meta': Meta}) 56 return model, form_class 57 raise GenericViewError("Generic view must be called with either a model or" 58 " form_class argument.") 59 60 def redirect(post_save_redirect, obj): 61 """ 62 Returns a HttpResponseRedirect to ``post_save_redirect``. 63 64 ``post_save_redirect`` should be a string, and can contain named string- 65 substitution place holders of ``obj`` field names. 66 67 If ``post_save_redirect`` is None, then redirect to ``obj``'s URL returned 68 by ``get_absolute_url()``. If ``obj`` has no ``get_absolute_url`` method, 69 then raise ImproperlyConfigured. 70 71 This method is meant to handle the post_save_redirect parameter to the 72 ``create_object`` and ``update_object`` views. 73 """ 74 if post_save_redirect: 75 return HttpResponseRedirect(post_save_redirect % obj.__dict__) 76 elif hasattr(obj, 'get_absolute_url'): 77 return HttpResponseRedirect(obj.get_absolute_url()) 78 else: 79 raise ImproperlyConfigured( 80 "No URL to redirect to. Either pass a post_save_redirect" 81 " parameter to the generic view or define a get_absolute_url" 82 " method on the Model.") 83 84 def lookup_object(model, object_id, slug, slug_field): 85 """ 86 Return the ``model`` object with the passed ``object_id``. If 87 ``object_id`` is None, then return the the object whose ``slug_field`` 88 equals the passed ``slug``. If ``slug`` and ``slug_field`` are not passed, 89 then raise Http404 exception. 90 """ 91 lookup_kwargs = {} 92 if object_id: 93 lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id 94 elif slug and slug_field: 95 lookup_kwargs['%s__exact' % slug_field] = slug 96 else: 97 raise GenericViewError( 98 "Generic view must be called with either an object_id or a" 99 " slug/slug_field.") 100 try: 101 return model.objects.get(**lookup_kwargs) 102 except ObjectDoesNotExist: 103 raise Http404("No %s found for %s" 104 % (model._meta.verbose_name, lookup_kwargs)) 105 106 def create_object(request, model=None, template_name=None, 12 107 template_loader=loader, extra_context=None, post_save_redirect=None, 13 login_required=False, follow=None, context_processors=None): 108 login_required=False, follow=None, context_processors=None, 109 form_class=None): 14 110 """ 15 111 Generic object-creation function. … … 18 114 Context: 19 115 form 20 the form wrapper for the object 21 """ 116 the form for the object 117 """ 118 deprecate_follow(follow) 22 119 if extra_context is None: extra_context = {} 23 120 if login_required and not request.user.is_authenticated(): 24 121 return redirect_to_login(request.path) 25 122 26 manipulator = model.AddManipulator(follow=follow) 27 if request.POST: 28 # If data was POSTed, we're trying to create a new object 29 new_data = request.POST.copy() 30 31 if model._meta.has_field_type(FileField): 32 new_data.update(request.FILES) 33 34 # Check for errors 35 errors = manipulator.get_validation_errors(new_data) 36 manipulator.do_html2python(new_data) 37 38 if not errors: 39 # No errors -- this means we can save the data! 40 new_object = manipulator.save(new_data) 41 123 model, form_class = get_model_and_form_class(model, form_class) 124 if request.method == 'POST': 125 form = form_class(request.POST, request.FILES) 126 if form.is_valid(): 127 new_object = form.save() 42 128 if request.user.is_authenticated(): 43 129 request.user.message_set.create(message=ugettext("The %(verbose_name)s was created successfully.") % {"verbose_name": model._meta.verbose_name}) 44 45 # Redirect to the new object: first by trying post_save_redirect, 46 # then by obj.get_absolute_url; fail if neither works. 47 if post_save_redirect: 48 return HttpResponseRedirect(post_save_redirect % new_object.__dict__) 49 elif hasattr(new_object, 'get_absolute_url'): 50 return HttpResponseRedirect(new_object.get_absolute_url()) 51 else: 52 raise ImproperlyConfigured("No URL to redirect to from generic create view.") 53 else: 54 # No POST, so we want a brand new form without any data or errors 55 errors = {} 56 new_data = manipulator.flatten_data() 57 58 # Create the FormWrapper, template, context, response 59 form = oldforms.FormWrapper(manipulator, new_data, errors) 130 return redirect(post_save_redirect, new_object) 131 else: 132 form = form_class() 133 134 # Create the template, context, response 60 135 if not template_name: 61 136 template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower()) … … 64 139 'form': form, 65 140 }, context_processors) 66 for key, value in extra_context.items(): 67 if callable(value): 68 c[key] = value() 69 else: 70 c[key] = value 141 apply_extra_context(extra_context, c) 71 142 return HttpResponse(t.render(c)) 72 143 73 def update_object(request, model , object_id=None, slug=None,144 def update_object(request, model=None, object_id=None, slug=None, 74 145 slug_field='slug', template_name=None, template_loader=loader, 75 146 extra_context=None, post_save_redirect=None, 76 147 login_required=False, follow=None, context_processors=None, 77 template_object_name='object' ):148 template_object_name='object', form_class=None): 78 149 """ 79 150 Generic object-update function. … … 82 153 Context: 83 154 form 84 the form wrapperfor the object155 the form for the object 85 156 object 86 157 the original object being edited 87 158 """ 159 deprecate_follow(follow) 88 160 if extra_context is None: extra_context = {} 89 161 if login_required and not request.user.is_authenticated(): 90 162 return redirect_to_login(request.path) 91 163 92 # Look up the object to be edited 93 lookup_kwargs = {} 94 if object_id: 95 lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id 96 elif slug and slug_field: 97 lookup_kwargs['%s__exact' % slug_field] = slug 98 else: 99 raise AttributeError("Generic edit view must be called with either an object_id or a slug/slug_field") 100 try: 101 object = model.objects.get(**lookup_kwargs) 102 except ObjectDoesNotExist: 103 raise Http404, "No %s found for %s" % (model._meta.verbose_name, lookup_kwargs) 104 105 manipulator = model.ChangeManipulator(getattr(object, object._meta.pk.attname), follow=follow) 106 107 if request.POST: 108 new_data = request.POST.copy() 109 if model._meta.has_field_type(FileField): 110 new_data.update(request.FILES) 111 errors = manipulator.get_validation_errors(new_data) 112 manipulator.do_html2python(new_data) 113 if not errors: 114 object = manipulator.save(new_data) 115 164 model, form_class = get_model_and_form_class(model, form_class) 165 obj = lookup_object(model, object_id, slug, slug_field) 166 167 if request.method == 'POST': 168 form = form_class(request.POST, request.FILES, instance=obj) 169 if form.is_valid(): 170 obj = form.save() 116 171 if request.user.is_authenticated(): 117 172 request.user.message_set.create(message=ugettext("The %(verbose_name)s was updated successfully.") % {"verbose_name": model._meta.verbose_name}) 118 119 # Do a post-after-redirect so that reload works, etc. 120 if post_save_redirect: 121 return HttpResponseRedirect(post_save_redirect % object.__dict__) 122 elif hasattr(object, 'get_absolute_url'): 123 return HttpResponseRedirect(object.get_absolute_url()) 124 else: 125 raise ImproperlyConfigured("No URL to redirect to from generic create view.") 126 else: 127 errors = {} 128 # This makes sure the form acurate represents the fields of the place. 129 new_data = manipulator.flatten_data() 130 131 form = oldforms.FormWrapper(manipulator, new_data, errors) 173 return redirect(post_save_redirect, obj) 174 else: 175 form = form_class(instance=obj) 176 132 177 if not template_name: 133 178 template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower()) … … 135 180 c = RequestContext(request, { 136 181 'form': form, 137 template_object_name: obj ect,182 template_object_name: obj, 138 183 }, context_processors) 139 for key, value in extra_context.items(): 140 if callable(value): 141 c[key] = value() 142 else: 143 c[key] = value 184 apply_extra_context(extra_context, c) 144 185 response = HttpResponse(t.render(c)) 145 populate_xheaders(request, response, model, getattr(obj ect, object._meta.pk.attname))186 populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.attname)) 146 187 return response 147 188 148 def delete_object(request, model, post_delete_redirect, 149 object_id=None,slug=None, slug_field='slug', template_name=None,150 template_loader=loader, extra_context=None, 151 login_required=False,context_processors=None, template_object_name='object'):189 def delete_object(request, model, post_delete_redirect, object_id=None, 190 slug=None, slug_field='slug', template_name=None, 191 template_loader=loader, extra_context=None, login_required=False, 192 context_processors=None, template_object_name='object'): 152 193 """ 153 194 Generic object-delete function. … … 166 207 return redirect_to_login(request.path) 167 208 168 # Look up the object to be edited 169 lookup_kwargs = {} 170 if object_id: 171 lookup_kwargs['%s__exact' % model._meta.pk.name] = object_id 172 elif slug and slug_field: 173 lookup_kwargs['%s__exact' % slug_field] = slug 174 else: 175 raise AttributeError("Generic delete view must be called with either an object_id or a slug/slug_field") 176 try: 177 object = model._default_manager.get(**lookup_kwargs) 178 except ObjectDoesNotExist: 179 raise Http404, "No %s found for %s" % (model._meta.app_label, lookup_kwargs) 209 obj = lookup_object(model, object_id, slug, slug_field) 180 210 181 211 if request.method == 'POST': 182 obj ect.delete()212 obj.delete() 183 213 if request.user.is_authenticated(): 184 214 request.user.message_set.create(message=ugettext("The %(verbose_name)s was deleted.") % {"verbose_name": model._meta.verbose_name}) … … 189 219 t = template_loader.get_template(template_name) 190 220 c = RequestContext(request, { 191 template_object_name: obj ect,221 template_object_name: obj, 192 222 }, context_processors) 193 for key, value in extra_context.items(): 194 if callable(value): 195 c[key] = value() 196 else: 197 c[key] = value 223 apply_extra_context(extra_context, c) 198 224 response = HttpResponse(t.render(c)) 199 populate_xheaders(request, response, model, getattr(obj ect, object._meta.pk.attname))225 populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.attname)) 200 226 return response django/branches/newforms-admin/django/views/generic/__init__.py
r4265 r7954 1 class GenericViewError(Exception): 2 """A problem in a generic view.""" 3 pass
