15.2.154. camcops_server.cc_modules.cc_view_classes

camcops_server/cc_modules/cc_view_classes.py


Copyright (C) 2012-2020 Rudolf Cardinal (rudolf@pobox.com).

This file is part of CamCOPS.

CamCOPS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

CamCOPS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.


Django-style class-based views for Pyramid. Adapted from Django’s views/generic/base.py and views/generic/edit.py.

Django has the following licence:

Copyright (c) Django Software Foundation and individual contributors.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.

    3. Neither the name of Django nor the names of its contributors may be
       used to endorse or promote products derived from this software
       without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

Custom views typically inherit from CreateView, DeleteView or UpdateView.

A Pyramid view function with a named route should create a view of the custom class, passing in the request, and return the results of its dispatch() method. For example:

@view_config(route_name="edit_server_created_patient")
def edit_server_created_patient(req: Request) -> Response:
    return EditServerCreatedPatientView(req).dispatch()

To provide a custom view class to create a new object in the database:

  • Inherit from CreateView.

  • Set the object_class property.

  • Set the form_class property.

  • Set the template_name property.

  • Override get_extra_context() for any extra parameters to pass to the template.

  • Set success_url or override get_success_url() to be the redirect on successful creation.

  • Override get_form_kwargs() for any extra parameters to pass to the form constructor.

  • For simple views, set the model_form_dict property to be a mapping of object properties to form parameters.

  • Override get_form_values() with any values additional to model_form_dict to populate the form.

  • Override ``save_object()` to do anything more than a simple record save (saving related objects, for example).

To provide a custom view class to delete an object from the database:

  • Inherit from DeleteView.

  • Set the object_class property.

  • Set the form_class property.

  • Set the template_name property.

  • Override get_extra_context(). for any extra parameters to pass to the template.

  • Set success_url or override get_success_url() to be the redirect on successful creation.

  • Override get_form_kwargs() for any extra parameters to pass to the form constructor.

  • Set the pk_param property to be the name of the parameter in the request that holds the unique/primary key of the object to be deleted.

  • Set the server_pk_name property to be the name of the property on the object that is the unique/primary key.

  • Override get_object() if the object cannot be retrieved with the above.

  • Override delete() to do anything more than a simple record delete; for example, to delete dependant objects

To provide a custom view class to update an object in the database:

  • Inherit from UpdateView.

  • Set the object_class property.

  • Set the form_class property.

  • Set the template_name property.

  • Override get_extra_context() for any extra parameters to pass to the template.

  • Set success_url or override get_success_url() to be the redirect on successful creation.

  • Override get_form_kwargs() for any extra parameters to pass to the form constructor.

  • Set the pk_param property to be the name of the parameter in the request that holds the unique/primary key of the object to be updated.

  • Set the server_pk_name property to be the name of the property on the object that is the unique/primary key.

  • Override get_object() if the object cannot be retrieved with the above.

  • For simple views, set the model_form_dict property to be a mapping of object properties to form parameters.

  • Override save_object() to do anything more than a simple record save (saving related objects, for example).

You can use mixins for settings common to multiple views.

Note

When we move to Python 3.8, there is typing.Protocol, which allows mixins to be type-checked properly. Currently we suppress warnings.

Some examples are in webview.py.

class camcops_server.cc_modules.cc_view_classes.BaseCreateView(request: CamcopsRequest)[source]

Base view for creating a new object instance.

Using this base class requires subclassing to provide a response mixin.

get() → Any[source]

Handle GET requests: instantiate a blank version of the form.

post() → Any[source]

Handle POST requests: instantiate a form instance with the passed POST variables and then check if it’s valid.

class camcops_server.cc_modules.cc_view_classes.BaseDeleteView(request: CamcopsRequest)[source]

Base view for deleting an object.

Using this base class requires subclassing to provide a response mixin.

delete() → None[source]

Delete the fetched object

form_valid(form: Form, appstruct: Dict[str, Any]) → pyramid.response.Response[source]

Called when the form is valid. Deletes the associated model.

get() → pyramid.response.Response[source]

Handle GET requests: fetch the object from the database, and renders a form with its data.

post() → pyramid.response.Response[source]

Handle POST requests: instantiate a form instance with the passed POST variables and then check if it’s valid.

class camcops_server.cc_modules.cc_view_classes.BaseFormView(request: CamcopsRequest)[source]

A base view for displaying a form.

class camcops_server.cc_modules.cc_view_classes.BaseUpdateView(request: CamcopsRequest)[source]

Base view for updating an existing object.

Using this base class requires subclassing to provide a response mixin.

get() → Any[source]

Handle GET requests: instantiate a blank version of the form.

post() → Any[source]

Handle POST requests: instantiate a form instance with the passed POST variables and then check if it’s valid.

class camcops_server.cc_modules.cc_view_classes.ContextMixin[source]

A default context mixin that passes the keyword arguments received by get_context_data() as the template context.

get_context_data(**kwargs: Any) → Dict[str, Any][source]

Provides context for a template, including the view argument and any additional context provided by get_extra_context().

get_extra_context() → Dict[str, Any][source]

Override to provide extra context, merged in by get_context_data().

class camcops_server.cc_modules.cc_view_classes.CreateView(request: CamcopsRequest)[source]

View for creating a new object, with a response rendered by a template.

class camcops_server.cc_modules.cc_view_classes.DeleteView(request: CamcopsRequest)[source]

View for deleting an object retrieved with self.get_object(), with a response rendered by a template.

class camcops_server.cc_modules.cc_view_classes.FormMixin[source]

Provide a way to show and handle a form in a request.

form_invalid(validation_error: deform.exception.ValidationFailure) → pyramid.response.Response[source]

Called when the form is invalid. Returns a response with a rendering of the invalid form.

form_valid(form: Form, appstruct: Dict[str, Any]) → pyramid.response.Response[source]

Called when the form is valid. Redirects to the supplied “success” URL.

get_cancel_url() → str[source]

Return the URL to redirect to when cancelling a form.

get_context_data(**kwargs: Any) → Dict[str, Any][source]

Insert the rendered form (as HTML) into the context dict.

get_form() → Form[source]

Return an instance of the form to be used in this view.

get_form_class() → Optional[Type[Form]][source]

Return the form class to use.

get_form_kwargs() → Dict[str, Any][source]

Return the keyword arguments for instantiating the form.

get_rendered_form() → str[source]

Returns the form, rendered as HTML.

get_success_url() → str[source]

Return the URL to redirect to after processing a valid form.

class camcops_server.cc_modules.cc_view_classes.FormView(request: CamcopsRequest)[source]

A view for displaying a form and rendering a template response.

class camcops_server.cc_modules.cc_view_classes.ModelFormMixin[source]

Represents an ORM object and an associated form.

form_valid(form: Form, appstruct: Dict[str, Any]) → pyramid.response.Response[source]

Called when the form is valid. Saves the associated model.

get_form_values() → Dict[str, Any][source]

Reads form values from the object (or provides an empty dictionary if there is no object yet).

save_object(appstruct: Dict[str, Any]) → None[source]

Saves the object in the database, from data provided via the form.

set_object_properties(appstruct: Dict[str, Any]) → None[source]

Sets properties of the object, from form data.

class camcops_server.cc_modules.cc_view_classes.ProcessFormView(request: CamcopsRequest)[source]

Render a form on GET and processes it on POST.

get() → pyramid.response.Response[source]

Handle GET requests: instantiate a blank version of the form.

post() → pyramid.response.Response[source]

Handle POST requests: instantiate a form instance with the passed POST variables and then check if it’s valid.

class camcops_server.cc_modules.cc_view_classes.SingleObjectMixin[source]

Represents a single ORM object, for use as a mixin.

get_context_data(**kwargs: Any) → Dict[str, Any][source]

Insert the single object into the context dict.

class camcops_server.cc_modules.cc_view_classes.TemplateResponseMixin[source]

A mixin that can be used to render a template.

render_to_response(context: Dict) → pyramid.response.Response[source]

Takes the supplied context, renders it through our specified template (set by template_name), and returns a pyramid.response.Response.

class camcops_server.cc_modules.cc_view_classes.UpdateView(request: CamcopsRequest)[source]

View for updating an object, with a response rendered by a template.

class camcops_server.cc_modules.cc_view_classes.View(request: CamcopsRequest)[source]

Simple parent class for all views

__init__(request: CamcopsRequest) → None[source]
Parameters

request – a camcops_server.cc_modules.cc_request.CamcopsRequest

dispatch() → pyramid.response.Response[source]

Try to dispatch to the right HTTP method (e.g. GET, POST). If a method doesn’t exist, defer to the error handler. Also defer to the error handler if the request method isn’t on the approved list.

http_method_not_allowed() → NoReturn[source]

Raise a pyramid.httpexceptions.HTTPMethodNotAllowed indicating that the selected HTTP method is not allowed.