64 def __init__(self, params=None): |
64 def __init__(self, params=None): |
65 """ |
65 """ |
66 |
66 |
67 Args: |
67 Args: |
68 params: This dictionary should be filled with the parameters |
68 params: This dictionary should be filled with the parameters |
69 specific to this entity, required fields are: |
69 specific to this entity. See the methods in this class on |
70 rights: This dictionary should be filled with the access check |
70 the fields it should contain, and how they are used. |
71 functions that should be called |
|
72 name: the name of the entity (names should have sentence-style caps) |
|
73 name_short: the short form name of the name ('org' vs 'organization') |
|
74 name_plural: the plural form of the name |
|
75 url_name: the name of the entity used in urls |
|
76 edit_form: the class of the Django form to be used when editing |
|
77 create_form: the class of the Django form to be used when creating |
|
78 edit_template: the Django template to be used for editing |
|
79 public_template: the Django template to be used as public page |
|
80 list_template: the Django template to be used as list page |
|
81 lists_template: the Django templates to search for the list page |
|
82 delete_redirect: the Django template to redirect to on delete |
|
83 create_redirect: the Django template to redirect to after creation |
|
84 save_message: the message to display when the entity is saved |
|
85 edit_params: the params to use when editing |
|
86 sidebar: the sidebar menu items for this view |
|
87 sidebar_defaults: a dictionary with defaults for the sidebar; each |
|
88 value in the dict is a two-tuple: |
|
89 (url_format, # supplied a single positional url_name |
|
90 menu_text_format) # supplied the params dict |
|
91 """ |
71 """ |
92 |
72 |
93 rights = {} |
73 rights = {} |
94 rights['unspecified'] = [] |
74 rights['unspecified'] = [] |
95 rights['any_access'] = [access.checkIsLoggedIn] |
75 rights['any_access'] = [access.checkIsLoggedIn] |
209 ) |
189 ) |
210 |
190 |
211 def public(self, request, page_name=None, params=None, **kwargs): |
191 def public(self, request, page_name=None, params=None, **kwargs): |
212 """Displays the public page for the entity specified by **kwargs. |
192 """Displays the public page for the entity specified by **kwargs. |
213 |
193 |
|
194 Params usage: |
|
195 rights: The rights dictionary is used to check if the user has |
|
196 the required rights to view the public page for this entity. |
|
197 See checkAccess for more details on how the rights dictionary |
|
198 is used to check access rights. |
|
199 error_public: The error_public value is used as template when |
|
200 the key values (as defined by the page's url) do not |
|
201 correspond to an existing entity. |
|
202 name: The name value is used to set the entity_type in the |
|
203 context so that the template can refer to it. |
|
204 public_template: The public_template value is used as template |
|
205 to display the public page of the found entity. |
|
206 |
214 Args: |
207 Args: |
215 request: the standard Django HTTP request object |
208 request: the standard Django HTTP request object |
216 page_name: the page name displayed in templates as page and header title |
209 page_name: the page name displayed in templates as page and header title |
217 params: a dict with params for this View |
210 params: a dict with params for this View |
218 kwargs: the Key Fields for the specified entity |
211 kwargs: the Key Fields for the specified entity |
219 """ |
212 """ |
220 |
213 |
221 params = dicts.merge(params, self._params) |
214 params = dicts.merge(params, self._params) |
222 |
215 |
223 try: |
216 try: |
224 self.checkAccess('public', request) |
217 self.checkAccess('public', request, rights=params['rights']) |
225 except out_of_band.Error, error: |
218 except out_of_band.Error, error: |
226 return error.response(request) |
219 return error.response(request) |
227 |
220 |
228 # create default template context for use with any templates |
221 # create default template context for use with any templates |
229 context = helper.responses.getUniversalContext(request) |
222 context = helper.responses.getUniversalContext(request) |
251 return helper.responses.respond(request, template, context) |
244 return helper.responses.respond(request, template, context) |
252 |
245 |
253 def create(self, request, page_name=None, params=None, **kwargs): |
246 def create(self, request, page_name=None, params=None, **kwargs): |
254 """Displays the create page for this entity type. |
247 """Displays the create page for this entity type. |
255 |
248 |
|
249 Params usage: |
|
250 The params dictionary is passed on to edit, see the docstring |
|
251 for edit on how it uses it. |
|
252 |
256 Args: |
253 Args: |
257 request: the standard Django HTTP request object |
254 request: the standard Django HTTP request object |
258 page_name: the page name displayed in templates as page and header title |
255 page_name: the page name displayed in templates as page and header title |
259 params: a dict with params for this View |
256 params: a dict with params for this View |
260 kwargs: not used for create() |
257 kwargs: not used for create() |
275 return self.edit(request, page_name=page_name, params=params, |
272 return self.edit(request, page_name=page_name, params=params, |
276 seed=kwargs, **empty_kwargs) |
273 seed=kwargs, **empty_kwargs) |
277 |
274 |
278 def edit(self, request, page_name=None, params=None, seed=None, **kwargs): |
275 def edit(self, request, page_name=None, params=None, seed=None, **kwargs): |
279 """Displays the edit page for the entity specified by **kwargs. |
276 """Displays the edit page for the entity specified by **kwargs. |
|
277 |
|
278 Params usage: |
|
279 The params dictionary is passed on to either editGet or editPost |
|
280 depending on the method type of the request. See the docstring |
|
281 for editGet and editPost on how they use it. |
|
282 |
|
283 rights: The rights dictionary is used to check if the user has |
|
284 the required rights to edit (or create) a new entity. |
|
285 See checkAccess for more details on how the rights dictionary |
|
286 is used to check access rights. |
|
287 name: The name value is used to construct the message_fmt of the |
|
288 raised error when there key_values do not define an existing |
|
289 entity. See DEF_CREATE_NEW_ENTITY_MSG_FMT on how the name |
|
290 (and the lower() version of it) is used. |
|
291 missing_redirect: The missing_redirect value is also used to |
|
292 construct the message_fmt mentioned above. |
|
293 error_public: The error_public value is used as the template for |
|
294 the error response mentioned above. |
280 |
295 |
281 Args: |
296 Args: |
282 request: the standard Django HTTP request object |
297 request: the standard Django HTTP request object |
283 page_name: the page name displayed in templates as page and header title |
298 page_name: the page name displayed in templates as page and header title |
284 params: a dict with params for this View |
299 params: a dict with params for this View |
314 return self.editPost(request, entity, context, params) |
329 return self.editPost(request, entity, context, params) |
315 else: |
330 else: |
316 return self.editGet(request, entity, context, seed, params) |
331 return self.editGet(request, entity, context, seed, params) |
317 |
332 |
318 def editPost(self, request, entity, context, params): |
333 def editPost(self, request, entity, context, params): |
319 """Same as edit, but on POST. |
334 """Processes POST requests for the specified entity |
|
335 |
|
336 Params usage: |
|
337 The params dictionary is passed to _constructResponse when the |
|
338 form is not valid (see edit_form and create_form below). See |
|
339 the docstring of _constructResponse on how it uses it. |
|
340 |
|
341 edit_form: The edit_form value is used as form when there is an |
|
342 existing entity. It is provided with with the request.POST |
|
343 dictionary on construction. The collectCleanedFields method |
|
344 is called with the newly constructed form. If the form is |
|
345 not valid, it is passed as argument to _constructResponse. |
|
346 create_form: The create_form value is used in a similar way to |
|
347 edit_form, only it is used when there is no existing entity. |
|
348 edit_redirect: The edit_redirect value is used as the first part |
|
349 of the url if the form was valid. The last part of the url is |
|
350 created using the getKeySuffix method of the _logic object. |
|
351 edit_params: The edit_params dictionary is used as argument to |
|
352 redirectToChangedSuffix, it will be appended to the url in the |
|
353 standard ?key=value format. |
|
354 |
|
355 Args: |
|
356 request: a django request object |
|
357 entity: the entity that will be modified or created, may be None |
|
358 context: the context dictionary that will be provided to Django |
|
359 params: a dict with params for this View |
320 """ |
360 """ |
321 |
361 |
322 params = dicts.merge(params, self._params) |
362 params = dicts.merge(params, self._params) |
323 |
363 |
324 if entity: |
364 if entity: |
351 return helper.responses.redirectToChangedSuffix( |
391 return helper.responses.redirectToChangedSuffix( |
352 request, None, new_suffix, |
392 request, None, new_suffix, |
353 params=page_params) |
393 params=page_params) |
354 |
394 |
355 def editGet(self, request, entity, context, seed, params): |
395 def editGet(self, request, entity, context, seed, params): |
356 """Same as edit, but on GET. |
396 """Processes GET requests for the specified entity |
|
397 |
|
398 Params usage: |
|
399 The params dictionary is passed to _constructResponse, see the |
|
400 docstring of _constructResponse on how it uses it. |
|
401 |
|
402 save_message: The save_message list is used as argument to |
|
403 getSingleIndexedParamValue when an existing entity was saved. |
|
404 edit_form: The edit_form is used as form if there is an existing |
|
405 entity. The existing entity is passed as instance to it on |
|
406 construction. If key_name is part of it's fields it will be |
|
407 set to the entity's key().name() value. It is also passed as |
|
408 argument to the _editGet method. See the docstring for |
|
409 _editGet on how it uses it. |
|
410 create_form: The create_form is used as form if there was no |
|
411 existing entity. If the seed argument is present, it is passed |
|
412 as the 'initial' argument on construction. Otherwise, it is |
|
413 called with no arguments. |
|
414 |
|
415 Args: |
|
416 request: the django request object |
|
417 entity: the entity that will be edited, may be None |
|
418 context: the context dictionary that will be provided to django |
|
419 seed: if no entity is provided, the initial values for the new entity |
|
420 params: a dict with paras for this View |
357 """ |
421 """ |
358 |
422 |
359 params = dicts.merge(params, self._params) |
423 params = dicts.merge(params, self._params) |
360 suffix = self._logic.getKeySuffix(entity) |
424 suffix = self._logic.getKeySuffix(entity) |
361 |
425 |
372 request, self.DEF_SUBMIT_MSG_PARAM_NAME, |
436 request, self.DEF_SUBMIT_MSG_PARAM_NAME, |
373 values=params['save_message']) |
437 values=params['save_message']) |
374 |
438 |
375 # populate form with the existing entity |
439 # populate form with the existing entity |
376 form = params['edit_form'](instance=entity) |
440 form = params['edit_form'](instance=entity) |
|
441 |
377 if 'key_name' in form.fields: |
442 if 'key_name' in form.fields: |
378 form.fields['key_name'].initial = entity.key().name() |
443 form.fields['key_name'].initial = entity.key().name() |
|
444 |
379 self._editGet(request, entity, form) |
445 self._editGet(request, entity, form) |
380 else: |
446 else: |
381 if seed: |
447 if seed: |
382 self._editSeed(request, seed) |
448 self._editSeed(request, seed) |
383 form = params['create_form'](initial=seed) |
449 form = params['create_form'](initial=seed) |
392 Args: |
458 Args: |
393 request: the standard Django HTTP request object |
459 request: the standard Django HTTP request object |
394 page_name: the page name displayed in templates as page and header title |
460 page_name: the page name displayed in templates as page and header title |
395 params: a dict with params for this View |
461 params: a dict with params for this View |
396 filter: a dict for the properties that the entities should have |
462 filter: a dict for the properties that the entities should have |
|
463 |
|
464 Params usage: |
|
465 The params dictionary is passed as argument to getListContent in |
|
466 the soc.views.helper.list module. See the docstring for |
|
467 getListContent on how it uses it. |
|
468 The params dictionary is also passed as argument to the _list |
|
469 method. See the docstring for _list on how it uses it. |
|
470 |
|
471 rights: The rights dictionary is used to check if the user has |
|
472 the required rights to list all entities of this View's type. |
|
473 See checkAccess for more details on how the rights dictionary |
|
474 is used to check access rights. |
397 """ |
475 """ |
398 |
476 |
399 params = dicts.merge(params, self._params) |
477 params = dicts.merge(params, self._params) |
400 |
478 |
401 try: |
479 try: |
402 self.checkAccess('list', request) |
480 self.checkAccess('list', request, rights=params['rights']) |
403 except out_of_band.Error, error: |
481 except out_of_band.Error, error: |
404 return error.response(request) |
482 return error.response(request) |
405 |
483 |
406 content = helper.lists.getListContent(request, params, self._logic, filter) |
484 content = helper.lists.getListContent(request, params, self._logic, filter) |
407 contents = [content] |
485 contents = [content] |
414 Args: |
492 Args: |
415 request: the standard Django HTTP request object |
493 request: the standard Django HTTP request object |
416 params: a dict with params for this View |
494 params: a dict with params for this View |
417 contents: a list of content dicts |
495 contents: a list of content dicts |
418 page_name: the page name displayed in templates as page and header title |
496 page_name: the page name displayed in templates as page and header title |
|
497 |
|
498 Params usage: |
|
499 name: The name value is used to set the entity_type in the |
|
500 context so that the template can refer to it. |
|
501 name_plural: The name_plural value is used to set |
|
502 the entity_type_plural value in the context so that the |
|
503 template can refer to it. |
|
504 list_template: The list_template value is used as template for |
|
505 to display the list of all entities for this View. |
419 """ |
506 """ |
420 |
507 |
421 context = helper.responses.getUniversalContext(request) |
508 context = helper.responses.getUniversalContext(request) |
422 context['page_name'] = page_name |
509 context['page_name'] = page_name |
423 context['list'] = soc.logic.lists.Lists(contents) |
510 context['list'] = soc.logic.lists.Lists(contents) |
435 Args: |
522 Args: |
436 request: the standard Django HTTP request object |
523 request: the standard Django HTTP request object |
437 page_name: the page name displayed in templates as page and header title |
524 page_name: the page name displayed in templates as page and header title |
438 params: a dict with params for this View |
525 params: a dict with params for this View |
439 kwargs: The Key Fields for the specified entity |
526 kwargs: The Key Fields for the specified entity |
|
527 |
|
528 Params usage: |
|
529 rights: The rights dictionary is used to check if the user has |
|
530 the required rights to delete the specified entity. |
|
531 See checkAccess for more details on how the rights dictionary |
|
532 is used to check access rights. |
|
533 name: used in the same way as in edit(), see it's docstring for |
|
534 a more detailed explanation on how it is used. |
|
535 missing_redirect: see name |
|
536 error_edit: see name |
|
537 delete_redirect: The delete_redirect value is used as the url to |
|
538 redirect to after having successfully deleted the entity. |
440 """ |
539 """ |
441 |
540 |
442 params = dicts.merge(params, self._params) |
541 params = dicts.merge(params, self._params) |
443 |
542 |
444 try: |
543 try: |
445 self.checkAccess('delete', request) |
544 self.checkAccess('delete', request, rights=params['rights']) |
446 except out_of_band.Error, error: |
545 except out_of_band.Error, error: |
447 return error.response(request) |
546 return error.response(request) |
448 |
547 |
449 # create default template context for use with any templates |
548 # create default template context for use with any templates |
450 context = helper.responses.getUniversalContext(request) |
549 context = helper.responses.getUniversalContext(request) |
531 def _constructResponse(self, request, entity, context, form, params): |
630 def _constructResponse(self, request, entity, context, form, params): |
532 """Updates the context and returns a response for the specified arguments. |
631 """Updates the context and returns a response for the specified arguments. |
533 |
632 |
534 Args: |
633 Args: |
535 request: the django request object |
634 request: the django request object |
536 entity: the entity that is used |
635 entity: the entity that is used and set in the context |
537 context: the context to be used |
636 context: the context to be used |
538 form: the form that will be used |
637 form: the form that will be used and set in the context |
539 params: a dict with params for this View |
638 params: a dict with params for this View |
|
639 |
|
640 Params usage: |
|
641 name: The name_plural value is used to set the entity_type |
|
642 value in the context so that the template can refer to it. |
|
643 name_plural: same as name, but used to set entity_type_plural |
|
644 name_short: same as name, but used to set entity_type_short |
|
645 url_name: same as name, but used to set entity_type_url |
|
646 edit_template: The edit_template value is used as template when |
|
647 there is an existing entity to display the edit page for the |
|
648 specified entity. |
|
649 create_template: similar to edit_template, but is used when |
|
650 there is no existing entity. |
540 """ |
651 """ |
541 |
652 |
542 suffix = self._logic.getKeySuffix(entity) |
653 suffix = self._logic.getKeySuffix(entity) |
543 |
654 |
544 context['form'] = form |
655 context['form'] = form |
560 """Runs all the defined checks for the specified type |
671 """Runs all the defined checks for the specified type |
561 |
672 |
562 Args: |
673 Args: |
563 access_type: the type of request (such as 'list' or 'edit') |
674 access_type: the type of request (such as 'list' or 'edit') |
564 request: the Django request object |
675 request: the Django request object |
|
676 rights: A dictionary containing access check functions |
|
677 |
|
678 Rights usage: The rights dictionary is used to check if the |
|
679 current user is allowed to view the page specified. The |
|
680 functions defined in this dictionary are always called with the |
|
681 django request object as argument. |
|
682 On any request, regardless of what type, the functions in the |
|
683 'any_access' value are called. |
|
684 If the specified type is not in the rights dictionary, all the |
|
685 functions in the 'unspecified' value are called. |
|
686 When the specified type _is_ in the rights dictionary, all the |
|
687 functions in that access_type's value are called. |
565 |
688 |
566 Returns: |
689 Returns: |
567 True: If all the required access checks have been made successfully |
690 True: If all the required access checks have been made successfully |
568 False: If a check failed, in this case self._response will contain |
691 False: If a check failed, in this case self._response will contain |
569 the response provided by the failed access check. |
692 the response provided by the failed access check. |
575 for check in rights['any_access']: |
698 for check in rights['any_access']: |
576 check(request) |
699 check(request) |
577 |
700 |
578 if access_type not in rights: |
701 if access_type not in rights: |
579 for check in rights['unspecified']: |
702 for check in rights['unspecified']: |
580 # No checks defined, so do the 'generic check' and bail out |
703 # No checks defined, so do the 'generic' checks and bail out |
581 check(request) |
704 check(request) |
582 return |
705 return |
583 |
706 |
584 for check in rights[access_type]: |
707 for check in rights[access_type]: |
585 check(request) |
708 check(request) |
587 def collectCleanedFields(self, form): |
710 def collectCleanedFields(self, form): |
588 """Collects all cleaned fields and returns them with the key_name. |
711 """Collects all cleaned fields and returns them with the key_name. |
589 |
712 |
590 Args: |
713 Args: |
591 form: The form from which the cleaned fields should be collected |
714 form: The form from which the cleaned fields should be collected |
|
715 |
|
716 Returns: All the fields that are in the form's cleaned_data |
|
717 property are returned. If there is a key_name field, it is not |
|
718 included in the returend fields, instead, it is returned as the |
|
719 first element in the returned tuple. If no key_name field is |
|
720 present, None is returned as first value instead. |
592 """ |
721 """ |
593 |
722 |
594 fields = {} |
723 fields = {} |
595 |
724 |
596 key_name = None |
725 key_name = None |
601 fields[field] = value |
730 fields[field] = value |
602 |
731 |
603 return key_name, fields |
732 return key_name, fields |
604 |
733 |
605 def getKeyFieldsPattern(self, params): |
734 def getKeyFieldsPattern(self, params): |
606 """ |
735 """Returns the Django pattern for this View's entity |
|
736 |
|
737 Params usage: |
|
738 key_fields_prefix: The key_fields_prefix value is used as the |
|
739 first part of the returned pattern. |
607 """ |
740 """ |
608 |
741 |
609 names = self._logic.getKeyFieldNames() |
742 names = self._logic.getKeyFieldNames() |
610 patterns = params['key_fields_prefix'] |
743 patterns = params['key_fields_prefix'] |
611 |
744 |
615 |
748 |
616 result = '/'.join(patterns) |
749 result = '/'.join(patterns) |
617 return result |
750 return result |
618 |
751 |
619 def _getSidebarItems(self, params): |
752 def _getSidebarItems(self, params): |
620 """Retrieves a list of sidebar entries for this view from self._params. |
753 """Retrieves a list of sidebar entries for this view |
621 |
754 |
622 If params['sidebar'] is None default entries will be constructed |
755 Params usage: |
|
756 The params dictionary is provided to the menu_text's format. |
|
757 |
|
758 sidebar: The sidebar value is returned directly if non-False |
|
759 sidebar_defaults: The sidebar_defaults are used to construct the |
|
760 sidebar items for this View. It is expected to be a tuple of |
|
761 three items, the item's url, it's menu_text, and it's |
|
762 access_type, see getSidebarLinks on how access_type is used. |
|
763 sidebar_additional: The sidebar_additional values are appended |
|
764 to the list of items verbatim, and should be in the format |
|
765 expected by getSidebarLinks. |
|
766 |
|
767 Args: |
|
768 params: a dict with params for this View. |
623 """ |
769 """ |
624 |
770 |
625 # Return the found result |
771 # Return the found result |
626 if params['sidebar']: |
772 if params['sidebar']: |
627 return params['sidebar'] |
773 return params['sidebar'] |
642 return result |
788 return result |
643 |
789 |
644 def getSidebarLinks(self, request, params=None): |
790 def getSidebarLinks(self, request, params=None): |
645 """Returns an dictionary with one sidebar entry. |
791 """Returns an dictionary with one sidebar entry. |
646 |
792 |
647 Args: |
793 Calls _getSidebarItems to retrieve the items that should be in the |
648 params: see __init__ |
794 menu. Expected is a tuple with an url, a menu_text, and an |
|
795 access_type. The access_type is then passed to checkAccess, if it |
|
796 raises out_of_band.Error, the item will not be added. |
|
797 |
|
798 Args: |
|
799 request: the django request object |
|
800 params: a dict with params for this View |
|
801 |
|
802 Params usage: |
|
803 The params dictionary is passed as argument to _getSidebarItems, |
|
804 see the docstring of _getSidebarItems on how it uses it. |
|
805 |
|
806 rights: The rights dictionary is used to check if the user has |
|
807 the required rights to see a sidebar item. |
|
808 See checkAccess for more details on how the rights dictionary |
|
809 is used to check access rights. |
|
810 sidebar_heading: The sidebar_heading value is used to set the |
|
811 heading variable in the result. |
|
812 name: The name value is used if sidebar_heading is not present. |
|
813 |
|
814 Returns: A dictionary is returned with it's 'heading' value set |
|
815 as explained above. It's 'items' value is constructed by |
|
816 calling _getSidebarItems. It constists of dictionaries with a |
|
817 url and a title field. |
649 """ |
818 """ |
650 |
819 |
651 params = dicts.merge(params, self._params) |
820 params = dicts.merge(params, self._params) |
652 rights = params['rights'] |
821 rights = params['rights'] |
653 |
822 |
676 def getDjangoURLPatterns(self, params=None): |
845 def getDjangoURLPatterns(self, params=None): |
677 """Retrieves a list of sidebar entries for this view from self._params. |
846 """Retrieves a list of sidebar entries for this view from self._params. |
678 |
847 |
679 If self._params['django_patterns'] is None default entries will be |
848 If self._params['django_patterns'] is None default entries will be |
680 constructed. |
849 constructed. |
|
850 |
|
851 Params usage: |
|
852 The params dictionary is passed to the getKeyFieldsPatterns |
|
853 method, see it's docstring on how it is used. |
|
854 django_patterns: The django_patterns value is returned directly |
|
855 if it is non-False. |
|
856 django_patterns_defaults: The dajngo_patterns_defaults value is |
|
857 used to construct the url patterns. It is expected to be a |
|
858 list of tuples. The tuples should contain an url, a module |
|
859 name, and the name of the url. The name is used as the |
|
860 page_name passed as keyword argument, but also as the name |
|
861 by which the url is known to Django internally. |
|
862 url_name: The url_name argument is passed as argument to each |
|
863 url, together with the link_id pattern, the link_id core |
|
864 pattern, and the key fields for this View. |
|
865 |
|
866 Args: |
|
867 params: a dict with params for this View |
681 """ |
868 """ |
682 |
869 |
683 params = dicts.merge(params, self._params) |
870 params = dicts.merge(params, self._params) |
684 |
871 |
685 # Return the found result |
872 # Return the found result |