# HG changeset patch # User Todd Larsen # Date 1222702310 0 # Node ID 832335761384119a418557fe6ba48e6ff78774f1 # Parent 4a86df7512229d2791543cdbd219d52b385fe87e Make use of PolyModel for Works, Documents, etc. Add some (but not all) of the missing Models related to Documents. Refactor site settings to be useful for any "/home" page view. Make the resulting home settings store a reference to the Document, rather than looking up the Document by a hard-code key name. This is to set the stage for Document editing being generic, and then being able to select from some existing documents which one to use as the "/home" static content. This makes it possible to pre-edit several Documents, have them Reviewed, and then quickly change the "/home" page content as a setting, rather than editing the Document in the settings form (though settings forms might still embed the current document into their form for convenience). Patch by: Todd Larsen Review by: Pawel Solyga Review URL: http://codereviews.googleopensourceprograms.com/1001 diff -r 4a86df751222 -r 832335761384 app/soc/logic/document.py --- a/app/soc/logic/document.py Mon Sep 29 14:03:45 2008 +0000 +++ b/app/soc/logic/document.py Mon Sep 29 15:31:50 2008 +0000 @@ -21,40 +21,33 @@ '"Pawel Solyga" ', ] + from google.appengine.ext import db +from soc.logic import key_name + import soc.models.document import soc.logic.model -def getDocumentFromPath(path): + +def getDocument(path, link_name): """Returns Document entity for a given path, or None if not found. Args: path: a request path of the Document that uniquely identifies it """ # lookup by Doc:path key name - key_name = getDocumentKeyNameForPath(path) + name = key_name.nameDocument(path, link_name) - if key_name: - document = soc.models.document.Document.get_by_key_name(key_name) + if name: + document = soc.models.document.Document.get_by_key_name(name) else: document = None return document -def getDocumentKeyNameForPath(path): - """Return a Datastore key_name for a Document from the path. - - Args: - path: a request path of the Document that uniquely identifies it - """ - if not path: - return None - return 'Doc:%s' % path - - -def updateOrCreateDocumentFromPath(path, **document_properties): +def updateOrCreateDocument(path, **document_properties): """Update existing Document entity, or create new one with supplied properties. Args: @@ -68,13 +61,13 @@ supplied path and properties. """ # attempt to retrieve the existing Document - document = getDocumentFromPath(path) + document = getDocument(path, document_properties['link_name']) if not document: # document did not exist, so create one in a transaction - key_name = getDocumentKeyNameForPath(path) + name = key_name.nameDocument(path, document_properties['link_name']) document = soc.models.document.Document.get_or_insert( - key_name, **document_properties) + name, **document_properties) # there is no way to be sure if get_or_insert() returned a new Document or # got an existing one due to a race, so update with document_properties anyway, diff -r 4a86df751222 -r 832335761384 app/soc/logic/key_name.py --- a/app/soc/logic/key_name.py Mon Sep 29 14:03:45 2008 +0000 +++ b/app/soc/logic/key_name.py Mon Sep 29 15:31:50 2008 +0000 @@ -22,15 +22,32 @@ ] +import soc.models.document import soc.models.site_settings import soc.models.user def nameSiteSettings(path): """Returns a SiteSettings key name constructed from a supplied path.""" - return '%s:%s' % (soc.models.site_settings.SiteSettings.__name__, path) + return '%(type)s:%(path)s' % { + 'type': soc.models.site_settings.SiteSettings.__name__, + 'path': path, + } + + +def nameDocument(path, link_name): + """Returns a Document key name constructed from a path and link name.""" + return '%(type)s:%(path)s/%(link_name)s' % { + 'type': soc.models.document.Document.__name__, + 'path': path, + 'link_name': link_name, + } def nameUser(email): """Returns a User key name constructed from a supplied email address.""" - return '%s:%s' % (soc.models.user.User.__name__, email) + return '%(type)s:%(email)s' % { + 'type': soc.models.user.User.__name__, + 'email': email, + } + diff -r 4a86df751222 -r 832335761384 app/soc/logic/site/settings.py --- a/app/soc/logic/site/settings.py Mon Sep 29 14:03:45 2008 +0000 +++ b/app/soc/logic/site/settings.py Mon Sep 29 15:31:50 2008 +0000 @@ -29,36 +29,24 @@ import soc.logic.model -def getSiteSettingsFromPath(path): +def getSiteSettings(path): """Returns SiteSettings entity for a given path, or None if not found. Args: path: a request path of the SiteSettings that uniquely identifies it """ # lookup by Settings:path key name - key_name = getSiteSettingsKeyNameForPath(path) + name = key_name.nameSiteSettings(path) - if key_name: - site_settings = soc.models.site_settings.SiteSettings.get_by_key_name(key_name) + if name: + site_settings = soc.models.site_settings.SiteSettings.get_by_key_name(name) else: site_settings = None return site_settings -def getSiteSettingsKeyNameForPath(path): - """Return a Datastore key_name for a SiteSettings from the path. - - Args: - path: a request path of the SiteSettings that uniquely identifies it - """ - if not path: - return None - - return key_name.nameSiteSettings(path) - - -def updateOrCreateSiteSettingsFromPath(path, **site_settings_properties): +def updateOrCreateSiteSettings(path, **site_settings_properties): """Update existing SiteSettings entity, or create new one with supplied properties. Args: @@ -72,13 +60,13 @@ supplied path and properties. """ # attempt to retrieve the existing Site Settings - site_settings = getSiteSettingsFromPath(path) + site_settings = getSiteSettings(path) if not site_settings: # site settings did not exist, so create one in a transaction - key_name = getSiteSettingsKeyNameForPath(path) + name = key_name.nameSiteSettings(path) site_settings = soc.models.site_settings.SiteSettings.get_or_insert( - key_name, **site_settings_properties) + name, **site_settings_properties) # there is no way to be sure if get_or_insert() returned a new SiteSettings or # got an existing one due to a race, so update with site_settings_properties anyway, diff -r 4a86df751222 -r 832335761384 app/soc/models/document.py --- a/app/soc/models/document.py Mon Sep 29 14:03:45 2008 +0000 +++ b/app/soc/models/document.py Mon Sep 29 15:31:50 2008 +0000 @@ -20,50 +20,44 @@ '"Pawel Solyga" ', ] + from google.appengine.ext import db +import polymodel + from django.utils.translation import ugettext_lazy -from soc.models import base import soc.models.user +import soc.models.work -class Document(base.ModelWithFieldAttributes): +class Document(soc.models.work.Work): """Model of a Document. - Document is used for things like FAQs, front page text etc. + Document is used for things like FAQs, front page text, etc. + + The specific way that the properties and relations inherited from Work + are used with a Document are described below. + + work.title: the title of the Document + + work.abstract: document summary displayed as a snippet in Document + list views + + work.authors: the Authors of the Work referred to by this relation + are the authors of the Document + + work.reviews: reviews of the Document by Reviewers """ - #: Document title displayed on the top of the page - title = db.StringProperty(required=True, - verbose_name=ugettext_lazy('Title')) - title.help_text = ugettext_lazy( - 'Document title displayed on the top of the page') - - #: Document link name used in URLs - link_name = db.StringProperty(required=True, - verbose_name=ugettext_lazy('Link name')) - link_name.help_text = ugettext_lazy('Document link name used in URLs') - - #: Document short name used for sidebar menu - short_name = db.StringProperty(required=True, - verbose_name=ugettext_lazy('Short name')) - short_name.help_text = ugettext_lazy( - 'Document short name used for sidebar menu') - - #: Content of the document - content = db.TextProperty( - verbose_name=ugettext_lazy('Content')) - - #: Date when the document was created. - created = db.DateTimeProperty(auto_now_add=True) - - #: Date when the document was modified. - modified = db.DateTimeProperty(auto_now=True) + #: Required db.TextProperty containing the Document contents. + #: Unlike the work.abstract, which is considered "public" information, + #: the content is only to be displayed to Persons in Roles eligible to + #: view them (which may be anyone, for example, with the site front page). + content = db.TextProperty(verbose_name=ugettext_lazy('Content')) #: User who created this document. + #: TODO(pawel.solyga): replace this with WorkAuthors relation user = db.ReferenceProperty(reference_class=soc.models.user.User, required=True, collection_name='documents') - - diff -r 4a86df751222 -r 832335761384 app/soc/models/documentation.py --- a/app/soc/models/documentation.py Mon Sep 29 14:03:45 2008 +0000 +++ b/app/soc/models/documentation.py Mon Sep 29 15:31:50 2008 +0000 @@ -21,41 +21,43 @@ '"Sverre Rabbelier" ', ] + from google.appengine.ext import db -from soc import models -import soc.models.person +import soc.models.role import soc.models.work -class Documentation(db.Model): - """Model of Documentation, which is a Work authored by Administrators.""" - - #: A required 1:1 relationship with a Work entity that contains the - #: general "work" properties of the Documentation. The - #: back-reference in the Work model is a Query named - #: 'documentation'. - #: - #: work.authors: The Authors of the Work referred to by this - #: relation are the Administrators (or Hosts) creating the - #: Documentation. - #: - #: work.title: The title of the Documentation (e.g. "Verification - #: of Eligibility"). - #: - #: work.abstract: Summary of the contents of the 'attachment', or - #: just an indication that the required documentation was - #: supplied but is not actually attached. - #: - #: work.reviews: Annotations to the Documentation made by other - #: Administrators. - work = db.ReferenceProperty(reference_class=models.work.Work, required=True, - collection_name="proposal") + +class Documentation(soc.models.work.Work): + """Model of Documentation, which is a Work authored by Administrators. + + Documentation is items like tax forms, letters from schools confirming + enrollment, etc., (often scanned in) that are attached to a Role as + documentation related to that Role. + + The specific way that some properties and relations inherited from Work + are used with a piece of Documentation are described below. + + work.title: The title of the Documentation (e.g. "Verification + of Eligibility"). + + work.abstract: Summary of the contents of the 'attachment', or + just an indication that the required documentation was + supplied but is not actually attached. + + work.authors: The Authors of the Work referred to by this + relation are the Administrators (or Hosts) creating the + Documentation. + + work.reviews: Annotations to the Documentation made by other + Administrators. + """ #: a many:1 relationship of Documentation entities that pertain - #: to a single Person. The back-reference in the Person model is a - #: Query named 'docs'. - person = db.ReferenceProperty(reference_class=models.person.Person, - collection_name="docs") + #: to a single Role. The back-reference in the Role model is a + #: Query named 'documentation'. + role = db.ReferenceProperty(reference_class=soc.models.role.Role, + collection_name='documentation') #: An optional db.BlobProperty containing the documentation #: (usually a scanned image of a paper document or a PDF file). diff -r 4a86df751222 -r 832335761384 app/soc/models/home_settings.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/soc/models/home_settings.py Mon Sep 29 15:31:50 2008 +0000 @@ -0,0 +1,55 @@ +#!/usr/bin/python2.5 +# +# Copyright 2008 the Melange authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""This module contains the HomeSettings Model.""" + +__authors__ = [ + '"Pawel Solyga" ', + '"Todd Larsen" ', +] + + +from google.appengine.ext import db + +import polymodel + +from django.utils.translation import ugettext_lazy + +import soc.models.document + + +class HomeSettings(polymodel.PolyModel): + """Model that stores settings for various Home pages. + + This Model is the basis for more specific "/home" view settings, such as + SiteSettings, ProgramSettings, etc. + """ + + #: Reference to Document containing the contents of the "/home" page + home = db.ReferenceProperty( + reference_class=soc.models.document.Document, + collection_name='home') + home.help_text = ugettext_lazy( + 'Document to be used as the "/home" page static contents.') + + #: Valid ATOM or RSS feed url or None if unused. Feed entries are shown + #: on the site page using Google's JavaScript blog widget + feed_url = db.LinkProperty(verbose_name=ugettext_lazy('Feed URL')) + feed_url.help_text = ugettext_lazy( + 'The URL should be a valid ATOM or RSS feed. ' + 'Feed entries are shown on the home page.') + + diff -r 4a86df751222 -r 832335761384 app/soc/models/proposal.py --- a/app/soc/models/proposal.py Mon Sep 29 14:03:45 2008 +0000 +++ b/app/soc/models/proposal.py Mon Sep 29 15:31:50 2008 +0000 @@ -21,38 +21,38 @@ '"Pawel Solyga" ', ] + from google.appengine.ext import db -from soc import models -from soc.models import base import soc.models.work -class Proposal(base.ModelWithFieldAttributes): + +class Proposal(soc.models.work.Work): """Model of a Proposal, which is a specific form of a Work. + The specific way that the properties and relations inherited from Work + are used with a Proposal are described below. + + work.title: the title of the Proposal + + work.abstract: publicly displayed as a proposal abstract or summary + + work.authors: the Authors of the Work referred to by this relation + are the authors of the Proposal + + work.reviews: reviews of the Proposal by Reviewers + A Proposal entity participates in the following relationships implemented as a db.ReferenceProperty elsewhere in another db.Model: tasks) an optional 1:many relationship of Task entities using the Proposal as their foundation. This relation is implemented as the 'tasks' back-reference Query of the Task model 'proposal' reference. - """ - #: Required 1:1 relationship with a Work entity that contains the - #: general "work" properties of the Proposal. The back-reference in the Work - #: model is a Query named 'proposal'. - #: - #: work.authors: the Authors of the Work referred to by this relation - #: are the authors of the Proposal. - #: work.title: the title of the Proposal. - #: work.abstract: publicly displayed as a proposal abstract or summary. - #: work.reviews: reviews of the Proposal by Reviewers. - work = db.ReferenceProperty(reference_class=models.work.Work, required=True, - collection_name="proposal") - #: Required db.TextProperty describing the proposal in detail. #: Unlike the work.abstract, which is considered "public" information, - #: the contents of 'details' is only to be displayed to Persons in roles + #: the contents of 'details' is only to be displayed to Persons in Roles #: that have a "need to know" the details. details = db.TextProperty(required=True) + diff -r 4a86df751222 -r 832335761384 app/soc/models/site_settings.py --- a/app/soc/models/site_settings.py Mon Sep 29 14:03:45 2008 +0000 +++ b/app/soc/models/site_settings.py Mon Sep 29 15:31:50 2008 +0000 @@ -20,21 +20,17 @@ '"Pawel Solyga" ', ] + from google.appengine.ext import db from django.utils.translation import ugettext_lazy -from soc.models import base +import soc.models.home_settings -class SiteSettings(base.ModelWithFieldAttributes): + +class SiteSettings(soc.models.home_settings.HomeSettings): """Model of a SiteSettings, which stores per site configuration.""" - - #: Valid ATOM or RSS feed url or None if unused. Feed entries are shown - #: on the site page using Google's JavaScript blog widget - feed_url = db.LinkProperty( - verbose_name=ugettext_lazy('Feed URL')) - feed_url.help_text = ugettext_lazy( - 'The URL should be a valid ATOM or RSS feed. ' - 'Feed entries are shown on the site page.') - + # there is currently no site-specific configuration that is different from + # other /home page configuration (but this will change...) + pass diff -r 4a86df751222 -r 832335761384 app/soc/models/work.py --- a/app/soc/models/work.py Mon Sep 29 14:03:45 2008 +0000 +++ b/app/soc/models/work.py Mon Sep 29 15:31:50 2008 +0000 @@ -22,29 +22,21 @@ ] from google.appengine.ext import db -from soc.models import base -class Work(base.ModelWithFieldAttributes): - """Model of a Work created by one or more Authors. +from django.utils.translation import ugettext_lazy - Work is a "base entity" of other more specific "works" created by "persons". +import polymodel - A Work entity participates in the following relationships implemented - as a db.ReferenceProperty elsewhere in another db.Model: - proposal), survey), documentation) - a 1:1 relationship with each entity containing a more specific type of - "work". These relationships are represented explicitly in the other - "work" models by a db.ReferenceProperty named 'work'. The - collection_name argument to db.ReferenceProperty should be set to the - singular of the entity model name of the other "work" class. The above - relationship names correspond, respectively to these Models: - Proposal, Survey, Documentation - The relationships listed here are mutually exclusive. For example, - a Work cannot be both a Proposal and a Survey at the same time. +class Work(polymodel.PolyModel): + """Model of a Work created by one or more Persons in Roles. - persons) a many:many relationship with Persons, stored in a separate - WorksPersons model. See the WorksPersons model class for details. + Work is a "base entity" of other more specific "works" created by Persons + serving in "roles". + + authors) a many:many relationship with Roles, stored in a separate + WorksAuthors model, used to represent authorship of the Work. See + the WorksAuthors model class for details. reviews) a 1:many relationship between a Work and the zero or more Reviews of that Work. This relation is implemented as the 'reviews' @@ -54,8 +46,34 @@ #: Required field indicating the "title" of the work, which may have #: different uses depending on the specific type of the work. Works #: can be indexed, filtered, and sorted by 'title'. - title = db.StringProperty(required=True) + title = db.StringProperty(required=True, + verbose_name=ugettext_lazy('Title')) + title.help_text = ugettext_lazy( + 'title of the document; often used in the window title') + + #: optional, indexed plain text field used for different purposes, + #: depending on the specific type of the work + abstract = db.StringProperty(multiline=True) + abstract.help_text = ugettext_lazy( + 'short abstract, summary, or snippet;' + ' 500 characters or less, plain text displayed publicly') - #: large, non-indexed text field used for different purposes, depending - #: on the specific type of the work. - abstract = db.TextProperty() + #: Required link name, appended to a "path" to form the document URL. + #: The combined "path" and link name must be globally unique on the + #: site (but, unlike some link names, a Work link name can be reused, + #: as long as the combination with the preceding path is unique). + link_name = db.StringProperty(required=True, + verbose_name=ugettext_lazy('Link name')) + link_name.help_text = ugettext_lazy('link name used in URLs') + + #: short name used in places such as the sidebar menu and breadcrumb trail + #: (optional: title will be used if short_name is not present) + short_name = db.StringProperty(verbose_name=ugettext_lazy('Short name')) + short_name.help_text = ugettext_lazy( + 'short name used, for example, in the sidebar menu') + + #: date when the work was created + created = db.DateTimeProperty(auto_now_add=True) + + #: date when the work was last modified + modified = db.DateTimeProperty(auto_now=True) diff -r 4a86df751222 -r 832335761384 app/soc/models/works_authors.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/soc/models/works_authors.py Mon Sep 29 15:31:50 2008 +0000 @@ -0,0 +1,43 @@ +#!/usr/bin/python2.5 +# +# Copyright 2008 the Melange authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""The WorksAuthors Model links one author (Role) to one Work.""" + +__authors__ = [ + '"Todd Larsen" ', +] + + +from google.appengine.ext import db + +import soc.models.role.Role +import soc.models.work.Work + + +class WorksAuthors(db.Model): + """Model linking one Work to its author Role. + """ + + #: the Role end of a single 1:1 link in the many:many relationship + #: between Works and Roles + author = db.ReferenceProperty(reference_class=soc.models.role.Role, + required=True, collection_name='authors') + + #: the Work end of a single 1:1 link in the many:many relationship + #: between Works and Roles + work = db.ReferenceProperty(reference_class=soc.models.work.Work, + required=True, collection_name='works') + diff -r 4a86df751222 -r 832335761384 app/soc/views/site/home.py --- a/app/soc/views/site/home.py Mon Sep 29 14:03:45 2008 +0000 +++ b/app/soc/views/site/home.py Mon Sep 29 15:31:50 2008 +0000 @@ -59,7 +59,8 @@ model = soc.models.document.Document #: list of model fields which will *not* be gathered by the form - exclude = ['user','modified','created','link_name'] + exclude = ['user','modified','created','link_name', 'inheritance_line'] + class SiteSettingsForm(forms_helpers.DbModelForm): """Django form displayed when creating or editing Site Settings. @@ -70,6 +71,9 @@ #: db.Model subclass for which the form will gather information model = soc.models.site_settings.SiteSettings + #: list of model fields which will *not* be gathered by the form + exclude = ['inheritance_line', 'home'] + def clean_feed_url(self): feed_url = self.cleaned_data.get('feed_url') @@ -82,7 +86,10 @@ return feed_url -DEF_SITE_HOME_PATH = 'site/home' + +DEF_SITE_SETTINGS_PATH = 'site' +DEF_SITE_HOME_DOC_LINK_NAME = 'home' + DEF_SITE_HOME_PUBLIC_TMPL = 'soc/site/home/public.html' def public(request, template=DEF_SITE_HOME_PUBLIC_TMPL): @@ -98,16 +105,16 @@ # create default template context for use with any templates context = response_helpers.getUniversalContext(request) - document = soc.logic.document.getDocumentFromPath(DEF_SITE_HOME_PATH) - site_settings = soc.logic.site.settings.getSiteSettingsFromPath(DEF_SITE_HOME_PATH) - - if document: - document.content = template_helpers.unescape(document.content) - context.update({'site_document': document}) - + site_settings = soc.logic.site.settings.getSiteSettings(DEF_SITE_SETTINGS_PATH) + if site_settings: context.update({'site_settings': site_settings}) - + site_doc = site_settings.home + + if site_doc: + site_doc.content = template_helpers.unescape(site_doc.content) + context.update({'site_document': site_doc}) + return response_helpers.respond(request, template, context) @@ -129,13 +136,13 @@ logged_in_id = users.get_current_user() alt_response = simple.getAltResponseIfNotDeveloper(request, context, - id = logged_in_id) + id=logged_in_id) if alt_response: # not a developer return alt_response alt_response = simple.getAltResponseIfNotLoggedIn(request, context, - id = logged_in_id) + id=logged_in_id) if alt_response: # not logged in return alt_response @@ -156,47 +163,43 @@ if document_form.is_valid() and settings_form.is_valid(): title = document_form.cleaned_data.get('title') - link_name = DEF_SITE_HOME_PATH + link_name = DEF_SITE_HOME_DOC_LINK_NAME short_name = document_form.cleaned_data.get('short_name') + abstract = document_form.cleaned_data.get('abstract') content = document_form.cleaned_data.get('content') + site_doc = soc.logic.document.updateOrCreateDocument( + DEF_SITE_SETTINGS_PATH, link_name=link_name, title=title, + short_name=short_name, abstract=abstract, content=content, + user=id_user.getUserFromId(logged_in_id)) + feed_url = settings_form.cleaned_data.get('feed_url') - - document = soc.logic.document.updateOrCreateDocumentFromPath( - DEF_SITE_HOME_PATH, - link_name = link_name, - title = title, - short_name = short_name, - content = content, - user = id_user.getUserFromId(logged_in_id)) - site_settings = soc.logic.site.settings.updateOrCreateSiteSettingsFromPath( - DEF_SITE_HOME_PATH, - feed_url = feed_url) + site_settings = soc.logic.site.settings.updateOrCreateSiteSettings( + DEF_SITE_SETTINGS_PATH, home=site_doc, feed_url=feed_url) context.update({'submit_message': 'Site Settings saved.'}) else: # request.method == 'GET' - # try to fetch Document entity by unique key_name - document = soc.logic.document.getDocumentFromPath(DEF_SITE_HOME_PATH) + # try to fetch SiteSettings entity by unique key_name + site_settings = soc.logic.site.settings.getSiteSettings( + DEF_SITE_SETTINGS_PATH) - if document: + if site_settings: + # populate form with the existing SiteSettings entity + settings_form = SiteSettingsForm(instance=site_settings) + site_doc = site_settings.home + else: + # no SiteSettings entity exists for this key_name, so show a blank form + settings_form = SiteSettingsForm() + site_doc = None + + if site_doc: # populate form with the existing Document entity - document_form = DocumentForm(instance=document) + document_form = DocumentForm(instance=site_doc) else: # no Document entity exists for this key_name, so show a blank form document_form = DocumentForm() - # try to fetch SiteSettings entity by unique key_name - site_settings = soc.logic.site.settings.getSiteSettingsFromPath( - DEF_SITE_HOME_PATH) - - if site_settings: - # populate form with the existing SiteSettings entity - settings_form = SiteSettingsForm(instance=site_settings) - else: - # no SiteSettings entity exists for this key_name, so show a blank form - settings_form = SiteSettingsForm() - context.update({'document_form': document_form, 'settings_form': settings_form })