diff -r d5302883f3ac -r d360162714b6 app/soc/views/site/docs/edit.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app/soc/views/site/docs/edit.py Wed Oct 01 06:24:17 2008 +0000 @@ -0,0 +1,280 @@ +#!/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. + +"""Developer views for editing and examining Documents. +""" + +__authors__ = [ + '"Todd Larsen" ', + ] + + +from google.appengine.api import users + +from django import http +from django import newforms as forms +from django.utils.translation import ugettext_lazy + +from soc.logic import document +from soc.logic import key_name +from soc.logic import out_of_band +from soc.logic.site import id_user +from soc.views import simple +from soc.views.helpers import custom_widgets +from soc.views.helpers import forms_helpers +from soc.views.helpers import request_helpers +from soc.views.helpers import response_helpers +from soc.views.user import profile + +import soc.models.document + + +class EditForm(forms_helpers.DbModelForm): + """Django form displayed when Developer edits a Document. + """ + doc_key_name = forms.CharField(widget=forms.HiddenInput) + content = forms.fields.CharField(widget=custom_widgets.TinyMCE()) + + class Meta: + model = soc.models.document.Document + + #: list of model fields which will *not* be gathered by the form + exclude = ['inheritance_line', 'user', 'created', 'modified'] + + def clean_partial_path(self): + partial_path = self.cleaned_data.get('partial_path') + # TODO(tlarsen): combine path and link_name and check for uniqueness + return partial_path + + def clean_link_name(self): + link_name = self.cleaned_data.get('link_name') + # TODO(tlarsen): combine path and link_name and check for uniqueness + return link_name + + +DEF_SITE_DOCS_EDIT_TMPL = 'soc/site/docs/edit.html' +DEF_CREATE_NEW_DOC_MSG = ' You can create a new user by visiting the' \ + ' Create ' \ + 'a New Document page.' + +def edit(request, partial_path=None, linkname=None, + template=DEF_SITE_DOCS_EDIT_TMPL): + """View for a Developer to modify the properties of a Document Model entity. + + Args: + request: the standard django request object + path: the Document's site-unique "path" extracted from the URL + template: the "sibling" template (or a search list of such templates) + from which to construct the public.html template name (or names) + + Returns: + A subclass of django.http.HttpResponse which either contains the form to + be filled out, or a redirect to the correct view in the interface. + """ + # create default template context for use with any templates + context = response_helpers.getUniversalContext(request) + + logged_in_id = users.get_current_user() + + alt_response = simple.getAltResponseIfNotDeveloper(request, context, + id=logged_in_id) + if alt_response: + # not a developer + return alt_response + + alt_response = simple.getAltResponseIfNotLoggedIn(request, context, + id=logged_in_id) + if alt_response: + # not logged in + return alt_response + + alt_response = simple.getAltResponseIfNotUser(request, context, + id = logged_in_id) + if alt_response: + # no existing User entity for logged in Google Account. User entity is + # required for creating Documents + return alt_response + + alt_response = simple.getAltResponseIfNotDeveloper(request, + context=context) + if alt_response: + return alt_response + + doc = None # assume that no Document entity will be found + + path = key_name.combinePath([partial_path, linkname]) + + # try to fetch Document entity corresponding to path if one exists + try: + doc = document.getDocumentIfPath(path) + except out_of_band.ErrorResponse, error: + # show custom 404 page when path doesn't exist in Datastore + error.message = error.message + DEF_CREATE_NEW_DOC_MSG + return simple.errorResponse(request, error, template, context) + + if request.method == 'POST': + form = EditForm(request.POST) + + if form.is_valid(): + new_partial_path = form.cleaned_data.get('partial_path') + new_linkname = form.cleaned_data.get('link_name') + title = form.cleaned_data.get('title') + short_name = form.cleaned_data.get('short_name') + abstract = form.cleaned_data.get('abstract') + content = form.cleaned_data.get('content') + doc_key_name = form.cleaned_data.get('doc_key_name') + + doc = soc.logic.document.updateOrCreateDocument( + partial_path=new_partial_path, link_name=new_linkname, + title=title, short_name=short_name, abstract=abstract, + content=content, user=id_user.getUserFromId(logged_in_id)) + + if not doc: + return http.HttpResponseRedirect('/') + + new_path = key_name.combinePath([new_partial_path, new_linkname]) + + # redirect to new /site/docs/edit/new_path?s=0 + # (causes 'Profile saved' message to be displayed) + return response_helpers.redirectToChangedSuffix( + request, path, new_path, + params=profile.SUBMIT_PROFILE_SAVED_PARAMS) + else: # method == 'GET': + # try to fetch Document entity corresponding to path if one exists + if path: + if doc: + # is 'Profile saved' parameter present, but referrer was not ourself? + # (e.g. someone bookmarked the GET that followed the POST submit) + if (request.GET.get(profile.SUBMIT_MSG_PARAM_NAME) + and (not request_helpers.isReferrerSelf(request, suffix=path))): + # redirect to aggressively remove 'Profile saved' query parameter + return http.HttpResponseRedirect(request.path) + + # referrer was us, so select which submit message to display + # (may display no message if ?s=0 parameter is not present) + context['submit_message'] = ( + request_helpers.getSingleIndexedParamValue( + request, profile.SUBMIT_MSG_PARAM_NAME, + values=profile.SUBMIT_MESSAGES)) + + # populate form with the existing User entity + 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, + 'user': doc.user}) + else: + if request.GET.get(profile.SUBMIT_MSG_PARAM_NAME): + # redirect to aggressively remove 'Profile saved' query parameter + return http.HttpResponseRedirect(request.path) + + context['lookup_error'] = ugettext_lazy( + 'Document with that path not found.') + form = EditForm(initial={'link_name': linkname}) + else: # no link name specified in the URL + if request.GET.get(profile.SUBMIT_MSG_PARAM_NAME): + # redirect to aggressively remove 'Profile saved' query parameter + return http.HttpResponseRedirect(request.path) + + # no link name specified, so start with an empty form + form = EditForm() + + context.update({'form': form, + 'existing_doc': doc}) + + return response_helpers.respond(request, template, context) + + +class CreateForm(forms_helpers.DbModelForm): + """Django form displayed when Developer creates a Document. + """ + doc_key_name = forms.CharField(widget=forms.HiddenInput) + content = forms.fields.CharField(widget=custom_widgets.TinyMCE()) + + class Meta: + model = soc.models.document.Document + + #: list of model fields which will *not* be gathered by the form + exclude = ['inheritance_line', 'user', 'created', 'modified'] + + def clean_partial_path(self): + partial_path = self.cleaned_data.get('partial_path') + # TODO(tlarsen): combine path and link_name and check for uniqueness + return partial_path + + def clean_link_name(self): + link_name = self.cleaned_data.get('link_name') + # TODO(tlarsen): combine path and link_name and check for uniqueness + return link_name + + +DEF_SITE_DOCS_CREATE_TMPL = 'soc/site/docs/edit.html' + +def create(request, template=DEF_SITE_DOCS_CREATE_TMPL): + """View for a Developer to create a new Document entity. + + Args: + request: the standard django request object + template: the "sibling" template (or a search list of such templates) + from which to construct the public.html template name (or names) + + Returns: + A subclass of django.http.HttpResponse which either contains the form to + be filled out, or a redirect to the correct view in the interface. + """ + # create default template context for use with any templates + context = response_helpers.getUniversalContext(request) + + alt_response = simple.getAltResponseIfNotDeveloper(request, + context=context) + if alt_response: + return alt_response + + if request.method == 'POST': + form = CreateForm(request.POST) + + if form.is_valid(): + new_partial_path = form.cleaned_data.get('partial_path') + new_linkname = form.cleaned_data.get('link_name') + title = form.cleaned_data.get('title') + short_name = form.cleaned_data.get('short_name') + abstract = form.cleaned_data.get('abstract') + content = form.cleaned_data.get('content') + doc_key_name = form.cleaned_data.get('doc_key_name') + + doc = soc.logic.document.updateOrCreateDocument( + partial_path=new_partial_path, link_name=new_linkname, + title=title, short_name=short_name, abstract=abstract, + content=content, user=id_user.getUserFromId(logged_in_id)) + + if not doc: + return http.HttpResponseRedirect('/') + + new_path = key_name.combinePathAndLinkName( + new_partial_path, new_linkname) + + # redirect to new /site/docs/edit/new_path?s=0 + # (causes 'Profile saved' message to be displayed) + return response_helpers.redirectToChangedSuffix( + request, None, new_path, + params=profile.SUBMIT_PROFILE_SAVED_PARAMS) + else: # method == 'GET': + # no link name specified, so start with an empty form + form = CreateForm() + + context.update({'form': form}) + + return response_helpers.respond(request, template, context)