Remove the proposed WorksAuthors many:many relation and promote the "founder"
property from Document up to Work. Update all subclasses of Work and any
affected views accordingly. This addresses review comments here:
http://code.google.com/p/soc/source/detail?r=786
Patch by: Todd Larsen
Review by: to-be-reviewed
--- a/app/soc/models/document.py Wed Oct 15 18:06:07 2008 +0000
+++ b/app/soc/models/document.py Wed Oct 15 19:33:50 2008 +0000
@@ -21,13 +21,10 @@
]
-import polymodel
-
from google.appengine.ext import db
from django.utils.translation import ugettext_lazy
-import soc.models.user
import soc.models.work
@@ -44,9 +41,6 @@
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
"""
@@ -55,12 +49,3 @@
#: 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'))
-
- #: TODO(pawel.solyga): replace this with WorkAuthors relation
- #: Required many:1 relationship indicating the founding User of the
- #: Document (this relationship is needed to keep track of lifetime document
- #: creation limits, used to prevent spamming, etc.).
- founder = db.ReferenceProperty(reference_class=soc.models.user.User,
- required=True, collection_name="documents",
- verbose_name=ugettext_lazy('Created by'))
-
--- a/app/soc/models/documentation.py Wed Oct 15 18:06:07 2008 +0000
+++ b/app/soc/models/documentation.py Wed Oct 15 19:33:50 2008 +0000
@@ -45,8 +45,8 @@
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
+ work.author: The author of the Work referred to by this
+ relation is the Administrator (or Host) creating the
Documentation.
work.reviews: Annotations to the Documentation made by other
--- a/app/soc/models/proposal.py Wed Oct 15 18:06:07 2008 +0000
+++ b/app/soc/models/proposal.py Wed Oct 15 19:33:50 2008 +0000
@@ -24,10 +24,12 @@
from google.appengine.ext import db
-import soc.models.work
+import soc.models.document
+import soc.models.quiz
+import soc.models.response
-class Proposal(soc.models.work.Work):
+class Proposal(soc.models.document.Document):
"""Model of a Proposal, which is a specific form of a Work.
The specific way that the properties and relations inherited from Work
@@ -37,10 +39,11 @@
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
- work.reviews: reviews of the Proposal by Reviewers
+ document.content: the details of the Proposal; which, unlike work.abstract
+ is considered "public" information, the contents of a Proposal are only
+ displayed to Persons in Roles that have a "need to know" those details.
A Proposal entity participates in the following relationships implemented
as a db.ReferenceProperty elsewhere in another db.Model:
@@ -49,10 +52,15 @@
Proposal as their foundation. This relation is implemented as the
'tasks' back-reference Query of the Task model 'proposal' reference.
"""
+ #: an optional many:1 relationship between Proposal and a Quiz that
+ #: defines what Questions were added by the prospective Proposal Reviewer
+ #: for the Proposal author to answer.
+ quiz = db.ReferenceProperty(reference_class=soc.models.quiz.Quiz,
+ required=False, collection_name="proposals")
- #: 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
- #: that have a "need to know" the details.
- details = db.TextProperty(required=True)
-
+ #: an optional 1:1 relationship where a Proposal author's Answers to
+ #: a Quiz attached to the Proposal template by the Proposal Reviewer
+ #; are collected.
+ response = db.ReferenceProperty(
+ reference_class=soc.models.response.Response, required=False,
+ collection_name="proposal")
--- a/app/soc/models/question.py Wed Oct 15 18:06:07 2008 +0000
+++ b/app/soc/models/question.py Wed Oct 15 19:33:50 2008 +0000
@@ -39,17 +39,18 @@
work.abstract: the Question text, asked to the respondent
- work.authors: the Authors of the Work referred to by this relation
- are the authors of the Question
+ work.author: the author of the Work referred to by this relation
+ is the original author of the actual Question, regardless of
+ which Quizzes might incorporate the Question
work.reviews: even Questions can be "reviewed" (possibly commented
on during creation or annotated once put into use).
- work.partial_path: used to scope (and, when combined with
+ work.partial_path: used to scope (and, when combined with
work.link_name, uniquely identify) a Question in the same way the
property are used with Documents, etc.
- work.link_name: used to identify (and, when combined with
+ work.link_name: used to identify (and, when combined with
work.partial_path, *uniquely* identify) a Question in the same way
these properties are used with Documents, etc.
--- a/app/soc/models/quiz.py Wed Oct 15 18:06:07 2008 +0000
+++ b/app/soc/models/quiz.py Wed Oct 15 19:33:50 2008 +0000
@@ -51,8 +51,8 @@
work.abstract: summary displayed as a snippet in Quiz list views
- work.authors: the Authors of the Work referred to by this relation
- are the authors of the Quiz (but not necessarily the individual
+ work.author: the author of the Work referred to by this relation
+ is the author of the Quiz (but not necessarily the individual
Questions themselves, see the Question Model)
work.reviews: even Quizzes can be "reviewed" (possibly commented
@@ -85,6 +85,11 @@
logic could check if a survey "passed" by querying for these
"solution" Answers and seeing if the survey Response had the "right"
Answers (to the one Question that matters in this case...).
+
+ proposals) a 1:many relationship where each Quiz can produce all of
+ the Proposals that make use of the Quiz as part of the Proposal.
+ This relation is implemented as the 'proposals' back-reference Query
+ of the Proposal Model 'quiz' reference.
"""
#: a many:many relationship (many:many because a given Question can be
--- a/app/soc/models/response.py Wed Oct 15 18:06:07 2008 +0000
+++ b/app/soc/models/response.py Wed Oct 15 19:33:50 2008 +0000
@@ -45,6 +45,11 @@
The collection of Answers that make up a Response is implemented as
the 'answers' back-reference Query of the Answer model 'response'
reference.
+
+ proposal) an optional 1:1 relationship where a Proposal placed its
+ Answers to a Quiz associated with the Proposal. This relation is
+ implemented as the 'proposal' back-reference Query of the Proposal
+ Model 'response' reference.
"""
#: a required many:1 relationship between Responses and a Quiz that
--- a/app/soc/models/work.py Wed Oct 15 18:06:07 2008 +0000
+++ b/app/soc/models/work.py Wed Oct 15 19:33:50 2008 +0000
@@ -21,11 +21,14 @@
'"Sverre Rabbelier" <sverre@rabbelier.nl>',
]
+
+import polymodel
+
from google.appengine.ext import db
from django.utils.translation import ugettext_lazy
-import polymodel
+import soc.models.user
class Work(polymodel.PolyModel):
@@ -34,14 +37,16 @@
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'
- back-reference Query of the Review model 'reviewed' reference.
+ reviews) a 1:many relationship between a Work and the zero or more
+ Reviews of that Work. This relation is implemented as the 'reviews'
+ back-reference Query of the Review model 'reviewed' reference.
"""
+ #: Required 1:1 relationship indicating the User who initially authored the
+ #: Work (this relationship is needed to keep track of lifetime document
+ #: creation limits, used to prevent spamming, etc.).
+ author = db.ReferenceProperty(reference_class=soc.models.user.User,
+ required=True, collection_name="documents",
+ verbose_name=ugettext_lazy('Created by'))
#: Required field indicating the "title" of the work, which may have
#: different uses depending on the specific type of the work. Works
--- a/app/soc/models/works_authors.py Wed Oct 15 18:06:07 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-#!/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" <tlarsen@google.com>',
-]
-
-
-from google.appengine.ext import db
-
-import soc.models.role
-import soc.models.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')
-
--- a/app/soc/templates/soc/site/docs/list/docs_heading.html Wed Oct 15 18:06:07 2008 +0000
+++ b/app/soc/templates/soc/site/docs/list/docs_heading.html Wed Oct 15 19:33:50 2008 +0000
@@ -4,6 +4,7 @@
<th>Partial Path</th>
<th>Linkname</th>
<th>Featured</th>
- <th>Created</th>
+ <th>Created By</th>
+ <th>Created On</th>
<th>Modified</th>
</tr>
--- a/app/soc/templates/soc/site/docs/list/docs_row.html Wed Oct 15 18:06:07 2008 +0000
+++ b/app/soc/templates/soc/site/docs/list/docs_row.html Wed Oct 15 19:33:50 2008 +0000
@@ -10,6 +10,7 @@
<td><div class="partial_path">{{ data_element.partial_path }}</div></td>
<td><div class="link_name">{{ data_element.link_name }}</div></td>
<td><div class="featured">{{ data_element.is_featured }}</div></td>
+ <td><div class="author">{{ data_element.author.link_name }}</div></td>
<td><div class="created">{{ data_element.created }}</div></td>
<td><div class="modified">{{ data_element.modified }}</div></td>
</tr>
--- a/app/soc/views/site/docs/edit.py Wed Oct 15 18:06:07 2008 +0000
+++ b/app/soc/views/site/docs/edit.py Wed Oct 15 19:33:50 2008 +0000
@@ -1,4 +1,4 @@
-#!/usr/bin/python2.5
+#founder!/usr/bin/python2.5
#
# Copyright 2008 the Melange authors.
#
@@ -75,7 +75,7 @@
properties['short_name'] = form.cleaned_data.get('short_name')
properties['abstract'] = form.cleaned_data.get('abstract')
properties['content'] = form.cleaned_data.get('content')
- properties['founder'] = models.user.logic.getFromFields(email=email)
+ properties['author'] = models.user.logic.getFromFields(email=email)
properties['is_featured'] = form.cleaned_data.get('is_featured')
doc = document.logic.updateOrCreateFromFields(properties,
@@ -94,7 +94,7 @@
model = soc.models.document.Document
#: list of model fields which will *not* be gathered by the form
- exclude = ['inheritance_line', 'founder', 'created', 'modified']
+ exclude = ['inheritance_line', 'author', 'created', 'modified']
def clean_partial_path(self):
partial_path = self.cleaned_data.get('partial_path')
@@ -240,13 +240,13 @@
values=SUBMIT_MESSAGES))
# populate form with the existing Document entity
- founder_link_name = doc.founder.link_name
+ author_link_name = doc.author.link_name
form = EditForm(initial={'doc_key_name': doc.key().name(),
'title': doc.title, 'partial_path': doc.partial_path,
'link_name': doc.link_name, 'short_name': doc.short_name,
'abstract': doc.abstract, 'content': doc.content,
- 'founder': doc.founder, 'is_featured': doc.is_featured,
- 'created_by': founder_link_name})
+ 'author': doc.author, 'is_featured': doc.is_featured,
+ 'created_by': author_link_name})
else:
if request.GET.get(profile.SUBMIT_MSG_PARAM_NAME):
# redirect to aggressively remove 'Profile saved' query parameter
--- a/app/soc/views/site/home.py Wed Oct 15 18:06:07 2008 +0000
+++ b/app/soc/views/site/home.py Wed Oct 15 19:33:50 2008 +0000
@@ -65,7 +65,7 @@
#: list of model fields which will *not* be gathered by the form
exclude = ['partial_path', 'link_name',
- 'founder', 'modified', 'created', 'inheritance_line']
+ 'author', 'modified', 'created', 'inheritance_line']
class SiteSettingsForm(helper.forms.DbModelForm):
@@ -162,7 +162,7 @@
link_name = DEF_SITE_HOME_DOC_LINK_NAME
partial_path=DEF_SITE_SETTINGS_PATH
logged_in_id = users.get_current_user()
- founder = models.user.logic.getFromFields(email=logged_in_id.email())
+ author = models.user.logic.getFromFields(email=logged_in_id.email())
properties = {
'title': document_form.cleaned_data.get('title'),
@@ -172,7 +172,7 @@
'link_name': link_name,
'partial_path': partial_path,
'id': logged_in_id,
- 'founder': founder,
+ 'author': author,
}
site_doc = document.logic.updateOrCreateFromFields(