16 |
16 |
17 """Site-wide Melange home page views. |
17 """Site-wide Melange home page views. |
18 |
18 |
19 public: how the general public sees the site home page of a Melange |
19 public: how the general public sees the site home page of a Melange |
20 site |
20 site |
21 |
|
22 edit: site settings view for logged-in Developers |
|
23 """ |
21 """ |
24 |
22 |
25 __authors__ = [ |
23 __authors__ = [ |
26 '"Pawel Solyga" <pawel.solyga@gmail.com>', |
24 '"Pawel Solyga" <pawel.solyga@gmail.com>', |
27 ] |
25 ] |
28 |
26 |
29 |
27 |
30 from google.appengine.api import users |
28 from google.appengine.api import users |
31 from google.appengine.ext import db |
29 from google.appengine.ext import db |
32 |
30 |
33 from django import forms |
|
34 from django import http |
|
35 from django import shortcuts |
|
36 |
|
37 from soc.logic import models |
31 from soc.logic import models |
38 from soc.logic import out_of_band |
|
39 from soc.logic import validate |
|
40 from soc.logic.models import document |
|
41 from soc.logic.site import id_user |
|
42 from soc.views import simple |
|
43 from soc.views import helper |
32 from soc.views import helper |
44 from soc.views.helper import access |
|
45 |
33 |
46 import soc.logic.models.site_settings |
34 import soc.logic.models.site_settings |
47 import soc.models.document |
|
48 import soc.models.site_settings |
|
49 import soc.views.helper.forms |
|
50 import soc.views.helper.responses |
35 import soc.views.helper.responses |
51 import soc.views.helper.templates |
36 import soc.views.helper.templates |
52 import soc.views.helper.widgets |
|
53 import soc.views.out_of_band |
|
54 |
37 |
55 |
|
56 class DocumentForm(helper.forms.DbModelForm): |
|
57 content = forms.fields.CharField(widget=helper.widgets.TinyMCE( |
|
58 attrs={'rows':10, 'cols':40})) |
|
59 |
|
60 class Meta: |
|
61 """Inner Meta class that defines some behavior for the form. |
|
62 """ |
|
63 #: db.Model subclass for which the form will gather information |
|
64 model = soc.models.document.Document |
|
65 |
|
66 #: list of model fields which will *not* be gathered by the form |
|
67 exclude = ['partial_path', 'link_name', |
|
68 'author', 'modified', 'created', 'inheritance_line'] |
|
69 |
|
70 |
|
71 class SiteSettingsForm(helper.forms.DbModelForm): |
|
72 """Django form displayed when creating or editing Site Settings. |
|
73 """ |
|
74 class Meta: |
|
75 """Inner Meta class that defines some behavior for the form. |
|
76 """ |
|
77 #: db.Model subclass for which the form will gather information |
|
78 model = soc.models.site_settings.SiteSettings |
|
79 |
|
80 #: list of model fields which will *not* be gathered by the form |
|
81 exclude = ['inheritance_line', 'home'] |
|
82 |
|
83 def clean_feed_url(self): |
|
84 feed_url = self.cleaned_data.get('feed_url') |
|
85 |
|
86 if feed_url == '': |
|
87 # feed url not supplied (which is OK), so do not try to validate it |
|
88 return None |
|
89 |
|
90 if not validate.isFeedURLValid(feed_url): |
|
91 raise forms.ValidationError('This URL is not a valid ATOM or RSS feed.') |
|
92 |
|
93 return feed_url |
|
94 |
|
95 |
|
96 DEF_SITE_SETTINGS_PATH = 'site' |
|
97 DEF_SITE_HOME_DOC_LINK_NAME = 'home' |
|
98 |
38 |
99 DEF_SITE_HOME_PUBLIC_TMPL = 'soc/site/home/public.html' |
39 DEF_SITE_HOME_PUBLIC_TMPL = 'soc/site/home/public.html' |
100 |
40 |
101 def public(request, template=DEF_SITE_HOME_PUBLIC_TMPL): |
41 def public(request, template=DEF_SITE_HOME_PUBLIC_TMPL): |
102 """How the "general public" sees the Melange site home page. |
42 """How the "general public" sees the Melange site home page. |
109 A subclass of django.http.HttpResponse with generated template. |
49 A subclass of django.http.HttpResponse with generated template. |
110 """ |
50 """ |
111 # create default template context for use with any templates |
51 # create default template context for use with any templates |
112 context = helper.responses.getUniversalContext(request) |
52 context = helper.responses.getUniversalContext(request) |
113 |
53 |
114 site_settings = soc.logic.models.site_settings.logic.getFromFields( |
54 site_settings = models.site_settings.logic.getFromFields( |
115 path=DEF_SITE_SETTINGS_PATH) |
55 path=models.site_settings.logic.DEF_SITE_SETTINGS_PATH) |
116 |
56 |
117 if site_settings: |
57 if site_settings: |
118 context['site_settings'] = site_settings |
58 context['site_settings'] = site_settings |
119 |
59 |
120 # check if ReferenceProperty to home Document is valid |
60 # check if ReferenceProperty to home Document is valid |
126 if site_doc: |
66 if site_doc: |
127 site_doc.content = helper.templates.unescape(site_doc.content) |
67 site_doc.content = helper.templates.unescape(site_doc.content) |
128 context['site_document'] = site_doc |
68 context['site_document'] = site_doc |
129 |
69 |
130 return helper.responses.respond(request, template, context=context) |
70 return helper.responses.respond(request, template, context=context) |
131 |
|
132 |
|
133 DEF_SITE_HOME_EDIT_TMPL = 'soc/site/home/edit.html' |
|
134 |
|
135 def edit(request, template=DEF_SITE_HOME_EDIT_TMPL): |
|
136 """View for Developer to edit content of Melange site home page. |
|
137 |
|
138 Args: |
|
139 request: the standard django request object. |
|
140 template: the template path to use for rendering the template. |
|
141 |
|
142 Returns: |
|
143 A subclass of django.http.HttpResponse with generated template. |
|
144 """ |
|
145 |
|
146 try: |
|
147 access.checkIsDeveloper(request) |
|
148 except soc.views.out_of_band.AccessViolationResponse, alt_response: |
|
149 return alt_response.response() |
|
150 |
|
151 # create default template context for use with any templates |
|
152 context = helper.responses.getUniversalContext(request) |
|
153 |
|
154 settings_form = None |
|
155 document_form = None |
|
156 |
|
157 if request.method == 'POST': |
|
158 document_form = DocumentForm(request.POST) |
|
159 settings_form = SiteSettingsForm(request.POST) |
|
160 |
|
161 if document_form.is_valid() and settings_form.is_valid(): |
|
162 link_name = DEF_SITE_HOME_DOC_LINK_NAME |
|
163 partial_path=DEF_SITE_SETTINGS_PATH |
|
164 logged_in_id = users.get_current_user() |
|
165 author = models.user.logic.getFromFields(email=logged_in_id.email()) |
|
166 |
|
167 properties = { |
|
168 'title': document_form.cleaned_data.get('title'), |
|
169 'short_name': document_form.cleaned_data.get('short_name'), |
|
170 'abstract': document_form.cleaned_data.get('abstract'), |
|
171 'content': document_form.cleaned_data.get('content'), |
|
172 'link_name': link_name, |
|
173 'partial_path': partial_path, |
|
174 'id': logged_in_id, |
|
175 'author': author, |
|
176 } |
|
177 |
|
178 site_doc = document.logic.updateOrCreateFromFields( |
|
179 properties, partial_path=partial_path, link_name=link_name) |
|
180 |
|
181 feed_url = settings_form.cleaned_data.get('feed_url') |
|
182 |
|
183 site_settings = models.site_settings.logic.updateOrCreateFromFields( |
|
184 {'feed_url': feed_url, 'home': site_doc}, path=DEF_SITE_SETTINGS_PATH) |
|
185 |
|
186 context['notice'] = 'Site Settings saved.' |
|
187 else: # request.method == 'GET' |
|
188 # try to fetch SiteSettings entity by unique key_name |
|
189 site_settings = models.site_settings.logic.getFromFields( |
|
190 path=DEF_SITE_SETTINGS_PATH) |
|
191 |
|
192 if site_settings: |
|
193 # populate form with the existing SiteSettings entity |
|
194 settings_form = SiteSettingsForm(instance=site_settings) |
|
195 |
|
196 # check if ReferenceProperty to home Document is valid |
|
197 try: |
|
198 site_doc = site_settings.home |
|
199 except db.Error: |
|
200 site_doc = None |
|
201 |
|
202 else: |
|
203 # no SiteSettings entity exists for this key_name, so show a blank form |
|
204 settings_form = SiteSettingsForm() |
|
205 site_doc = None |
|
206 |
|
207 if site_doc: |
|
208 # populate form with the existing Document entity |
|
209 document_form = DocumentForm(instance=site_doc) |
|
210 else: |
|
211 # no Document entity exists for this key_name, so show a blank form |
|
212 document_form = DocumentForm() |
|
213 |
|
214 context.update({'document_form': document_form, |
|
215 'settings_form': settings_form }) |
|
216 |
|
217 return helper.responses.respond(request, template, context) |
|