Now clicking cancel button returns user to previous page. Fixes issue 569.
[Melange.git] / app / soc / views / models / base.py
bloba06fa46b4b74ffed4e5d78654951ec8034d2c944
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 requests
43 from soc.views.helper import responses
44 from soc.views import sitemap
46 import soc.cache.logic
47 import soc.logic
48 import soc.logic.lists
49 import soc.views.helper.lists
50 import soc.views.helper.params
53 class View(object):
54 """Views for entity classes.
56 The View class functions specific to Entity classes by relying
57 on the the child-classes to define the following fields:
59 self._logic: the logic singleton for this entity
60 """
62 DEF_CREATE_NEW_ENTITY_MSG_FMT = ugettext(
63 ' You can create a new %(entity_type)s by visiting'
64 ' <a href="%(create)s">Create '
65 'a New %(entity_type)s</a> page.')
67 DEF_CREATE_INSTRUCTION_MSG_FMT = ugettext(
68 'Please select a %s for the new %s.')
70 def __init__(self, params=None):
71 """
73 Args:
74 params: This dictionary should be filled with the parameters
75 specific to this entity. See the methods in this class on
76 the fields it should contain, and how they are used.
77 """
79 self._params = helper.params.constructParams(params)
80 self._logic = params['logic']
82 @decorators.merge_params
83 @decorators.check_access
84 def public(self, request, access_type,
85 page_name=None, params=None, **kwargs):
86 """Displays the public page for the entity specified by **kwargs.
88 Params usage:
89 rights: The rights dictionary is used to check if the user has
90 the required rights to view the public page for this entity.
91 See checkAccess for more details on how the rights dictionary
92 is used to check access rights.
93 error_public: The error_public value is used as template when
94 the key values (as defined by the page's url) do not
95 correspond to an existing entity.
96 name: The name value is used to set the entity_type in the
97 context so that the template can refer to it.
98 public_template: The public_template value is used as template
99 to display the public page of the found entity.
101 Args:
102 request: the standard Django HTTP request object
103 access_type : the name of the access type which should be checked
104 page_name: the page name displayed in templates as page and header title
105 params: a dict with params for this View
106 kwargs: the Key Fields for the specified entity
109 # create default template context for use with any templates
110 context = helper.responses.getUniversalContext(request)
111 helper.responses.useJavaScript(context, params['js_uses_all'])
112 context['page_name'] = page_name
113 entity = None
114 logic = params['logic']
116 if not all(kwargs.values()):
117 #TODO: Change this into a proper redirect
118 return http.HttpResponseRedirect('/')
120 try:
121 entity = logic.getFromKeyFieldsOr404(kwargs)
122 except out_of_band.Error, error:
123 return helper.responses.errorResponse(
124 error, request, template=params['error_public'], context=context)
126 if not self._public(request, entity, context):
127 redirect = params['public_redirect']
128 if redirect:
129 return http.HttpResponseRedirect(redirect)
131 context['entity'] = entity
132 context['entity_type'] = params['name']
133 context['entity_type_url'] = params['url_name']
135 context = dicts.merge(params['context'], context)
137 template = params['public_template']
139 return helper.responses.respond(request, template, context=context)
141 @decorators.merge_params
142 @decorators.check_access
143 def admin(self, request, access_type,
144 page_name=None, params=None, **kwargs):
145 """Displays the admin page for the entity specified by **kwargs.
147 Params usage:
148 rights: The rights dictionary is used to check if the user has
149 the required rights to view the admin page for this entity.
150 See checkAccess for more details on how the rights dictionary
151 is used to check access rights.
152 name: The name value is used to set the entity_type in the
153 context so that the template can refer to it.
154 public_template: The public_template value is used as template
155 to display the public page of the found entity.
157 Args:
158 request: the standard Django HTTP request object
159 access_type : the name of the access type which should be checked
160 page_name: the page name displayed in templates as page and header title
161 params: a dict with params for this View
162 kwargs: the Key Fields for the specified entity
165 # create default template context for use with any templates
166 context = helper.responses.getUniversalContext(request)
167 helper.responses.useJavaScript(context, params['js_uses_all'])
168 context['page_name'] = page_name
169 logic = params['logic']
171 try:
172 entity = logic.getFromKeyFieldsOr404(kwargs)
173 except out_of_band.Error, error:
174 return helper.responses.errorResponse(error, request, context=context)
176 form = params['admin_form'](instance=entity)
177 template = params['admin_template']
179 return self._constructResponse(request, entity, context, form,
180 params, template=template)
182 @decorators.merge_params
183 @decorators.check_access
184 def export(self, request, access_type,
185 page_name=None, params=None, **kwargs):
186 """Displays the export page for the entity specified by **kwargs.
188 Params usage:
189 rights: The rights dictionary is used to check if the user has
190 the required rights to view the export page for this entity.
191 See checkAccess for more details on how the rights dictionary
192 is used to check access rights.
193 error_export: The error_export value is used as template when
194 the key values (as defined by the page's url) do not
195 correspond to an existing entity.
196 Params is passed to download, refer to it's docstring for more
197 details on how it uses it.
199 Args:
200 request: the standard Django HTTP request object
201 access_type : the name of the access type which should be checked
202 page_name: the page name displayed in templates as page and header title
203 params: a dict with params for this View
204 kwargs: the Key Fields for the specified entity
207 if not ('export_content_type' in params) and ('export_function' in params):
208 return self.public(request, access_type, page_name=page_name,
209 params=params, **kwargs)
211 # create default template context for use with any templates
212 entity = None
213 logic = params['logic']
215 if not all(kwargs.values()):
216 #TODO: Change this into a proper redirect
217 return http.HttpResponseRedirect('/')
219 try:
220 entity = logic.getFromKeyFieldsOr404(kwargs)
221 except out_of_band.Error, error:
222 return helper.responses.errorResponse(
223 error, request, template=params['error_export'])
225 export_function = params['export_function']
226 data, filename = export_function(entity)
228 return self.download(request, data, filename, params)
230 def download(self, request, data, filename, params):
231 """Returns data as a downloadable file with the specified name.
233 Params usage:
234 export_template: The export_template value is used as template
235 to display the export page of the found entity.
236 export_content_type: The export_content_type value is used to set
237 the Content-Type header of the HTTP response. If empty (or None),
238 public() is called instead.
239 export_extension: The export_extension value is used as the suffix
240 of the file that will be offered for download.
242 Args:
243 request: the standard Django HTTP request object
244 data: the data that should be offered as file content
245 filename: the name the file should have
246 params: a dict with params for this View
249 context = {}
250 context['data'] = data
252 template = params['export_template']
254 response_args = {'mimetype': params['export_content_type']}
256 export_extension = params['export_extension']
258 response_headers = {
259 'Content-Disposition': 'attachment; filename=%s%s' % (
260 filename, export_extension),
263 return helper.responses.respond(request, template, context=context,
264 response_args=response_args,
265 response_headers=response_headers)
267 @decorators.check_access
268 def create(self, request, access_type,
269 page_name=None, params=None, **kwargs):
270 """Displays the create page for this entity type.
272 Params usage:
273 The params dictionary is passed on to edit, see the docstring
274 for edit on how it uses it.
276 Args:
277 request: the standard Django HTTP request object
278 access_type : the name of the access type which should be checked
279 page_name: the page name displayed in templates as page and header title
280 params: a dict with params for this View
281 kwargs: not used for create()
284 new_params = dicts.merge(params, self._params)
286 # redirect to scope selection view
287 if ('scope_view' in new_params) and ('scope_path' not in kwargs):
288 view = new_params['scope_view'].view
289 redirect = new_params['scope_redirect']
290 return self.select(request, view, redirect,
291 params=params, page_name=page_name, **kwargs)
293 params = new_params
295 context = helper.responses.getUniversalContext(request)
296 helper.responses.useJavaScript(context, params['js_uses_all'])
297 context['page_name'] = page_name
299 if request.method == 'POST':
300 return self.createPost(request, context, params)
301 else:
302 return self.createGet(request, context, params, kwargs)
304 def createGet(self, request, context, params, seed):
305 """See editGet.
307 Handles generating the patch to create new entities.
310 self._editSeed(request, seed)
312 if seed:
313 # pass the seed through the context to _constructResponse
314 # it will be popped before dispatching to Django
315 context['seed'] = seed
316 form = params['create_form'](initial=seed)
317 else:
318 form = params['create_form']()
320 return self._constructResponse(request, None, context, form, params)
322 def createPost(self, request, context, params):
323 """See editPost.
325 Handles the creation of new entities.
328 form = params['create_form'](request.POST)
330 if not form.is_valid():
331 return self._constructResponse(request, None, context, form, params)
333 _, fields = forms.collectCleanedFields(form)
334 self._editPost(request, None, fields)
336 logic = params['logic']
337 entity = logic.updateOrCreateFromFields(fields)
339 page_params = params['edit_params']
340 params['suffix'] = entity.key().id_or_name()
342 request.path = params['edit_redirect'] % params
344 return helper.responses.redirectToChangedSuffix(
345 request, None, params=page_params)
347 @decorators.merge_params
348 @decorators.check_access
349 def edit(self, request, access_type,
350 page_name=None, params=None, seed=None, **kwargs):
351 """Displays the edit page for the entity specified by **kwargs.
353 Params usage:
354 The params dictionary is passed on to either editGet or editPost
355 depending on the method type of the request. See the docstring
356 for editGet and editPost on how they use it.
358 rights: The rights dictionary is used to check if the user has
359 the required rights to edit (or create) a new entity.
360 See checkAccess for more details on how the rights dictionary
361 is used to check access rights.
362 name: The name value is used to construct the message_fmt of the
363 raised error when there key_values do not define an existing
364 entity. See DEF_CREATE_NEW_ENTITY_MSG_FMT on how the name
365 (and the lower() version of it) is used.
366 missing_redirect: The missing_redirect value is also used to
367 construct the message_fmt mentioned above.
368 error_public: The error_public value is used as the template for
369 the error response mentioned above.
371 Args:
372 request: the standard Django HTTP request object
373 access_type : the name of the access type which should be checked
374 page_name: the page name displayed in templates as page and header title
375 params: a dict with params for this View
376 kwargs: The Key Fields for the specified entity
379 logic = params['logic']
381 context = helper.responses.getUniversalContext(request)
382 helper.responses.useJavaScript(context, params['js_uses_all'])
383 context['page_name'] = page_name
385 try:
386 entity = logic.getFromKeyFieldsOr404(kwargs)
387 except out_of_band.Error, error:
388 msg = self.DEF_CREATE_NEW_ENTITY_MSG_FMT % {
389 'entity_type_lower' : params['name'].lower(),
390 'entity_type' : params['name'],
391 'create' : params['missing_redirect']
393 error.message_fmt = error.message_fmt + msg
394 return helper.responses.errorResponse(
395 error, request, context=context)
397 if request.method == 'POST':
398 return self.editPost(request, entity, context, params=params)
399 else:
400 return self.editGet(request, entity, context, params=params)
402 @decorators.merge_params
403 def editPost(self, request, entity, context, params=None):
404 """Processes POST requests for the specified entity.
406 Params usage:
407 The params dictionary is passed to _constructResponse when the
408 form is not valid (see edit_form and create_form below). See
409 the docstring of _constructResponse on how it uses it.
411 edit_form: The edit_form value is used as form when there is an
412 existing entity. It is provided with with the request.POST
413 dictionary on construction. The collectCleanedFields method
414 is called with the newly constructed form. If the form is
415 not valid, it is passed as argument to _constructResponse.
416 create_form: The create_form value is used in a similar way to
417 edit_form, only it is used when there is no existing entity.
418 edit_redirect: The edit_redirect value is used as the first part
419 of the url if the form was valid. The last part of the url is
420 created using the .key().id_or_name() method of the entity.
421 edit_params: The edit_params dictionary is used as argument to
422 redirectToChangedSuffix, it will be appended to the url in the
423 standard ?key=value format.
425 Args:
426 request: a django request object
427 entity: the entity that will be modified or created, may be None
428 context: the context dictionary that will be provided to Django
429 params: required, a dict with params for this View
432 logic = params['logic']
434 form = params['edit_form'](request.POST)
436 if not form.is_valid():
437 return self._constructResponse(request, entity, context, form, params)
439 _, fields = forms.collectCleanedFields(form)
441 self._editPost(request, entity, fields)
443 entity = logic.updateEntityProperties(entity, fields)
445 page_params = params['edit_params']
446 params['suffix'] = entity.key().id_or_name()
448 request.path = params['edit_redirect'] % params
450 return helper.responses.redirectToChangedSuffix(
451 request, None, params=page_params)
453 @decorators.merge_params
454 def editGet(self, request, entity, context, params=None):
455 """Processes GET requests for the specified entity.
457 Params usage:
458 The params dictionary is passed to _constructResponse, see the
459 docstring of _constructResponse on how it uses it.
461 save_message: The save_message list is used as argument to
462 getSingleIndexedParamValue when an existing entity was saved.
463 edit_form: The edit_form is used as form if there is an existing
464 entity. The existing entity is passed as instance to it on
465 construction. If key_name is part of it's fields it will be
466 set to the entity's key().id_or_name() value. It is also passed as
467 argument to the _editGet method. See the docstring for
468 _editGet on how it uses it.
469 create_form: The create_form is used as form if there was no
470 existing entity. If the seed argument is present, it is passed
471 as the 'initial' argument on construction. Otherwise, it is
472 called with no arguments.
473 submit_msg_param_name: The submit_msg_param_name value is used
474 as the key part in the ?key=value construct for the submit
475 message parameter (see also save_message).
477 Args:
478 request: the django request object
479 entity: the entity that will be edited, may be None
480 context: the context dictionary that will be provided to django
481 seed: if no entity is provided, the initial values for the new entity
482 params: required, a dict with params for this View
485 # logic = params['logic']
486 suffix = entity.key().id_or_name() if entity else None
488 # remove the params from the request, this is relevant only if
489 # someone bookmarked a POST page.
490 is_self_referrer = requests.isReferrerSelf(
491 request, suffix=suffix, url_name=params['url_name'])
493 if request.GET.get(params['submit_msg_param_name']):
494 if (not entity) or (not is_self_referrer):
495 return http.HttpResponseRedirect(request.path)
497 # note: no message will be displayed if parameter is not present
498 context['notice'] = requests.getSingleIndexedParamValue(
499 request, params['submit_msg_param_name'],
500 values=params['save_message'])
502 # populate form with the existing entity
503 form = params['edit_form'](instance=entity)
505 self._editGet(request, entity, form)
507 return self._constructResponse(request, entity, context, form, params)
509 @decorators.merge_params
510 @decorators.check_access
511 def list(self, request, access_type,
512 page_name=None, params=None, filter=None, order=None, **kwargs):
513 """Displays the list page for the entity type.
515 Args:
516 request: the standard Django HTTP request object
517 access_type : the name of the access type which should be checked
518 page_name: the page name displayed in templates as page and header title
519 params: a dict with params for this View
520 filter: a dict for the properties that the entities should have
522 Params usage:
523 The params dictionary is passed as argument to getListContent in
524 the soc.views.helper.list module. See the docstring for getListContent
525 on how it uses it. The params dictionary is also passed as argument to
526 the _list method. See the docstring for _list on how it uses it.
529 content = helper.lists.getListContent(request, params, filter, order=order)
530 contents = [content]
532 return self._list(request, params, contents, page_name)
534 def _list(self, request, params, contents, page_name, context=None):
535 """Returns the list page for the specified contents.
537 If the export parameter is present in request.GET a csv export of
538 the specified list is returned instead, see csv().
540 Args:
541 request: the standard Django HTTP request object
542 params: a dict with params for this View
543 contents: a list of content dicts
544 page_name: the page name displayed in templates as page and header title
545 context: the context for this page
547 Params usage:
548 name: The name value is used to set the entity_type in the
549 context so that the template can refer to it.
550 name_plural: The name_plural value is used to set
551 the entity_type_plural value in the context so that the
552 template can refer to it.
553 list_template: The list_template value is used as template for
554 to display the list of all entities for this View.
557 try:
558 export = int(request.GET.get('export', -1))
559 export = export if export >= 0 else None
560 except ValueError:
561 export = None
563 content = [i for i in contents if i.get('idx') == export]
564 if len(content) == 1:
565 content = content[0]
566 key_order = content.get('key_order')
568 if key_order:
569 data = [i.toDict(key_order) for i in content['data']]
571 filename = "export_%d" % export
572 return self.csv(request, data, filename, params, key_order)
574 context = dicts.merge(context,
575 helper.responses.getUniversalContext(request))
576 helper.responses.useJavaScript(context, params['js_uses_all'])
577 context['page_name'] = page_name
578 context['list'] = soc.logic.lists.Lists(contents)
580 context['entity_type'] = params['name']
581 context['entity_type_plural'] = params['name_plural']
582 context['list_msg'] = params['list_msg']
583 context['no_lists_msg'] = params['no_lists_msg']
585 template = params['list_template']
587 return helper.responses.respond(request, template, context)
589 @decorators.merge_params
590 @decorators.check_access
591 def delete(self, request, access_type,
592 page_name=None, params=None, **kwargs):
593 """Shows the delete page for the entity specified by **kwargs.
595 Args:
596 request: the standard Django HTTP request object
597 access_type : the name of the access type which should be checked
598 page_name: the page name displayed in templates as page and header title
599 params: a dict with params for this View
600 kwargs: The Key Fields for the specified entity
602 Params usage:
603 rights: The rights dictionary is used to check if the user has
604 the required rights to delete the specified entity. See checkAccess
605 for more details on how the rights dictionary is used to check access
606 rights.
607 name: used in the same way as in edit(), see it's docstring for
608 a more detailed explanation on how it is used.
609 missing_redirect: see name
610 error_edit: see name
611 delete_redirect: The delete_redirect value is used as the url to
612 redirect to after having successfully deleted the entity.
615 logic = params['logic']
617 try:
618 entity = logic.getFromKeyFieldsOr404(kwargs)
619 except out_of_band.Error, error:
620 error.message_fmt = (
621 error.message_fmt + self.DEF_CREATE_NEW_ENTITY_MSG_FMT % {
622 'entity_type_lower' : params['name'].lower(),
623 'entity_type' : params['name'],
624 'create' : params['missing_redirect']})
625 return helper.responses.errorResponse(
626 error, request, template=params['error_edit'])
628 if not logic.isDeletable(entity):
629 page_params = params['cannot_delete_params']
630 params['suffix'] = entity.key().id_or_name()
631 request.path = params['edit_redirect'] % params
633 # redirect to the edit page
634 # display notice that entity could not be deleted
635 return helper.responses.redirectToChangedSuffix(
636 request, None, params=page_params)
638 logic.delete(entity)
639 redirect = params['delete_redirect']
641 return http.HttpResponseRedirect(redirect)
643 def select(self, request, view, redirect,
644 page_name=None, params=None, filter=None):
645 """Displays a list page allowing the user to select an entity.
647 After having selected the Scope, the user is redirected to the
648 'create a new entity' page with the scope_path set appropriately.
650 Params usage:
651 The params dictionary is also passed to getListContent from
652 the helper.list module, please refer to its docstring also.
653 The params dictionary is passed to self._list as well, refer
654 to its docstring for details on how it uses it.
656 Args:
657 request: the standard Django HTTP request object
658 view: the view for which to generate the select page
659 redirect: the redirect to use
660 page_name: the page name displayed in templates as page and header title
661 params: a dict with params for this View
662 filter: a filter that all displayed entities should satisfy
665 params = dicts.merge(params, view.getParams())
666 params = dicts.merge(params, self._params)
667 params['list_action'] = (redirect, self._params)
668 params['list_description'] = self.DEF_CREATE_INSTRUCTION_MSG_FMT % (
669 params['name'], self._params['name'])
671 content = helper.lists.getListContent(request, params, filter=filter)
672 contents = [content]
674 return self._list(request, params, contents, page_name)
676 def _getData(self, model, filter, order, logic):
677 """Retrieves the pick data for this query.
679 Args:
680 model: the model that is being queried
681 filter: the filters that apply
682 logic: the logic that will be used for the query
685 entities = logic.getForFields(filter=filter, order=order, limit=1000)
686 return entities
688 @decorators.merge_params
689 @decorators.check_access
690 def pick(self, request, acces_type, page_name=None, params=None):
691 """Displays a list page allowing the user to select an entity.
693 After having selected an entity, the user is redirected to the
694 return_url as specified in the GET args.
696 Params usage:
697 The params dictionary is passed to self.select, refer
698 to its docstring for details on how it uses it.
700 Args:
701 request: the standard Django HTTP request object
702 access_type : the name of the access type which should be checked
703 page_name: the page name displayed in templates as page and header title
704 params: a dict with params for this View
707 logic = params['logic']
709 # convert to a regular dict
710 filter = {}
711 for key in request.GET.keys():
712 # need to use getlist as we want to support multiple values
713 filter[key] = request.GET.getlist(key)
715 if params['cache_pick']:
716 fun = soc.cache.logic.cache(self._getData)
717 else:
718 fun = self._getData
720 order = []
721 entities = fun(logic.getModel(), filter, order, logic)
723 key_order = params.get('cache_pick_order')
724 data = [i.toDict(key_order) for i in entities]
726 return self.json(request, data)
728 def json(self, request, data):
729 """Returns data as a json object.
732 to_json = {
733 'data': data,
736 json = simplejson.dumps(to_json)
738 context = {'json': json}
739 template = 'soc/json.html'
741 response = responses.respond(request, template, context)
743 # if the browser supports HTTP/1.1
744 # post-check and pre-check and no-store for IE7
745 response['Cache-Control'] = 'no-store, no-cache, must-revalidate, ' \
746 'post-check=0, pre-check=0'
748 # if the browser supports HTTP/1.0
749 response['Pragma'] = 'no-cache'
751 return response
753 def csv(self, request, data, filename, params, key_order=None):
754 """Returns data as a csv file.
756 If key_order is set data should be a sequence of dicts, otherwise
757 data should be a sequence of lists, see csv.writer and
758 csv.DictWriter for more information.
761 params = params.copy()
762 params['export_extension'] = '.csv'
763 params['export_content_type'] = 'text/csv'
764 # fieldnames = params['csv_fieldnames']
766 file_handler = StringIO.StringIO()
768 if key_order:
769 writer = csv.DictWriter(file_handler, key_order, dialect='excel')
770 writer.writerow(dicts.identity(key_order))
772 # encode the data to UTF-8 to ensure compatibiliy
773 for row_dict in data:
774 for key in row_dict.keys():
775 value = row_dict[key]
776 if isinstance(value, basestring):
777 row_dict[key] = value.encode("utf-8")
778 else:
779 row_dict[key] = str(value)
780 writer.writerow(row_dict)
781 else:
782 writer = csv.writer(file_handler, dialect='excel')
784 # encode the data to UTF-8 to ensure compatibiliy
785 for row in data:
786 if row:
787 writer.writerow(row.encode("utf-8"))
788 else:
789 writer.writerow(row)
791 data = file_handler.getvalue()
793 return self.download(request, data, filename, params)
795 def _editPost(self, request, entity, fields):
796 """Performs any required processing on the entity to post its edit page.
798 Args:
799 request: the django request object
800 entity: the entity to create or update from POST contents
801 fields: the new field values
804 references = self._params['references']
805 for field_name, original_name, _ in references:
806 if field_name not in fields:
807 continue
809 entity = fields.get('resolved_%s' % field_name)
810 fields[original_name] = entity
812 # If scope_logic is not defined, this entity has no scope
813 if not self._params['scope_logic']:
814 return
816 # If this entity is unscoped, do not try to retrieve a scope
817 if 'scope_path' not in fields:
818 return
820 if not entity:
821 scope = self._params['scope_logic'].logic.getFromKeyName(
822 fields['scope_path'])
823 fields['scope'] = scope
825 def _public(self, request, entity, context):
826 """Performs any required processing to get an entity's public page.
828 Should return True iff the public page should be displayed.
830 Args:
831 request: the django request object
832 entity: the entity to make public
833 context: the context object
836 return True
838 def _editGet(self, request, entity, form):
839 """Performs any required processing on the form to get its edit page.
841 Args:
842 request: the django request object
843 entity: the entity to get
844 form: the django form that will be used for the page
847 # fill in the email field with the data from the entity
848 if 'scope_path' in form.fields:
849 form.fields['scope_path'].initial = entity.scope_path
851 for field_name, _, getter in self._params['references']:
852 try:
853 field = getter(entity)
854 form.fields[field_name].initial = field.link_id if field else None
855 except db.Error:
856 # TODO(Pawel.Solyga): use logging to log exception
857 return
859 for field, value in request.GET.iteritems():
860 if field in form.fields:
861 form.fields[field].initial = value
863 def _editSeed(self, request, seed):
864 """Performs any required processing on the form to get its edit page.
866 Args:
867 request: the django request object
868 seed: the fields to seed the create page with
870 pass
872 def _editContext(self, request, context):
873 """Performs any required processing on the context for edit pages.
875 Args:
876 request: the django request object
877 context: the context dictionary that will be used
880 pass
882 def _constructResponse(self, request, entity, context,
883 form, params, template=None):
884 """Updates the context and returns a response for the specified arguments.
886 Args:
887 request: the django request object
888 entity: the entity that is used and set in the context
889 context: the context to be used
890 form: the form that will be used and set in the context
891 params: a dict with params for this View
892 template: if specified, this template is
894 Params usage:
895 name: The name value is used to set the entity_type
896 value in the context so that the template can refer to it.
897 name_plural: same as name, but used to set entity_type_plural
898 name_short: same as name, but used to set entity_type_short
899 url_name: same as name, but used to set entity_type_url
900 edit_template: The edit_template value is used as template when
901 there is an existing entity to display the edit page for the
902 specified entity.
903 create_template: similar to edit_template, but is used when
904 there is no existing entity.
907 # logic = params['logic']
908 suffix = entity.key().id_or_name() if entity else None
910 context['form'] = form
911 context['entity'] = entity
912 context['entity_suffix'] = suffix
913 context['entity_type'] = params['name']
914 context['entity_type_plural'] = params['name_plural']
915 context['entity_type_short'] = params['name_short']
916 context['entity_type_url'] = params['url_name']
917 context['cancel_redirect'] = params.get('cancel_redirect')
918 context['return_url'] = request.path
920 if params.get('export_content_type') and entity:
921 context['export_link'] = redirects.getExportRedirect(entity, params)
923 if not template:
924 if entity:
925 template = params['edit_template']
926 else:
927 template = params['create_template']
929 self._editContext(request, context)
931 # remove the seed from the context before dispatching to Django
932 context.pop('seed', None)
934 return helper.responses.respond(request, template, context)
936 def getParams(self):
937 """Returns this view's params attribute.
940 return self._params
942 @decorators.merge_params
943 def getSidebarMenus(self, id, user, params=None):
944 """Returns an dictionary with one sidebar entry.
946 Args:
947 params: a dict with params for this View
949 Params usage:
950 The params dictionary is passed as argument to getSidebarItems
951 from the soc.views.sitemap.sidebar module, see the docstring
952 of _getSidebarItems on how it uses it.
955 return sitemap.sidebar.getSidebarMenus(id, user, params=params)
957 @decorators.merge_params
958 def getDjangoURLPatterns(self, params=None):
959 """Retrieves a list of sidebar entries for this view
961 Params usage:
962 The params dictionary is passed to the getDjangoURLPatterns
963 function in the soc.views.sitemap.sitemap module, see the
964 docstring of getDjangoURLPatterns on how it uses it.
966 Args:
967 params: a dict with params for this View
970 return sitemap.sitemap.getDjangoURLPatterns(params)