app/soc/views/site/docs/edit.py
changeset 237 d360162714b6
child 247 4997b54b0400
equal deleted inserted replaced
236:d5302883f3ac 237:d360162714b6
       
     1 #!/usr/bin/python2.5
       
     2 #
       
     3 # Copyright 2008 the Melange authors.
       
     4 #
       
     5 # Licensed under the Apache License, Version 2.0 (the "License");
       
     6 # you may not use this file except in compliance with the License.
       
     7 # You may obtain a copy of the License at
       
     8 #
       
     9 #   http://www.apache.org/licenses/LICENSE-2.0
       
    10 #
       
    11 # Unless required by applicable law or agreed to in writing, software
       
    12 # distributed under the License is distributed on an "AS IS" BASIS,
       
    13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    14 # See the License for the specific language governing permissions and
       
    15 # limitations under the License.
       
    16 
       
    17 """Developer views for editing and examining Documents.
       
    18 """
       
    19 
       
    20 __authors__ = [
       
    21   '"Todd Larsen" <tlarsen@google.com>',
       
    22   ]
       
    23 
       
    24 
       
    25 from google.appengine.api import users
       
    26 
       
    27 from django import http
       
    28 from django import newforms as forms
       
    29 from django.utils.translation import ugettext_lazy
       
    30 
       
    31 from soc.logic import document
       
    32 from soc.logic import key_name
       
    33 from soc.logic import out_of_band
       
    34 from soc.logic.site import id_user
       
    35 from soc.views import simple
       
    36 from soc.views.helpers import custom_widgets
       
    37 from soc.views.helpers import forms_helpers
       
    38 from soc.views.helpers import request_helpers
       
    39 from soc.views.helpers import response_helpers
       
    40 from soc.views.user import profile
       
    41 
       
    42 import soc.models.document
       
    43 
       
    44 
       
    45 class EditForm(forms_helpers.DbModelForm):
       
    46   """Django form displayed when Developer edits a Document.
       
    47   """
       
    48   doc_key_name = forms.CharField(widget=forms.HiddenInput)
       
    49   content = forms.fields.CharField(widget=custom_widgets.TinyMCE())
       
    50   
       
    51   class Meta:
       
    52     model = soc.models.document.Document
       
    53     
       
    54     #: list of model fields which will *not* be gathered by the form
       
    55     exclude = ['inheritance_line', 'user', 'created', 'modified']
       
    56  
       
    57   def clean_partial_path(self):
       
    58     partial_path = self.cleaned_data.get('partial_path')
       
    59     # TODO(tlarsen): combine path and link_name and check for uniqueness
       
    60     return partial_path
       
    61 
       
    62   def clean_link_name(self):
       
    63     link_name = self.cleaned_data.get('link_name')
       
    64     # TODO(tlarsen): combine path and link_name and check for uniqueness
       
    65     return link_name
       
    66 
       
    67 
       
    68 DEF_SITE_DOCS_EDIT_TMPL = 'soc/site/docs/edit.html'
       
    69 DEF_CREATE_NEW_DOC_MSG = ' You can create a new user by visiting the' \
       
    70                          ' <a href="/site/docs/edit">Create ' \
       
    71                          'a New Document</a> page.'
       
    72 
       
    73 def edit(request, partial_path=None, linkname=None,
       
    74          template=DEF_SITE_DOCS_EDIT_TMPL):
       
    75   """View for a Developer to modify the properties of a Document Model entity.
       
    76 
       
    77   Args:
       
    78     request: the standard django request object
       
    79     path: the Document's site-unique "path" extracted from the URL
       
    80     template: the "sibling" template (or a search list of such templates)
       
    81       from which to construct the public.html template name (or names)
       
    82 
       
    83   Returns:
       
    84     A subclass of django.http.HttpResponse which either contains the form to
       
    85     be filled out, or a redirect to the correct view in the interface.
       
    86   """
       
    87   # create default template context for use with any templates
       
    88   context = response_helpers.getUniversalContext(request)
       
    89 
       
    90   logged_in_id = users.get_current_user()
       
    91   
       
    92   alt_response = simple.getAltResponseIfNotDeveloper(request, context, 
       
    93                                                      id=logged_in_id)
       
    94   if alt_response:
       
    95     # not a developer
       
    96     return alt_response
       
    97   
       
    98   alt_response = simple.getAltResponseIfNotLoggedIn(request, context, 
       
    99                                                     id=logged_in_id)
       
   100   if alt_response:
       
   101     # not logged in
       
   102     return alt_response
       
   103   
       
   104   alt_response = simple.getAltResponseIfNotUser(request, context, 
       
   105                                                 id = logged_in_id)
       
   106   if alt_response:
       
   107     # no existing User entity for logged in Google Account. User entity is 
       
   108     # required for creating Documents
       
   109     return alt_response
       
   110 
       
   111   alt_response = simple.getAltResponseIfNotDeveloper(request,
       
   112                                                      context=context)
       
   113   if alt_response:
       
   114     return alt_response
       
   115 
       
   116   doc = None  # assume that no Document entity will be found
       
   117 
       
   118   path = key_name.combinePath([partial_path, linkname])
       
   119 
       
   120   # try to fetch Document entity corresponding to path if one exists    
       
   121   try:
       
   122     doc = document.getDocumentIfPath(path)
       
   123   except out_of_band.ErrorResponse, error:
       
   124     # show custom 404 page when path doesn't exist in Datastore
       
   125     error.message = error.message + DEF_CREATE_NEW_DOC_MSG
       
   126     return simple.errorResponse(request, error, template, context)
       
   127 
       
   128   if request.method == 'POST':
       
   129     form = EditForm(request.POST)
       
   130 
       
   131     if form.is_valid():
       
   132       new_partial_path = form.cleaned_data.get('partial_path')
       
   133       new_linkname = form.cleaned_data.get('link_name')
       
   134       title = form.cleaned_data.get('title')
       
   135       short_name = form.cleaned_data.get('short_name')
       
   136       abstract = form.cleaned_data.get('abstract')
       
   137       content = form.cleaned_data.get('content')
       
   138       doc_key_name = form.cleaned_data.get('doc_key_name')
       
   139       
       
   140       doc = soc.logic.document.updateOrCreateDocument(
       
   141           partial_path=new_partial_path, link_name=new_linkname,
       
   142           title=title, short_name=short_name, abstract=abstract,
       
   143           content=content, user=id_user.getUserFromId(logged_in_id))
       
   144       
       
   145       if not doc:
       
   146         return http.HttpResponseRedirect('/')
       
   147 
       
   148       new_path = key_name.combinePath([new_partial_path, new_linkname])
       
   149         
       
   150       # redirect to new /site/docs/edit/new_path?s=0
       
   151       # (causes 'Profile saved' message to be displayed)
       
   152       return response_helpers.redirectToChangedSuffix(
       
   153           request, path, new_path,
       
   154           params=profile.SUBMIT_PROFILE_SAVED_PARAMS)
       
   155   else: # method == 'GET':
       
   156     # try to fetch Document entity corresponding to path if one exists
       
   157     if path:
       
   158       if doc:
       
   159         # is 'Profile saved' parameter present, but referrer was not ourself?
       
   160         # (e.g. someone bookmarked the GET that followed the POST submit) 
       
   161         if (request.GET.get(profile.SUBMIT_MSG_PARAM_NAME)
       
   162             and (not request_helpers.isReferrerSelf(request, suffix=path))):
       
   163           # redirect to aggressively remove 'Profile saved' query parameter
       
   164           return http.HttpResponseRedirect(request.path)
       
   165     
       
   166         # referrer was us, so select which submit message to display
       
   167         # (may display no message if ?s=0 parameter is not present)
       
   168         context['submit_message'] = (
       
   169             request_helpers.getSingleIndexedParamValue(
       
   170                 request, profile.SUBMIT_MSG_PARAM_NAME,
       
   171                 values=profile.SUBMIT_MESSAGES))
       
   172 
       
   173         # populate form with the existing User entity
       
   174         form = EditForm(initial={'doc_key_name': doc.key().name(),
       
   175             'title': doc.title, 'partial_path': doc.partial_path,
       
   176             'link_name': doc.link_name, 'short_name': doc.short_name,
       
   177             'abstract': doc.abstract, 'content': doc.content,
       
   178             'user': doc.user})       
       
   179       else:
       
   180         if request.GET.get(profile.SUBMIT_MSG_PARAM_NAME):
       
   181           # redirect to aggressively remove 'Profile saved' query parameter
       
   182           return http.HttpResponseRedirect(request.path)
       
   183           
       
   184         context['lookup_error'] = ugettext_lazy(
       
   185             'Document with that path not found.')
       
   186         form = EditForm(initial={'link_name': linkname})
       
   187     else:  # no link name specified in the URL
       
   188       if request.GET.get(profile.SUBMIT_MSG_PARAM_NAME):
       
   189         # redirect to aggressively remove 'Profile saved' query parameter
       
   190         return http.HttpResponseRedirect(request.path)
       
   191 
       
   192       # no link name specified, so start with an empty form
       
   193       form = EditForm()
       
   194 
       
   195   context.update({'form': form,
       
   196                   'existing_doc': doc})
       
   197 
       
   198   return response_helpers.respond(request, template, context)
       
   199 
       
   200 
       
   201 class CreateForm(forms_helpers.DbModelForm):
       
   202   """Django form displayed when Developer creates a Document.
       
   203   """
       
   204   doc_key_name = forms.CharField(widget=forms.HiddenInput)
       
   205   content = forms.fields.CharField(widget=custom_widgets.TinyMCE())
       
   206   
       
   207   class Meta:
       
   208     model = soc.models.document.Document
       
   209     
       
   210     #: list of model fields which will *not* be gathered by the form
       
   211     exclude = ['inheritance_line', 'user', 'created', 'modified']
       
   212  
       
   213   def clean_partial_path(self):
       
   214     partial_path = self.cleaned_data.get('partial_path')
       
   215     # TODO(tlarsen): combine path and link_name and check for uniqueness
       
   216     return partial_path
       
   217 
       
   218   def clean_link_name(self):
       
   219     link_name = self.cleaned_data.get('link_name')
       
   220     # TODO(tlarsen): combine path and link_name and check for uniqueness
       
   221     return link_name
       
   222 
       
   223 
       
   224 DEF_SITE_DOCS_CREATE_TMPL = 'soc/site/docs/edit.html'
       
   225 
       
   226 def create(request, template=DEF_SITE_DOCS_CREATE_TMPL):
       
   227   """View for a Developer to create a new Document entity.
       
   228 
       
   229   Args:
       
   230     request: the standard django request object
       
   231     template: the "sibling" template (or a search list of such templates)
       
   232       from which to construct the public.html template name (or names)
       
   233 
       
   234   Returns:
       
   235     A subclass of django.http.HttpResponse which either contains the form to
       
   236     be filled out, or a redirect to the correct view in the interface.
       
   237   """
       
   238   # create default template context for use with any templates
       
   239   context = response_helpers.getUniversalContext(request)
       
   240 
       
   241   alt_response = simple.getAltResponseIfNotDeveloper(request,
       
   242                                                      context=context)
       
   243   if alt_response:
       
   244     return alt_response
       
   245 
       
   246   if request.method == 'POST':
       
   247     form = CreateForm(request.POST)
       
   248 
       
   249     if form.is_valid():
       
   250       new_partial_path = form.cleaned_data.get('partial_path')
       
   251       new_linkname = form.cleaned_data.get('link_name')
       
   252       title = form.cleaned_data.get('title')
       
   253       short_name = form.cleaned_data.get('short_name')
       
   254       abstract = form.cleaned_data.get('abstract')
       
   255       content = form.cleaned_data.get('content')
       
   256       doc_key_name = form.cleaned_data.get('doc_key_name')
       
   257       
       
   258       doc = soc.logic.document.updateOrCreateDocument(
       
   259           partial_path=new_partial_path, link_name=new_linkname,
       
   260           title=title, short_name=short_name, abstract=abstract,
       
   261           content=content, user=id_user.getUserFromId(logged_in_id))
       
   262 
       
   263       if not doc:
       
   264         return http.HttpResponseRedirect('/')
       
   265 
       
   266       new_path = key_name.combinePathAndLinkName(
       
   267           new_partial_path, new_linkname)
       
   268         
       
   269       # redirect to new /site/docs/edit/new_path?s=0
       
   270       # (causes 'Profile saved' message to be displayed)
       
   271       return response_helpers.redirectToChangedSuffix(
       
   272           request, None, new_path,
       
   273           params=profile.SUBMIT_PROFILE_SAVED_PARAMS)
       
   274   else: # method == 'GET':
       
   275     # no link name specified, so start with an empty form
       
   276     form = CreateForm()
       
   277 
       
   278   context.update({'form': form})
       
   279 
       
   280   return response_helpers.respond(request, template, context)