|
1 from django.core.xheaders import populate_xheaders |
|
2 from django.template import loader |
|
3 from django import oldforms |
|
4 from django.db.models import FileField |
|
5 from django.contrib.auth.views import redirect_to_login |
|
6 from django.template import RequestContext |
|
7 from django.http import Http404, HttpResponse, HttpResponseRedirect |
|
8 from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured |
|
9 from django.utils.translation import ugettext |
|
10 |
|
11 def create_object(request, model, template_name=None, |
|
12 template_loader=loader, extra_context=None, post_save_redirect=None, |
|
13 login_required=False, follow=None, context_processors=None): |
|
14 """ |
|
15 Generic object-creation function. |
|
16 |
|
17 Templates: ``<app_label>/<model_name>_form.html`` |
|
18 Context: |
|
19 form |
|
20 the form wrapper for the object |
|
21 """ |
|
22 if extra_context is None: extra_context = {} |
|
23 if login_required and not request.user.is_authenticated(): |
|
24 return redirect_to_login(request.path) |
|
25 |
|
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 |
|
42 if request.user.is_authenticated(): |
|
43 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) |
|
60 if not template_name: |
|
61 template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower()) |
|
62 t = template_loader.get_template(template_name) |
|
63 c = RequestContext(request, { |
|
64 'form': form, |
|
65 }, context_processors) |
|
66 for key, value in extra_context.items(): |
|
67 if callable(value): |
|
68 c[key] = value() |
|
69 else: |
|
70 c[key] = value |
|
71 return HttpResponse(t.render(c)) |
|
72 |
|
73 def update_object(request, model, object_id=None, slug=None, |
|
74 slug_field='slug', template_name=None, template_loader=loader, |
|
75 extra_context=None, post_save_redirect=None, |
|
76 login_required=False, follow=None, context_processors=None, |
|
77 template_object_name='object'): |
|
78 """ |
|
79 Generic object-update function. |
|
80 |
|
81 Templates: ``<app_label>/<model_name>_form.html`` |
|
82 Context: |
|
83 form |
|
84 the form wrapper for the object |
|
85 object |
|
86 the original object being edited |
|
87 """ |
|
88 if extra_context is None: extra_context = {} |
|
89 if login_required and not request.user.is_authenticated(): |
|
90 return redirect_to_login(request.path) |
|
91 |
|
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 |
|
116 if request.user.is_authenticated(): |
|
117 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) |
|
132 if not template_name: |
|
133 template_name = "%s/%s_form.html" % (model._meta.app_label, model._meta.object_name.lower()) |
|
134 t = template_loader.get_template(template_name) |
|
135 c = RequestContext(request, { |
|
136 'form': form, |
|
137 template_object_name: object, |
|
138 }, context_processors) |
|
139 for key, value in extra_context.items(): |
|
140 if callable(value): |
|
141 c[key] = value() |
|
142 else: |
|
143 c[key] = value |
|
144 response = HttpResponse(t.render(c)) |
|
145 populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname)) |
|
146 return response |
|
147 |
|
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'): |
|
152 """ |
|
153 Generic object-delete function. |
|
154 |
|
155 The given template will be used to confirm deletetion if this view is |
|
156 fetched using GET; for safty, deletion will only be performed if this |
|
157 view is POSTed. |
|
158 |
|
159 Templates: ``<app_label>/<model_name>_confirm_delete.html`` |
|
160 Context: |
|
161 object |
|
162 the original object being deleted |
|
163 """ |
|
164 if extra_context is None: extra_context = {} |
|
165 if login_required and not request.user.is_authenticated(): |
|
166 return redirect_to_login(request.path) |
|
167 |
|
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) |
|
180 |
|
181 if request.method == 'POST': |
|
182 object.delete() |
|
183 if request.user.is_authenticated(): |
|
184 request.user.message_set.create(message=ugettext("The %(verbose_name)s was deleted.") % {"verbose_name": model._meta.verbose_name}) |
|
185 return HttpResponseRedirect(post_delete_redirect) |
|
186 else: |
|
187 if not template_name: |
|
188 template_name = "%s/%s_confirm_delete.html" % (model._meta.app_label, model._meta.object_name.lower()) |
|
189 t = template_loader.get_template(template_name) |
|
190 c = RequestContext(request, { |
|
191 template_object_name: object, |
|
192 }, context_processors) |
|
193 for key, value in extra_context.items(): |
|
194 if callable(value): |
|
195 c[key] = value() |
|
196 else: |
|
197 c[key] = value |
|
198 response = HttpResponse(t.render(c)) |
|
199 populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname)) |
|
200 return response |