Don't create csv export when no key_order is defined
[Melange.git] / app / soc / views / models / base.py
blob2f8f5771c40dfc0d78aa0f7ee3c0c11266cd5a55
1 #!/usr/bin/python2.5
3 # Copyright 2008 the Melange authors.
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 """Helpers functions for displaying views.
18 """
20 __authors__ = [
21 '"Sverre Rabbelier" <sverre@rabbelier.nl>',
22 '"Lennard de Rijk" <ljvderijk@gmail.com>',
23 '"Pawel Solyga" <pawel.solyga@gmail.com>',
27 import csv
28 import StringIO
30 from google.appengine.ext import db
32 from django import http
33 from django.utils import simplejson
34 from django.utils.translation import ugettext
36 from soc.logic import dicts
37 from soc.views import helper
38 from soc.views import out_of_band
39 from soc.views.helper import decorators
40 from soc.views.helper import forms
41 from soc.views.helper import redirects
42 from soc.views.helper import responses
43 from soc.views import sitemap
45 import soc.cache.logic
46 import soc.logic
47 import soc.logic.lists
48 import soc.views.helper.lists
49 import soc.views.helper.params
52 class View(object):
53 """Views for entity classes.
55 The View class functions specific to Entity classes by relying
56 on the the child-classes to define the following fields:
58 self._logic: the logic singleton for this entity
59 """
61 DEF_CREATE_NEW_ENTITY_MSG_FMT = ugettext(
62 ' You can create a new %(entity_type)s by visiting'
63 ' <a href="%(create)s">Create '
64 'a New %(entity_type)s</a> page.')
66 DEF_CREATE_INSTRUCTION_MSG_FMT = ugettext(
67 'Please select a %s for the new %s.')
69 def __init__(self, params=None):
70 """
72 Args:
73 params: This dictionary should be filled with the parameters
74 specific to this entity. See the methods in this class on
75 the fields it should contain, and how they are used.
76 """
78 self._params = helper.params.constructParams(params)
79 self._logic = params['logic']
81 @decorators.merge_params
82 @decorators.check_access
83 def public(self, request, access_type,
84 page_name=None, params=None, **kwargs):
85 """Displays the public page for the entity specified by **kwargs.
87 Params usage:
88 rights: The rights dictionary is used to check if the user has
89 the required rights to view the public page for this entity.
90 See checkAccess for more details on how the rights dictionary
91 is used to check access rights.
92 error_public: The error_public value is used as template when
93 the key values (as defined by the page's url) do not
94 correspond to an existing entity.
95 name: The name value is used to set the entity_type in the
96 context so that the template can refer to it.
97 public_template: The public_template value is used as template
98 to display the public page of the found entity.
100 Args:
101 request: the standard Django HTTP request object
102 access_type : the name of the access type which should be checked
103 page_name: the page name displayed in templates as page and header title
104 params: a dict with params for this View
105 kwargs: the Key Fields for the specified entity
108 # create default template context for use with any templates
109 context = helper.responses.getUniversalContext(request)
110 helper.responses.useJavaScript(context, params['js_uses_all'])
111 context['page_name'] = page_name
112 entity = None
113 logic = params['logic']
115 if not all(kwargs.values()):
116 #TODO: Change this into a proper redirect
117 return http.HttpResponseRedirect('/')
119 try:
120 entity = logic.getFromKeyFieldsOr404(kwargs)
121 except out_of_band.Error, error:
122 return helper.responses.errorResponse(
123 error, request, template=params['error_public'], context=context)
125 self._public(request, entity, context)
127 context['entity'] = entity
128 context['entity_type'] = params['name']
129 context['entity_type_url'] = params['url_name']
131 context = dicts.merge(params['context'], context)
133 template = params['public_template']
135 return helper.responses.respond(request, template, context=context)
137 @decorators.merge_params
138 @decorators.check_access
139 def admin(self, request, access_type,
140 page_name=None, params=None, **kwargs):
141 """Displays the admin page for the entity specified by **kwargs.
143 Params usage:
144 rights: The rights dictionary is used to check if the user has
145 the required rights to view the public page for this entity.
146 See checkAccess for more details on how the rights dictionary
147 is used to check access rights.
148 name: The name value is used to set the entity_type in the
149 context so that the template can refer to it.
150 public_template: The public_template value is used as template
151 to display the public page of the found entity.
153 Args:
154 request: the standard Django HTTP request object
155 access_type : the name of the access type which should be checked
156 page_name: the page name displayed in templates as page and header title
157 params: a dict with params for this View
158 kwargs: the Key Fields for the specified entity
161 # create default template context for use with any templates
162 context = helper.responses.getUniversalContext(request)
163 helper.responses.useJavaScript(context, params['js_uses_all'])
164 context['page_name'] = page_name
165 logic = params['logic']
167 try:
168 entity = logic.getFromKeyFieldsOr404(kwargs)
169 except out_of_band.Error, error:
170 return helper.responses.errorResponse(error, request, context=context)
172 form = params['admin_form'](instance=entity)
173 template = params['admin_template']
175 return self._constructResponse(request, entity, context, form,
176 params, template=template)
178 @decorators.merge_params
179 @decorators.check_access
180 def export(self, request, access_type,
181 page_name=None, params=None, **kwargs):
182 """Displays the export page for the entity specified by **kwargs.
184 Params usage:
185 rights: The rights dictionary is used to check if the user has
186 the required rights to view the export page for this entity.
187 See checkAccess for more details on how the rights dictionary
188 is used to check access rights.
189 error_export: The error_export value is used as template when
190 the key values (as defined by the page's url) do not
191 correspond to an existing entity.
192 Params is passed to download, refer to it's docstring for more
193 details on how it uses it.
195 Args:
196 request: the standard Django HTTP request object
197 access_type : the name of the access type which should be checked
198 page_name: the page name displayed in templates as page and header title
199 params: a dict with params for this View
200 kwargs: the Key Fields for the specified entity
203 if not ('export_content_type' in params) and ('export_function' in params):
204 return self.public(request, access_type, page_name=page_name,
205 params=params, **kwargs)
207 # create default template context for use with any templates
208 entity = None
209 logic = params['logic']
211 if not all(kwargs.values()):
212 #TODO: Change this into a proper redirect
213 return http.HttpResponseRedirect('/')
215 try:
216 entity = logic.getFromKeyFieldsOr404(kwargs)
217 except out_of_band.Error, error:
218 return helper.responses.errorResponse(
219 error, request, template=params['error_export'])
221 export_function = params['export_function']
222 data, filename = export_function(entity)
224 return self.download(request, data, filename, params)
226 def download(self, request, data, filename, params):
227 """Returns data as a downloadable file with the specified name.
229 Params usage:
230 export_template: The export_template value is used as template
231 to display the export page of the found entity.
232 export_content_type: The export_content_type value is used to set
233 the Content-Type header of the HTTP response. If empty (or None),
234 public() is called instead.
235 export_extension: The export_extension value is used as the suffix
236 of the file that will be offered for download.
238 Args:
239 request: the standard Django HTTP request object
240 data: the data that should be offered as file content
241 filename: the name the file should have
242 params: a dict with params for this View
245 context = {}
246 context['data'] = data
248 template = params['export_template']
250 response_args = {'mimetype': params['export_content_type']}
252 export_extension = params['export_extension']
254 response_headers = {
255 'Content-Disposition': 'attachment; filename=%s%s' % (
256 filename, export_extension),
259 return helper.responses.respond(request, template, context=context,
260 response_args=response_args,
261 response_headers=response_headers)
263 @decorators.check_access
264 def create(self, request, access_type,
265 page_name=None, params=None, **kwargs):
266 """Displays the create page for this entity type.
268 Params usage:
269 The params dictionary is passed on to edit, see the docstring
270 for edit on how it uses it.
272 Args:
273 request: the standard Django HTTP request object
274 access_type : the name of the access type which should be checked
275 page_name: the page name displayed in templates as page and header title
276 params: a dict with params for this View
277 kwargs: not used for create()
280 new_params = dicts.merge(params, self._params)
282 if ('scope_view' in new_params) and ('scope_path' not in kwargs):
283 view = new_params['scope_view'].view
284 redirect = new_params['scope_redirect']
285 return self.select(request, view, redirect,
286 params=params, page_name=page_name, **kwargs)
288 params = new_params
289 logic = params['logic']
291 # Create page is an edit page with no key fields
292 empty_kwargs = {}
293 fields = logic.getKeyFieldNames()
294 for field in fields:
295 empty_kwargs[field] = None
297 return self.edit(request, access_type, page_name=page_name,
298 params=params, seed=kwargs, **empty_kwargs)
300 @decorators.merge_params
301 @decorators.check_access
302 def edit(self, request, access_type,
303 page_name=None, params=None, seed=None, **kwargs):
304 """Displays the edit page for the entity specified by **kwargs.
306 Params usage:
307 The params dictionary is passed on to either editGet or editPost
308 depending on the method type of the request. See the docstring
309 for editGet and editPost on how they use it.
311 rights: The rights dictionary is used to check if the user has
312 the required rights to edit (or create) a new entity.
313 See checkAccess for more details on how the rights dictionary
314 is used to check access rights.
315 name: The name value is used to construct the message_fmt of the
316 raised error when there key_values do not define an existing
317 entity. See DEF_CREATE_NEW_ENTITY_MSG_FMT on how the name
318 (and the lower() version of it) is used.
319 missing_redirect: The missing_redirect value is also used to
320 construct the message_fmt mentioned above.
321 error_public: The error_public value is used as the template for
322 the error response mentioned above.
324 Args:
325 request: the standard Django HTTP request object
326 access_type : the name of the access type which should be checked
327 page_name: the page name displayed in templates as page and header title
328 params: a dict with params for this View
329 kwargs: The Key Fields for the specified entity
332 logic = params['logic']
334 context = helper.responses.getUniversalContext(request)
335 helper.responses.useJavaScript(context, params['js_uses_all'])
336 context['page_name'] = page_name
337 entity = None
339 try:
340 if all(kwargs.values()):
341 entity = logic.getFromKeyFieldsOr404(kwargs)
342 except out_of_band.Error, error:
343 if not seed:
344 error.message_fmt = (
345 error.message_fmt + self.DEF_CREATE_NEW_ENTITY_MSG_FMT % {
346 'entity_type_lower' : params['name'].lower(),
347 'entity_type' : params['name'],
348 'create' : params['missing_redirect']})
349 return helper.responses.errorResponse(
350 error, request, template=params['error_public'], context=context)
352 if request.method == 'POST':
353 return self.editPost(request, entity, context, params=params)
354 else:
355 return self.editGet(request, entity, context, seed, params=params)
357 @decorators.merge_params
358 def editPost(self, request, entity, context, params=None):
359 """Processes POST requests for the specified entity.
361 Params usage:
362 The params dictionary is passed to _constructResponse when the
363 form is not valid (see edit_form and create_form below). See
364 the docstring of _constructResponse on how it uses it.
366 edit_form: The edit_form value is used as form when there is an
367 existing entity. It is provided with with the request.POST
368 dictionary on construction. The collectCleanedFields method
369 is called with the newly constructed form. If the form is
370 not valid, it is passed as argument to _constructResponse.
371 create_form: The create_form value is used in a similar way to
372 edit_form, only it is used when there is no existing entity.
373 edit_redirect: The edit_redirect value is used as the first part
374 of the url if the form was valid. The last part of the url is
375 created using the getKeySuffix method of the _logic object.
376 edit_params: The edit_params dictionary is used as argument to
377 redirectToChangedSuffix, it will be appended to the url in the
378 standard ?key=value format.
380 Args:
381 request: a django request object
382 entity: the entity that will be modified or created, may be None
383 context: the context dictionary that will be provided to Django
384 params: required, a dict with params for this View
387 logic = params['logic']
389 if entity:
390 form = params['edit_form'](request.POST)
391 else:
392 form = params['create_form'](request.POST)
394 if not form.is_valid():
395 return self._constructResponse(request, entity, context, form, params)
397 key_name, fields = forms.collectCleanedFields(form)
399 self._editPost(request, entity, fields)
401 if not key_name:
402 key_name = logic.getKeyNameFromFields(fields)
404 entity = logic.updateOrCreateFromKeyName(fields, key_name)
406 if not entity:
407 return http.HttpResponseRedirect('/')
409 page_params = params['edit_params']
410 params['suffix'] = logic.getKeySuffix(entity)
412 request.path = params['edit_redirect'] % params
414 # redirect to (possibly new) location of the entity
415 # (causes 'Profile saved' message to be displayed)
416 return helper.responses.redirectToChangedSuffix(
417 request, None, params=page_params)
419 @decorators.merge_params
420 def editGet(self, request, entity, context, seed, params=None):
421 """Processes GET requests for the specified entity.
423 Params usage:
424 The params dictionary is passed to _constructResponse, see the
425 docstring of _constructResponse on how it uses it.
427 save_message: The save_message list is used as argument to
428 getSingleIndexedParamValue when an existing entity was saved.
429 edit_form: The edit_form is used as form if there is an existing
430 entity. The existing entity is passed as instance to it on
431 construction. If key_name is part of it's fields it will be
432 set to the entity's key().name() value. It is also passed as
433 argument to the _editGet method. See the docstring for
434 _editGet on how it uses it.
435 create_form: The create_form is used as form if there was no
436 existing entity. If the seed argument is present, it is passed
437 as the 'initial' argument on construction. Otherwise, it is
438 called with no arguments.
439 submit_msg_param_name: The submit_msg_param_name value is used
440 as the key part in the ?key=value construct for the submit
441 message parameter (see also save_message).
443 Args:
444 request: the django request object
445 entity: the entity that will be edited, may be None
446 context: the context dictionary that will be provided to django
447 seed: if no entity is provided, the initial values for the new entity
448 params: required, a dict with params for this View
451 logic = params['logic']
452 suffix = logic.getKeySuffix(entity)
454 # remove the params from the request, this is relevant only if
455 # someone bookmarked a POST page.
456 is_self_referrer = helper.requests.isReferrerSelf(
457 request, suffix=suffix, url_name=params['url_name'])
459 if request.GET.get(params['submit_msg_param_name']):
460 if (not entity) or (not is_self_referrer):
461 return http.HttpResponseRedirect(request.path)
463 if entity:
464 # note: no message will be displayed if parameter is not present
465 context['notice'] = helper.requests.getSingleIndexedParamValue(
466 request, params['submit_msg_param_name'],
467 values=params['save_message'])
469 # populate form with the existing entity
470 form = params['edit_form'](instance=entity)
472 if 'key_name' in form.fields:
473 form.fields['key_name'].initial = entity.key().name()
475 self._editGet(request, entity, form)
476 else:
477 seed = seed if seed else {}
478 dicts.merge(seed, request.GET)
479 self._editSeed(request, seed)
481 if seed:
482 # pass the seed through the context to _constructResponse
483 # it will be popped before dispatching to Django
484 context['seed'] = seed
485 form = params['create_form'](initial=seed)
486 else:
487 form = params['create_form']()
489 return self._constructResponse(request, entity, context, form, params)
491 @decorators.merge_params
492 @decorators.check_access
493 def list(self, request, access_type,
494 page_name=None, params=None, filter=None, order=None, **kwargs):
495 """Displays the list page for the entity type.
497 Args:
498 request: the standard Django HTTP request object
499 access_type : the name of the access type which should be checked
500 page_name: the page name displayed in templates as page and header title
501 params: a dict with params for this View
502 filter: a dict for the properties that the entities should have
504 Params usage:
505 The params dictionary is passed as argument to getListContent in
506 the soc.views.helper.list module. See the docstring for getListContent
507 on how it uses it. The params dictionary is also passed as argument to
508 the _list method. See the docstring for _list on how it uses it.
511 content = helper.lists.getListContent(request, params, filter, order=order)
512 contents = [content]
514 return self._list(request, params, contents, page_name)
516 def _list(self, request, params, contents, page_name, context=None):
517 """Returns the list page for the specified contents.
519 If the export parameter is present in request.GET a csv export of
520 the specified list is returned instead, see csv().
522 Args:
523 request: the standard Django HTTP request object
524 params: a dict with params for this View
525 contents: a list of content dicts
526 page_name: the page name displayed in templates as page and header title
527 context: the context for this page
529 Params usage:
530 name: The name value is used to set the entity_type in the
531 context so that the template can refer to it.
532 name_plural: The name_plural value is used to set
533 the entity_type_plural value in the context so that the
534 template can refer to it.
535 list_template: The list_template value is used as template for
536 to display the list of all entities for this View.
539 try:
540 export = int(request.GET.get('export', -1))
541 export = export if export >= 0 else None
542 except ValueError:
543 export = None
545 if export is not None and export < len(contents):
546 content = contents[export]
547 key_order = content.get('key_order')
549 if key_order:
550 data = [i.toDict(key_order) for i in content['data']]
552 filename = "export_%d" % export
553 return self.csv(request, data, filename, params, key_order)
555 context = dicts.merge(context,
556 helper.responses.getUniversalContext(request))
557 helper.responses.useJavaScript(context, params['js_uses_all'])
558 context['page_name'] = page_name
559 context['list'] = soc.logic.lists.Lists(contents)
561 context['entity_type'] = params['name']
562 context['entity_type_plural'] = params['name_plural']
563 context['no_lists_msg'] = params['no_lists_msg']
565 template = params['list_template']
567 return helper.responses.respond(request, template, context)
569 @decorators.merge_params
570 @decorators.check_access
571 def delete(self, request, access_type,
572 page_name=None, params=None, **kwargs):
573 """Shows the delete page for the entity specified by **kwargs.
575 Args:
576 request: the standard Django HTTP request object
577 access_type : the name of the access type which should be checked
578 page_name: the page name displayed in templates as page and header title
579 params: a dict with params for this View
580 kwargs: The Key Fields for the specified entity
582 Params usage:
583 rights: The rights dictionary is used to check if the user has
584 the required rights to delete the specified entity. See checkAccess
585 for more details on how the rights dictionary is used to check access
586 rights.
587 name: used in the same way as in edit(), see it's docstring for
588 a more detailed explanation on how it is used.
589 missing_redirect: see name
590 error_edit: see name
591 delete_redirect: The delete_redirect value is used as the url to
592 redirect to after having successfully deleted the entity.
595 logic = params['logic']
597 try:
598 entity = logic.getFromKeyFieldsOr404(kwargs)
599 except out_of_band.Error, error:
600 error.message_fmt = (
601 error.message_fmt + self.DEF_CREATE_NEW_ENTITY_MSG_FMT % {
602 'entity_type_lower' : params['name'].lower(),
603 'entity_type' : params['name'],
604 'create' : params['missing_redirect']})
605 return helper.responses.errorResponse(
606 error, request, template=params['error_edit'])
608 if not logic.isDeletable(entity):
609 page_params = params['cannot_delete_params']
610 params['suffix'] = entity.key().name()
611 request.path = params['edit_redirect'] % params
613 # redirect to the edit page
614 # display notice that entity could not be deleted
615 return helper.responses.redirectToChangedSuffix(
616 request, None, params=page_params)
618 logic.delete(entity)
619 redirect = params['delete_redirect']
621 return http.HttpResponseRedirect(redirect)
623 def select(self, request, view, redirect,
624 page_name=None, params=None, filter=None):
625 """Displays a list page allowing the user to select an entity.
627 After having selected the Scope, the user is redirected to the
628 'create a new entity' page with the scope_path set appropriately.
630 Params usage:
631 The params dictionary is also passed to getListContent from
632 the helper.list module, please refer to its docstring also.
633 The params dictionary is passed to self._list as well, refer
634 to its docstring for details on how it uses it.
636 Args:
637 request: the standard Django HTTP request object
638 view: the view for which to generate the select page
639 redirect: the redirect to use
640 page_name: the page name displayed in templates as page and header title
641 params: a dict with params for this View
642 filter: a filter that all displayed entities should satisfy
645 params = dicts.merge(params, view.getParams())
646 params = dicts.merge(params, self._params)
647 params['list_action'] = (redirect, self._params)
648 params['list_description'] = self.DEF_CREATE_INSTRUCTION_MSG_FMT % (
649 params['name'], self._params['name'])
651 content = helper.lists.getListContent(request, params, filter=filter)
652 contents = [content]
654 return self._list(request, params, contents, page_name)
656 def _getPickData(self, model, filter, logic):
657 """Retrieves the pick data for this query.
659 Args:
660 model: the model that is being queried
661 filter: the filters that apply
662 logic: the logic that will be used for the query
665 entities = logic.getForFields(filter=filter, limit=1000)
666 return entities
668 @decorators.merge_params
669 @decorators.check_access
670 def pick(self, request, acces_type, page_name=None, params=None):
671 """Displays a list page allowing the user to select an entity.
673 After having selected an entity, the user is redirected to the
674 return_url as specified in the GET args.
676 Params usage:
677 The params dictionary is passed to self.select, refer
678 to its docstring for details on how it uses it.
680 Args:
681 request: the standard Django HTTP request object
682 access_type : the name of the access type which should be checked
683 page_name: the page name displayed in templates as page and header title
684 params: a dict with params for this View
687 logic = params['logic']
689 # convert to a regular dict
690 filter = {}
691 for key in request.GET.keys():
692 # need to use getlist as we want to support multiple values
693 filter[key] = request.GET.getlist(key)
695 if params['cache_pick']:
696 fun = soc.cache.logic.cache(self._getPickData)
697 else:
698 fun = self._getPickData
700 entities = fun(logic._model, filter, logic)
702 data = [i.toDict() for i in entities]
704 return self.json(request, data)
706 def json(self, request, data):
707 """Returns data as a json object.
710 to_json = {
711 'data': data,
714 json = simplejson.dumps(to_json)
716 context = {'json': json}
717 template = 'soc/json.html'
719 response = responses.respond(request, template, context)
721 # if the browser supports HTTP/1.1
722 # post-check and pre-check and no-store for IE7
723 response['Cache-Control'] = 'no-store, no-cache, must-revalidate, ' \
724 'post-check=0, pre-check=0'
726 # if the browser supports HTTP/1.0
727 response['Pragma'] = 'no-cache'
729 return response
731 def csv(self, request, data, filename, params, key_order=None):
732 """Returns data as a csv file
734 If key_order is set data should be a sequence of dicts, otherwise
735 data should be a sequence of lists,s ee csv.writer and
736 csv.DictWriter for more information.
739 params = params.copy()
740 params['export_extension'] = '.csv'
741 params['export_content_type'] = 'text/csv'
742 fieldnames = params['csv_fieldnames']
744 f = StringIO.StringIO()
746 if key_order:
747 writer = csv.DictWriter(f, key_order, dialect='excel')
748 writer.writerow(dicts.identity(key_order))
749 else:
750 writer = csv.writer(f, dialect='excel')
752 writer.writerows(data)
754 data = f.getvalue()
756 return self.download(request, data, filename, params)
758 def _editPost(self, request, entity, fields):
759 """Performs any required processing on the entity to post its edit page.
761 Args:
762 request: the django request object
763 entity: the entity to create or update from POST contents
764 fields: the new field values
767 references = self._params['references']
768 for field_name, original_name, _ in references:
769 if field_name not in fields:
770 continue
772 entity = fields.get('resolved_%s' % field_name)
773 fields[original_name] = entity
775 # If scope_logic is not defined, this entity has no scope
776 if not self._params['scope_logic']:
777 return
779 # If this entity is unscoped, do not try to retrieve a scope
780 if 'scope_path' not in fields:
781 return
783 if not entity:
784 scope = self._params['scope_logic'].logic.getFromKeyName(
785 fields['scope_path'])
786 fields['scope'] = scope
788 def _public(self, request, entity, context):
789 """Performs any required processing to get an entity's public page.
791 Args:
792 request: the django request object
793 entity: the entity to make public
794 context: the context object
796 pass
798 def _editGet(self, request, entity, form):
799 """Performs any required processing on the form to get its edit page.
801 Args:
802 request: the django request object
803 entity: the entity to get
804 form: the django form that will be used for the page
807 # fill in the email field with the data from the entity
808 if 'scope_path' in form.fields:
809 form.fields['scope_path'].initial = entity.scope_path
811 for field_name, _, getter in self._params['references']:
812 try:
813 field = getter(entity)
814 form.fields[field_name].initial = field.link_id if field else None
815 except db.Error:
816 pass
818 for field, value in request.GET.iteritems():
819 if field in form.fields:
820 form.fields[field].initial = value
822 def _editSeed(self, request, seed):
823 """Performs any required processing on the form to get its edit page.
825 Args:
826 request: the django request object
827 seed: the fields to seed the create page with
829 pass
831 def _editContext(self, request, context):
832 """Performs any required processing on the context for edit pages.
834 Args:
835 request: the django request object
836 context: the context dictionary that will be used
839 pass
841 def _constructResponse(self, request, entity, context,
842 form, params, template=None):
843 """Updates the context and returns a response for the specified arguments.
845 Args:
846 request: the django request object
847 entity: the entity that is used and set in the context
848 context: the context to be used
849 form: the form that will be used and set in the context
850 params: a dict with params for this View
851 template: if specified, this template is
853 Params usage:
854 name: The name_plural value is used to set the entity_type
855 value in the context so that the template can refer to it.
856 name_plural: same as name, but used to set entity_type_plural
857 name_short: same as name, but used to set entity_type_short
858 url_name: same as name, but used to set entity_type_url
859 edit_template: The edit_template value is used as template when
860 there is an existing entity to display the edit page for the
861 specified entity.
862 create_template: similar to edit_template, but is used when
863 there is no existing entity.
866 logic = params['logic']
867 suffix = logic.getKeySuffix(entity)
869 context['form'] = form
870 context['entity'] = entity
871 context['entity_suffix'] = suffix
872 context['entity_type'] = params['name']
873 context['entity_type_plural'] = params['name_plural']
874 context['entity_type_short'] = params['name_short']
875 context['entity_type_url'] = params['url_name']
876 context['edit_cancel_redirect'] = params.get('edit_cancel_redirect')
877 context['return_url'] = request.path
879 if params.get('export_content_type') and entity:
880 context['export_link'] = redirects.getExportRedirect(entity, params)
882 if not template:
883 if entity:
884 template = params['edit_template']
885 else:
886 template = params['create_template']
888 self._editContext(request, context)
890 # remove the seed from the context before dispatching to Django
891 context.pop('seed', None)
893 return helper.responses.respond(request, template, context)
895 def getParams(self):
896 """Returns this view's params attribute.
899 return self._params
901 @decorators.merge_params
902 def getSidebarMenus(self, id, user, params=None):
903 """Returns an dictionary with one sidebar entry.
905 Args:
906 params: a dict with params for this View
908 Params usage:
909 The params dictionary is passed as argument to getSidebarItems
910 from the soc.views.sitemap.sidebar module, see the docstring
911 of _getSidebarItems on how it uses it.
914 return sitemap.sidebar.getSidebarMenus(id, user, params=params)
916 @decorators.merge_params
917 def getDjangoURLPatterns(self, params=None):
918 """Retrieves a list of sidebar entries for this view
920 Params usage:
921 The params dictionary is passed to the getDjangoURLPatterns
922 function in the soc.views.sitemap.sitemap module, see the
923 docstring of getDjangoURLPatterns on how it uses it.
925 Args:
926 params: a dict with params for this View
929 return sitemap.sitemap.getDjangoURLPatterns(params)