Style fixes and removal of unused imports in soc.views.models.
[Melange.git] / app / soc / views / models / base.py
blob01843b9df77139f5384fb6c2ffee66205ac22e2e
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 if not self._public(request, entity, context):
126 redirect = params['public_redirect']
127 if redirect:
128 return http.HttpResponseRedirect(redirect)
130 context['entity'] = entity
131 context['entity_type'] = params['name']
132 context['entity_type_url'] = params['url_name']
134 context = dicts.merge(params['context'], context)
136 template = params['public_template']
138 return helper.responses.respond(request, template, context=context)
140 @decorators.merge_params
141 @decorators.check_access
142 def admin(self, request, access_type,
143 page_name=None, params=None, **kwargs):
144 """Displays the admin page for the entity specified by **kwargs.
146 Params usage:
147 rights: The rights dictionary is used to check if the user has
148 the required rights to view the admin page for this entity.
149 See checkAccess for more details on how the rights dictionary
150 is used to check access rights.
151 name: The name value is used to set the entity_type in the
152 context so that the template can refer to it.
153 public_template: The public_template value is used as template
154 to display the public page of the found entity.
156 Args:
157 request: the standard Django HTTP request object
158 access_type : the name of the access type which should be checked
159 page_name: the page name displayed in templates as page and header title
160 params: a dict with params for this View
161 kwargs: the Key Fields for the specified entity
164 # create default template context for use with any templates
165 context = helper.responses.getUniversalContext(request)
166 helper.responses.useJavaScript(context, params['js_uses_all'])
167 context['page_name'] = page_name
168 logic = params['logic']
170 try:
171 entity = logic.getFromKeyFieldsOr404(kwargs)
172 except out_of_band.Error, error:
173 return helper.responses.errorResponse(error, request, context=context)
175 form = params['admin_form'](instance=entity)
176 template = params['admin_template']
178 return self._constructResponse(request, entity, context, form,
179 params, template=template)
181 @decorators.merge_params
182 @decorators.check_access
183 def export(self, request, access_type,
184 page_name=None, params=None, **kwargs):
185 """Displays the export page for the entity specified by **kwargs.
187 Params usage:
188 rights: The rights dictionary is used to check if the user has
189 the required rights to view the export page for this entity.
190 See checkAccess for more details on how the rights dictionary
191 is used to check access rights.
192 error_export: The error_export value is used as template when
193 the key values (as defined by the page's url) do not
194 correspond to an existing entity.
195 Params is passed to download, refer to it's docstring for more
196 details on how it uses it.
198 Args:
199 request: the standard Django HTTP request object
200 access_type : the name of the access type which should be checked
201 page_name: the page name displayed in templates as page and header title
202 params: a dict with params for this View
203 kwargs: the Key Fields for the specified entity
206 if not ('export_content_type' in params) and ('export_function' in params):
207 return self.public(request, access_type, page_name=page_name,
208 params=params, **kwargs)
210 # create default template context for use with any templates
211 entity = None
212 logic = params['logic']
214 if not all(kwargs.values()):
215 #TODO: Change this into a proper redirect
216 return http.HttpResponseRedirect('/')
218 try:
219 entity = logic.getFromKeyFieldsOr404(kwargs)
220 except out_of_band.Error, error:
221 return helper.responses.errorResponse(
222 error, request, template=params['error_export'])
224 export_function = params['export_function']
225 data, filename = export_function(entity)
227 return self.download(request, data, filename, params)
229 def download(self, request, data, filename, params):
230 """Returns data as a downloadable file with the specified name.
232 Params usage:
233 export_template: The export_template value is used as template
234 to display the export page of the found entity.
235 export_content_type: The export_content_type value is used to set
236 the Content-Type header of the HTTP response. If empty (or None),
237 public() is called instead.
238 export_extension: The export_extension value is used as the suffix
239 of the file that will be offered for download.
241 Args:
242 request: the standard Django HTTP request object
243 data: the data that should be offered as file content
244 filename: the name the file should have
245 params: a dict with params for this View
248 context = {}
249 context['data'] = data
251 template = params['export_template']
253 response_args = {'mimetype': params['export_content_type']}
255 export_extension = params['export_extension']
257 response_headers = {
258 'Content-Disposition': 'attachment; filename=%s%s' % (
259 filename, export_extension),
262 return helper.responses.respond(request, template, context=context,
263 response_args=response_args,
264 response_headers=response_headers)
266 @decorators.check_access
267 def create(self, request, access_type,
268 page_name=None, params=None, **kwargs):
269 """Displays the create page for this entity type.
271 Params usage:
272 The params dictionary is passed on to edit, see the docstring
273 for edit on how it uses it.
275 Args:
276 request: the standard Django HTTP request object
277 access_type : the name of the access type which should be checked
278 page_name: the page name displayed in templates as page and header title
279 params: a dict with params for this View
280 kwargs: not used for create()
283 new_params = dicts.merge(params, self._params)
285 if ('scope_view' in new_params) and ('scope_path' not in kwargs):
286 view = new_params['scope_view'].view
287 redirect = new_params['scope_redirect']
288 return self.select(request, view, redirect,
289 params=params, page_name=page_name, **kwargs)
291 params = new_params
292 logic = params['logic']
294 # Create page is an edit page with no key fields
295 empty_kwargs = {}
296 fields = logic.getKeyFieldNames()
297 for field in fields:
298 empty_kwargs[field] = None
300 return self.edit(request, access_type, page_name=page_name,
301 params=params, seed=kwargs, **empty_kwargs)
303 @decorators.merge_params
304 @decorators.check_access
305 def edit(self, request, access_type,
306 page_name=None, params=None, seed=None, **kwargs):
307 """Displays the edit page for the entity specified by **kwargs.
309 Params usage:
310 The params dictionary is passed on to either editGet or editPost
311 depending on the method type of the request. See the docstring
312 for editGet and editPost on how they use it.
314 rights: The rights dictionary is used to check if the user has
315 the required rights to edit (or create) a new entity.
316 See checkAccess for more details on how the rights dictionary
317 is used to check access rights.
318 name: The name value is used to construct the message_fmt of the
319 raised error when there key_values do not define an existing
320 entity. See DEF_CREATE_NEW_ENTITY_MSG_FMT on how the name
321 (and the lower() version of it) is used.
322 missing_redirect: The missing_redirect value is also used to
323 construct the message_fmt mentioned above.
324 error_public: The error_public value is used as the template for
325 the error response mentioned above.
327 Args:
328 request: the standard Django HTTP request object
329 access_type : the name of the access type which should be checked
330 page_name: the page name displayed in templates as page and header title
331 params: a dict with params for this View
332 kwargs: The Key Fields for the specified entity
335 logic = params['logic']
337 context = helper.responses.getUniversalContext(request)
338 helper.responses.useJavaScript(context, params['js_uses_all'])
339 context['page_name'] = page_name
340 entity = None
342 try:
343 if all(kwargs.values()):
344 entity = logic.getFromKeyFieldsOr404(kwargs)
345 except out_of_band.Error, error:
346 if not seed:
347 error.message_fmt = (
348 error.message_fmt + self.DEF_CREATE_NEW_ENTITY_MSG_FMT % {
349 'entity_type_lower' : params['name'].lower(),
350 'entity_type' : params['name'],
351 'create' : params['missing_redirect']})
352 return helper.responses.errorResponse(
353 error, request, template=params['error_public'], context=context)
355 if request.method == 'POST':
356 return self.editPost(request, entity, context, params=params)
357 else:
358 return self.editGet(request, entity, context, seed, params=params)
360 @decorators.merge_params
361 def editPost(self, request, entity, context, params=None):
362 """Processes POST requests for the specified entity.
364 Params usage:
365 The params dictionary is passed to _constructResponse when the
366 form is not valid (see edit_form and create_form below). See
367 the docstring of _constructResponse on how it uses it.
369 edit_form: The edit_form value is used as form when there is an
370 existing entity. It is provided with with the request.POST
371 dictionary on construction. The collectCleanedFields method
372 is called with the newly constructed form. If the form is
373 not valid, it is passed as argument to _constructResponse.
374 create_form: The create_form value is used in a similar way to
375 edit_form, only it is used when there is no existing entity.
376 edit_redirect: The edit_redirect value is used as the first part
377 of the url if the form was valid. The last part of the url is
378 created using the getKeySuffix method of the _logic object.
379 edit_params: The edit_params dictionary is used as argument to
380 redirectToChangedSuffix, it will be appended to the url in the
381 standard ?key=value format.
383 Args:
384 request: a django request object
385 entity: the entity that will be modified or created, may be None
386 context: the context dictionary that will be provided to Django
387 params: required, a dict with params for this View
390 logic = params['logic']
392 if entity:
393 form = params['edit_form'](request.POST)
394 else:
395 form = params['create_form'](request.POST)
397 if not form.is_valid():
398 return self._constructResponse(request, entity, context, form, params)
400 key_name, fields = forms.collectCleanedFields(form)
402 self._editPost(request, entity, fields)
404 if not key_name:
405 key_name = logic.getKeyNameFromFields(fields)
407 entity = logic.updateOrCreateFromKeyName(fields, key_name)
409 if not entity:
410 return http.HttpResponseRedirect('/')
412 page_params = params['edit_params']
413 params['suffix'] = logic.getKeySuffix(entity)
415 request.path = params['edit_redirect'] % params
417 # redirect to (possibly new) location of the entity
418 # (causes 'Profile saved' message to be displayed)
419 return helper.responses.redirectToChangedSuffix(
420 request, None, params=page_params)
422 @decorators.merge_params
423 def editGet(self, request, entity, context, seed, params=None):
424 """Processes GET requests for the specified entity.
426 Params usage:
427 The params dictionary is passed to _constructResponse, see the
428 docstring of _constructResponse on how it uses it.
430 save_message: The save_message list is used as argument to
431 getSingleIndexedParamValue when an existing entity was saved.
432 edit_form: The edit_form is used as form if there is an existing
433 entity. The existing entity is passed as instance to it on
434 construction. If key_name is part of it's fields it will be
435 set to the entity's key().name() value. It is also passed as
436 argument to the _editGet method. See the docstring for
437 _editGet on how it uses it.
438 create_form: The create_form is used as form if there was no
439 existing entity. If the seed argument is present, it is passed
440 as the 'initial' argument on construction. Otherwise, it is
441 called with no arguments.
442 submit_msg_param_name: The submit_msg_param_name value is used
443 as the key part in the ?key=value construct for the submit
444 message parameter (see also save_message).
446 Args:
447 request: the django request object
448 entity: the entity that will be edited, may be None
449 context: the context dictionary that will be provided to django
450 seed: if no entity is provided, the initial values for the new entity
451 params: required, a dict with params for this View
454 logic = params['logic']
455 suffix = logic.getKeySuffix(entity)
457 # remove the params from the request, this is relevant only if
458 # someone bookmarked a POST page.
459 is_self_referrer = helper.requests.isReferrerSelf(
460 request, suffix=suffix, url_name=params['url_name'])
462 if request.GET.get(params['submit_msg_param_name']):
463 if (not entity) or (not is_self_referrer):
464 return http.HttpResponseRedirect(request.path)
466 if entity:
467 # note: no message will be displayed if parameter is not present
468 context['notice'] = helper.requests.getSingleIndexedParamValue(
469 request, params['submit_msg_param_name'],
470 values=params['save_message'])
472 # populate form with the existing entity
473 form = params['edit_form'](instance=entity)
475 if 'key_name' in form.fields:
476 form.fields['key_name'].initial = entity.key().name()
478 self._editGet(request, entity, form)
479 else:
480 seed = seed if seed else {}
481 dicts.merge(seed, request.GET)
482 self._editSeed(request, seed)
484 if seed:
485 # pass the seed through the context to _constructResponse
486 # it will be popped before dispatching to Django
487 context['seed'] = seed
488 form = params['create_form'](initial=seed)
489 else:
490 form = params['create_form']()
492 return self._constructResponse(request, entity, context, form, params)
494 @decorators.merge_params
495 @decorators.check_access
496 def list(self, request, access_type,
497 page_name=None, params=None, filter=None, order=None, **kwargs):
498 """Displays the list page for the entity type.
500 Args:
501 request: the standard Django HTTP request object
502 access_type : the name of the access type which should be checked
503 page_name: the page name displayed in templates as page and header title
504 params: a dict with params for this View
505 filter: a dict for the properties that the entities should have
507 Params usage:
508 The params dictionary is passed as argument to getListContent in
509 the soc.views.helper.list module. See the docstring for getListContent
510 on how it uses it. The params dictionary is also passed as argument to
511 the _list method. See the docstring for _list on how it uses it.
514 content = helper.lists.getListContent(request, params, filter, order=order)
515 contents = [content]
517 return self._list(request, params, contents, page_name)
519 def _list(self, request, params, contents, page_name, context=None):
520 """Returns the list page for the specified contents.
522 If the export parameter is present in request.GET a csv export of
523 the specified list is returned instead, see csv().
525 Args:
526 request: the standard Django HTTP request object
527 params: a dict with params for this View
528 contents: a list of content dicts
529 page_name: the page name displayed in templates as page and header title
530 context: the context for this page
532 Params usage:
533 name: The name value is used to set the entity_type in the
534 context so that the template can refer to it.
535 name_plural: The name_plural value is used to set
536 the entity_type_plural value in the context so that the
537 template can refer to it.
538 list_template: The list_template value is used as template for
539 to display the list of all entities for this View.
542 try:
543 export = int(request.GET.get('export', -1))
544 export = export if export >= 0 else None
545 except ValueError:
546 export = None
548 if export is not None and export < len(contents):
549 content = contents[export]
550 key_order = content.get('key_order')
552 if key_order:
553 data = [i.toDict(key_order) for i in content['data']]
555 filename = "export_%d" % export
556 return self.csv(request, data, filename, params, key_order)
558 context = dicts.merge(context,
559 helper.responses.getUniversalContext(request))
560 helper.responses.useJavaScript(context, params['js_uses_all'])
561 context['page_name'] = page_name
562 context['list'] = soc.logic.lists.Lists(contents)
564 context['entity_type'] = params['name']
565 context['entity_type_plural'] = params['name_plural']
566 context['list_msg'] = params['list_msg']
567 context['no_lists_msg'] = params['no_lists_msg']
569 template = params['list_template']
571 return helper.responses.respond(request, template, context)
573 @decorators.merge_params
574 @decorators.check_access
575 def delete(self, request, access_type,
576 page_name=None, params=None, **kwargs):
577 """Shows the delete page for the entity specified by **kwargs.
579 Args:
580 request: the standard Django HTTP request object
581 access_type : the name of the access type which should be checked
582 page_name: the page name displayed in templates as page and header title
583 params: a dict with params for this View
584 kwargs: The Key Fields for the specified entity
586 Params usage:
587 rights: The rights dictionary is used to check if the user has
588 the required rights to delete the specified entity. See checkAccess
589 for more details on how the rights dictionary is used to check access
590 rights.
591 name: used in the same way as in edit(), see it's docstring for
592 a more detailed explanation on how it is used.
593 missing_redirect: see name
594 error_edit: see name
595 delete_redirect: The delete_redirect value is used as the url to
596 redirect to after having successfully deleted the entity.
599 logic = params['logic']
601 try:
602 entity = logic.getFromKeyFieldsOr404(kwargs)
603 except out_of_band.Error, error:
604 error.message_fmt = (
605 error.message_fmt + self.DEF_CREATE_NEW_ENTITY_MSG_FMT % {
606 'entity_type_lower' : params['name'].lower(),
607 'entity_type' : params['name'],
608 'create' : params['missing_redirect']})
609 return helper.responses.errorResponse(
610 error, request, template=params['error_edit'])
612 if not logic.isDeletable(entity):
613 page_params = params['cannot_delete_params']
614 params['suffix'] = entity.key().name()
615 request.path = params['edit_redirect'] % params
617 # redirect to the edit page
618 # display notice that entity could not be deleted
619 return helper.responses.redirectToChangedSuffix(
620 request, None, params=page_params)
622 logic.delete(entity)
623 redirect = params['delete_redirect']
625 return http.HttpResponseRedirect(redirect)
627 def select(self, request, view, redirect,
628 page_name=None, params=None, filter=None):
629 """Displays a list page allowing the user to select an entity.
631 After having selected the Scope, the user is redirected to the
632 'create a new entity' page with the scope_path set appropriately.
634 Params usage:
635 The params dictionary is also passed to getListContent from
636 the helper.list module, please refer to its docstring also.
637 The params dictionary is passed to self._list as well, refer
638 to its docstring for details on how it uses it.
640 Args:
641 request: the standard Django HTTP request object
642 view: the view for which to generate the select page
643 redirect: the redirect to use
644 page_name: the page name displayed in templates as page and header title
645 params: a dict with params for this View
646 filter: a filter that all displayed entities should satisfy
649 params = dicts.merge(params, view.getParams())
650 params = dicts.merge(params, self._params)
651 params['list_action'] = (redirect, self._params)
652 params['list_description'] = self.DEF_CREATE_INSTRUCTION_MSG_FMT % (
653 params['name'], self._params['name'])
655 content = helper.lists.getListContent(request, params, filter=filter)
656 contents = [content]
658 return self._list(request, params, contents, page_name)
660 def _getData(self, model, filter, order, logic):
661 """Retrieves the pick data for this query.
663 Args:
664 model: the model that is being queried
665 filter: the filters that apply
666 logic: the logic that will be used for the query
669 entities = logic.getForFields(filter=filter, order=order, limit=1000)
670 return entities
672 @decorators.merge_params
673 @decorators.check_access
674 def pick(self, request, acces_type, page_name=None, params=None):
675 """Displays a list page allowing the user to select an entity.
677 After having selected an entity, the user is redirected to the
678 return_url as specified in the GET args.
680 Params usage:
681 The params dictionary is passed to self.select, refer
682 to its docstring for details on how it uses it.
684 Args:
685 request: the standard Django HTTP request object
686 access_type : the name of the access type which should be checked
687 page_name: the page name displayed in templates as page and header title
688 params: a dict with params for this View
691 logic = params['logic']
693 # convert to a regular dict
694 filter = {}
695 for key in request.GET.keys():
696 # need to use getlist as we want to support multiple values
697 filter[key] = request.GET.getlist(key)
699 if params['cache_pick']:
700 fun = soc.cache.logic.cache(self._getData)
701 else:
702 fun = self._getData
704 order = []
705 entities = fun(logic.getModel(), filter, order, logic)
707 data = [i.toDict() for i in entities]
709 return self.json(request, data)
711 def json(self, request, data):
712 """Returns data as a json object.
715 to_json = {
716 'data': data,
719 json = simplejson.dumps(to_json)
721 context = {'json': json}
722 template = 'soc/json.html'
724 response = responses.respond(request, template, context)
726 # if the browser supports HTTP/1.1
727 # post-check and pre-check and no-store for IE7
728 response['Cache-Control'] = 'no-store, no-cache, must-revalidate, ' \
729 'post-check=0, pre-check=0'
731 # if the browser supports HTTP/1.0
732 response['Pragma'] = 'no-cache'
734 return response
736 def csv(self, request, data, filename, params, key_order=None):
737 """Returns data as a csv file.
739 If key_order is set data should be a sequence of dicts, otherwise
740 data should be a sequence of lists, see csv.writer and
741 csv.DictWriter for more information.
744 params = params.copy()
745 params['export_extension'] = '.csv'
746 params['export_content_type'] = 'text/csv'
747 # fieldnames = params['csv_fieldnames']
749 file_handler = StringIO.StringIO()
751 if key_order:
752 writer = csv.DictWriter(file_handler, key_order, dialect='excel')
753 writer.writerow(dicts.identity(key_order))
755 # encode the data to UTF-8 to ensure compatibiliy
756 for row_dict in data:
757 for key in row_dict.keys():
758 value = row_dict[key]
759 if isinstance(value, basestring):
760 row_dict[key] = value.encode("utf-8")
761 else:
762 row_dict[key] = str(value)
763 writer.writerow(row_dict)
764 else:
765 writer = csv.writer(file_handler, dialect='excel')
767 # encode the data to UTF-8 to ensure compatibiliy
768 for row in data:
769 if row:
770 writer.writerow(row.encode("utf-8"))
771 else:
772 writer.writerow(row)
774 data = file_handler.getvalue()
776 return self.download(request, data, filename, params)
778 def _editPost(self, request, entity, fields):
779 """Performs any required processing on the entity to post its edit page.
781 Args:
782 request: the django request object
783 entity: the entity to create or update from POST contents
784 fields: the new field values
787 references = self._params['references']
788 for field_name, original_name, _ in references:
789 if field_name not in fields:
790 continue
792 entity = fields.get('resolved_%s' % field_name)
793 fields[original_name] = entity
795 # If scope_logic is not defined, this entity has no scope
796 if not self._params['scope_logic']:
797 return
799 # If this entity is unscoped, do not try to retrieve a scope
800 if 'scope_path' not in fields:
801 return
803 if not entity:
804 scope = self._params['scope_logic'].logic.getFromKeyName(
805 fields['scope_path'])
806 fields['scope'] = scope
808 def _public(self, request, entity, context):
809 """Performs any required processing to get an entity's public page.
811 Should return True iff the public page should be displayed.
813 Args:
814 request: the django request object
815 entity: the entity to make public
816 context: the context object
819 return True
821 def _editGet(self, request, entity, form):
822 """Performs any required processing on the form to get its edit page.
824 Args:
825 request: the django request object
826 entity: the entity to get
827 form: the django form that will be used for the page
830 # fill in the email field with the data from the entity
831 if 'scope_path' in form.fields:
832 form.fields['scope_path'].initial = entity.scope_path
834 for field_name, _, getter in self._params['references']:
835 try:
836 field = getter(entity)
837 form.fields[field_name].initial = field.link_id if field else None
838 except db.Error:
839 # TODO(Pawel.Solyga): use logging to log exception
840 return
842 for field, value in request.GET.iteritems():
843 if field in form.fields:
844 form.fields[field].initial = value
846 def _editSeed(self, request, seed):
847 """Performs any required processing on the form to get its edit page.
849 Args:
850 request: the django request object
851 seed: the fields to seed the create page with
853 pass
855 def _editContext(self, request, context):
856 """Performs any required processing on the context for edit pages.
858 Args:
859 request: the django request object
860 context: the context dictionary that will be used
863 pass
865 def _constructResponse(self, request, entity, context,
866 form, params, template=None):
867 """Updates the context and returns a response for the specified arguments.
869 Args:
870 request: the django request object
871 entity: the entity that is used and set in the context
872 context: the context to be used
873 form: the form that will be used and set in the context
874 params: a dict with params for this View
875 template: if specified, this template is
877 Params usage:
878 name: The name value is used to set the entity_type
879 value in the context so that the template can refer to it.
880 name_plural: same as name, but used to set entity_type_plural
881 name_short: same as name, but used to set entity_type_short
882 url_name: same as name, but used to set entity_type_url
883 edit_template: The edit_template value is used as template when
884 there is an existing entity to display the edit page for the
885 specified entity.
886 create_template: similar to edit_template, but is used when
887 there is no existing entity.
890 logic = params['logic']
891 suffix = logic.getKeySuffix(entity)
893 context['form'] = form
894 context['entity'] = entity
895 context['entity_suffix'] = suffix
896 context['entity_type'] = params['name']
897 context['entity_type_plural'] = params['name_plural']
898 context['entity_type_short'] = params['name_short']
899 context['entity_type_url'] = params['url_name']
900 context['edit_cancel_redirect'] = params.get('edit_cancel_redirect')
901 context['return_url'] = request.path
903 if params.get('export_content_type') and entity:
904 context['export_link'] = redirects.getExportRedirect(entity, params)
906 if not template:
907 if entity:
908 template = params['edit_template']
909 else:
910 template = params['create_template']
912 self._editContext(request, context)
914 # remove the seed from the context before dispatching to Django
915 context.pop('seed', None)
917 return helper.responses.respond(request, template, context)
919 def getParams(self):
920 """Returns this view's params attribute.
923 return self._params
925 @decorators.merge_params
926 def getSidebarMenus(self, id, user, params=None):
927 """Returns an dictionary with one sidebar entry.
929 Args:
930 params: a dict with params for this View
932 Params usage:
933 The params dictionary is passed as argument to getSidebarItems
934 from the soc.views.sitemap.sidebar module, see the docstring
935 of _getSidebarItems on how it uses it.
938 return sitemap.sidebar.getSidebarMenus(id, user, params=params)
940 @decorators.merge_params
941 def getDjangoURLPatterns(self, params=None):
942 """Retrieves a list of sidebar entries for this view
944 Params usage:
945 The params dictionary is passed to the getDjangoURLPatterns
946 function in the soc.views.sitemap.sitemap module, see the
947 docstring of getDjangoURLPatterns on how it uses it.
949 Args:
950 params: a dict with params for this View
953 return sitemap.sitemap.getDjangoURLPatterns(params)