|
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) |