1 # -*- coding: utf-8 -*-
3 # Copyright (c) 2010-2012 Cidadania S. Coop. Galega
5 # This file is part of e-cidadania.
7 # e-cidadania is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # e-cidadania is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with e-cidadania. If not, see <http://www.gnu.org/licenses/>.
21 These are the views that control the debates.
27 from django
.views
.generic
.base
import TemplateView
, RedirectView
28 from django
.views
.generic
.list import ListView
29 from django
.views
.generic
.edit
import CreateView
, UpdateView
, DeleteView
30 from django
.views
.generic
.detail
import DetailView
31 from django
.contrib
.auth
.models
import User
, Group
32 from django
.contrib
import messages
33 from django
.contrib
.auth
.decorators
import login_required
, permission_required
34 from django
.contrib
.comments
import *
35 from django
.contrib
.contenttypes
.models
import ContentType
36 from django
.contrib
.comments
.forms
import CommentForm
37 from django
.utils
.decorators
import method_decorator
38 from django
.http
import HttpResponse
, HttpResponseRedirect
, Http404
39 from django
.shortcuts
import render_to_response
, get_object_or_404
, redirect
40 from django
.template
import RequestContext
41 from django
.forms
.formsets
import formset_factory
, BaseFormSet
42 from django
.core
.exceptions
import ObjectDoesNotExist
43 from django
.core
.serializers
.json
import DjangoJSONEncoder
44 from django
.core
.urlresolvers
import reverse
45 from django
.db
import connection
46 from django
.forms
.models
import modelformset_factory
, inlineformset_factory
48 from apps
.ecidadania
.debate
import url_names
as urln
49 from apps
.ecidadania
.debate
.models
import Debate
, Note
, Row
, Column
50 from apps
.ecidadania
.debate
.forms
import DebateForm
, UpdateNoteForm
, \
51 NoteForm
, RowForm
, ColumnForm
, UpdateNotePosition
52 from core
.spaces
.models
import Space
53 from core
.permissions
import has_space_permission
, has_all_permissions
54 from helpers
.cache
import get_or_insert_object_in_cache
57 @permission_required('debate.add_debate')
58 def add_new_debate(request
, space_url
):
61 Create a new debate. This function returns two forms to create
62 a complete debate, debate form and phases formset.
64 .. versionadded:: 0.1.5
66 :attributes: debate_form, row_formset, column_formset
67 :context: form, rowform, colform, get_place, debateid
69 place
= get_object_or_404(Space
, url
=space_url
)
71 if has_space_permission(request
.user
, place
, allow
=['admins']) \
72 or has_all_permissions(request
.user
):
74 RowFormSet
= inlineformset_factory(Debate
, Row
, extra
=1)
75 ColumnFormSet
= inlineformset_factory(Debate
, Column
, extra
=1)
77 debate_form
= DebateForm(request
.POST
or None)
78 row_formset
= RowFormSet(request
.POST
or None, prefix
="rowform")
79 column_formset
= ColumnFormSet(request
.POST
or None, prefix
="colform")
82 # Get the last PK and add 1 to get the current PK
84 last_debate_id
= Debate
.objects
.latest('id')
85 current_debate_id
= last_debate_id
.pk
+ 1
86 except ObjectDoesNotExist
:
89 if request
.method
== 'POST':
90 if debate_form
.is_valid() and row_formset
.is_valid() \
91 and column_formset
.is_valid():
92 debate_form_uncommited
= debate_form
.save(commit
=False)
93 debate_form_uncommited
.space
= place
94 debate_form_uncommited
.author
= request
.user
96 saved_debate
= debate_form_uncommited
.save()
97 debate_instance
= get_object_or_404(Debate
,
100 row
= row_formset
.save(commit
=False)
102 form
.debate
= debate_instance
105 column
= column_formset
.save(commit
=False)
107 form
.debate
= debate_instance
110 return HttpResponseRedirect(reverse(urln
.DEBATE_VIEW
,
111 kwargs
={'space_url': space_url
,
112 'debate_id': str(debate_form_uncommited
.id)}))
114 return render_to_response('debate/debate_add.html',
115 {'form': debate_form
,
116 'rowform': row_formset
,
117 'colform': column_formset
,
119 'debateid': current_debate_id
},
120 context_instance
=RequestContext(request
))
121 return render_to_response('not_allowed.html',
122 context_instance
=RequestContext(request
))
124 @permission_required('debate.edit_debate')
125 def edit_debate(request
, space_url
, pk
):
128 place
= get_object_or_404(Space
, url
=space_url
)
130 if has_space_permission(request
.user
, place
, allow
=['admins']) \
131 or has_all_permissions(request
.user
):
133 RowFormSet
= inlineformset_factory(Debate
, Row
, extra
=1)
134 ColumnFormSet
= inlineformset_factory(Debate
, Column
, extra
=1)
136 instance
= Debate
.objects
.get(pk
=pk
)
137 debate_form
= DebateForm(request
.POST
or None, instance
=instance
)
138 row_formset
= RowFormSet(request
.POST
or None, instance
=instance
, prefix
="rowform")
139 column_formset
= ColumnFormSet(request
.POST
or None, instance
=instance
, prefix
="colform")
142 if request
.user
.has_perm('debate.debate_edit') \
143 or has_all_permissions(request
.user
):
144 if request
.method
== 'POST':
145 if debate_form
.is_valid() and row_formset
.is_valid() \
146 and column_formset
.is_valid():
147 debate_form_uncommited
= debate_form
.save(commit
=False)
148 debate_form_uncommited
.space
= place
149 debate_form_uncommited
.author
= request
.user
151 saved_debate
= debate_form_uncommited
.save()
152 debate_instance
= get_object_or_404(Debate
,
155 row
= row_formset
.save(commit
=False)
157 form
.debate
= instance
160 column
= column_formset
.save(commit
=False)
162 form
.debate
= instance
165 return HttpResponseRedirect(reverse(urln
.DEBATE_VIEW
,
166 kwargs
={'space_url': space_url
,
167 'debate_id': str(debate_form_uncommited
.id)}))
169 return render_to_response('debate/debate_add.html',
170 {'form': debate_form
,
171 'rowform': row_formset
,
172 'colform': column_formset
,
175 context_instance
=RequestContext(request
))
176 return render_to_response('not_allowed.html',
177 context_instance
=RequestContext(request
))
178 def get_debates(request
):
181 Get all debates and serve them through JSON.
183 data
= [debate
.title
for debate
in Debate
.objects
.order_by('title')]
184 return render_to_response(json
.dumps(data
), content_type
='application/json')
187 def create_note(request
, space_url
):
190 This function creates a new note inside the debate board. It receives the
191 order from the createNote() AJAX function. To create the note first we
192 create the note in the DB, and if successful we return some of its
193 parameters to the debate board for the user. In case the petition had
194 errors, we return the error message that will be shown by jsnotify.
196 .. versionadded:: 0.1.5
198 note_form
= NoteForm(request
.POST
or None)
200 if request
.method
== "POST" and request
.is_ajax
:
201 if note_form
.is_valid():
202 note_form_uncommited
= note_form
.save(commit
=False)
203 note_form_uncommited
.author
= request
.user
204 note_form_uncommited
.debate
= get_object_or_404(Debate
,
205 pk
=request
.POST
['debateid'])
206 note_form_uncommited
.title
= request
.POST
['title']
207 note_form_uncommited
.message
= request
.POST
['message']
208 note_form_uncommited
.column
= get_object_or_404(Column
,
209 pk
=request
.POST
['column'])
210 note_form_uncommited
.row
= get_object_or_404(Row
,
211 pk
=request
.POST
['row'])
212 note_form_uncommited
.save()
215 response_data
['id'] = note_form_uncommited
.id
216 response_data
['message'] = note_form_uncommited
.message
217 response_data
['title'] = note_form_uncommited
.title
218 return HttpResponse(json
.dumps(response_data
),
219 mimetype
="application/json")
222 msg
= "The note form didn't validate. This fields gave errors: " \
223 + str(note_form
.errors
)
225 msg
= "The petition was not POST."
227 return HttpResponse(json
.dumps(msg
), mimetype
="application/json")
230 def update_note(request
, space_url
):
233 Updated the current note with the POST data. UpdateNoteForm is an incomplete
234 form that doesn't handle some properties, only the important for the note
238 if request
.method
== "GET" and request
.is_ajax
:
239 note
= get_object_or_404(Note
, pk
=request
.GET
['noteid'])
240 ctype
= ContentType
.objects
.get_for_model(Note
)
241 latest_comments
= Comment
.objects
.filter(is_public
=True,
242 is_removed
=False, content_type
=ctype
, object_pk
=note
.id) \
243 .order_by('-submit_date')[:5]
244 form
= CommentForm(target_object
= note
)
247 response_data
['title'] = note
.title
248 response_data
['message'] = note
.message
249 response_data
['author'] = { 'name': note
.author
.username
}
250 response_data
['comments'] = [ {'username': c
.user
.username
,
251 'comment': c
.comment
,
252 'submit_date': c
.submit_date
} for c
in latest_comments
]
253 response_data
["form_html"] = form
.as_p()
255 return HttpResponse(json
.dumps(response_data
, cls
=DjangoJSONEncoder
),
256 mimetype
="application/json")
258 if request
.method
== "POST" and request
.is_ajax
:
259 note
= get_object_or_404(Note
, pk
=request
.POST
['noteid'])
260 note_form
= UpdateNoteForm(request
.POST
or None, instance
=note
)
261 if note_form
.is_valid():
262 note_form_uncommited
= note_form
.save(commit
=False)
263 note_form_uncommited
.title
= request
.POST
['title']
264 note_form_uncommited
.message
= request
.POST
['message']
265 note_form_uncommited
.last_mod_author
= request
.user
267 note_form_uncommited
.save()
268 msg
= "The note has been updated."
270 msg
= "The form is not valid, check field(s): " + note_form
.errors
272 msg
= "There was some error in the petition."
274 return HttpResponse(msg
)
277 def update_position(request
, space_url
):
280 This view saves the new note position in the debate board. Instead of
281 reloading all the note form with all the data, we use the partial form
282 "UpdateNotePosition" which only handles the column and row of the note.
284 note
= get_object_or_404(Note
, pk
=request
.POST
['noteid'])
285 position_form
= UpdateNotePosition(request
.POST
or None, instance
=note
)
287 if request
.method
== "POST" and request
.is_ajax
:
288 if request
.user
== note
.author
or request
.user
.is_staff
:
289 if position_form
.is_valid():
290 position_form_uncommited
= position_form
.save(commit
=False)
291 position_form_uncommited
.column
= get_object_or_404(Column
,
292 pk
=request
.POST
['column'])
293 position_form_uncommited
.row
= get_object_or_404(Row
,
294 pk
=request
.POST
['row'])
295 position_form_uncommited
.save()
296 msg
= "The note has been updated."
298 msg
= "There has been an error validating the form."
300 msg
= "There was some error in the petition."
302 return HttpResponse(msg
)
305 def delete_note(request
, space_url
):
308 Deletes a note object.
310 note
= get_object_or_404(Note
, pk
=request
.POST
['noteid'])
312 if note
.author
== request
.user
or has_all_permissions(request
.user
):
313 ctype
= ContentType
.objects
.get_for_model(Note
)
314 all_comments
= Comment
.objects
.filter(is_public
=True,
315 is_removed
=False, content_type
=ctype
,
316 object_pk
=note
.id).all()
317 for i
in range(note
.comment_count
):
318 all_comments
[i
].delete()
320 return HttpResponse("The note has been deleted.")
323 return HttpResponse("You're not the author of the note. Can't delete.")
326 class ViewDebate(DetailView
):
330 :context: get_place, notes, columns, rows
332 context_object_name
= 'debate'
333 template_name
= 'debate/debate_view.html'
335 def get_object(self
):
336 key
= self
.kwargs
['debate_id']
337 debate
= get_or_insert_object_in_cache(Debate
, key
, pk
=key
)
340 if datetime
.date
.today() >= debate
.end_date \
341 or datetime
.date
.today() < debate
.start_date
:
342 self
.template_name
= 'debate/debate_outdated.html'
344 # We can't return none, if we do, the platform cannot show
345 # the start and end dates and the title
346 #return Debate.objects.none()
350 def get_context_data(self
, **kwargs
):
351 context
= super(ViewDebate
, self
).get_context_data(**kwargs
)
352 columns
= Column
.objects
.filter(debate
=self
.kwargs
['debate_id'])
353 rows
= Row
.objects
.filter(debate
=self
.kwargs
['debate_id'])
354 space_key
= self
.kwargs
['space_url']
355 current_space
= get_or_insert_object_in_cache(Space
, space_key
,
357 debate_key
= self
.kwargs
['debate_id']
358 current_debate
= get_or_insert_object_in_cache(Debate
, debate_key
,
360 notes
= Note
.objects
.filter(debate
=current_debate
.pk
)
362 last_note
= Note
.objects
.latest('id')
366 context
['get_place'] = current_space
367 context
['notes'] = notes
368 context
['columns'] = columns
369 context
['rows'] = rows
371 context
['lastnote'] = 0
373 context
['lastnote'] = last_note
.pk
378 class ListDebates(ListView
):
380 Return a list of debates for the current space.
386 def get_queryset(self
):
387 key
= self
.kwargs
['space_url']
388 current_space
= get_or_insert_object_in_cache(Space
, key
, url
=key
)
389 debates
= Debate
.objects
.filter(space
=current_space
)
391 # Here must go a validation so a user registered to the space
392 # can always see the debate list. While an anonymous or not
393 # registered user can't see anything unless the space is public
397 def get_context_data(self
, **kwargs
):
398 context
= super(ListDebates
, self
).get_context_data(**kwargs
)
399 key
= self
.kwargs
['space_url']
400 space
= get_or_insert_object_in_cache(Space
, key
, url
=key
)
401 context
['get_place'] = space