some work on questions
authorRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Thu, 10 Jan 2013 12:23:46 +0000 (13:23 +0100)
committerRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Thu, 10 Jan 2013 12:24:58 +0000 (13:24 +0100)
16 files changed:
prawokultury/settings.d/30-apps.py
prawokultury/urls.py
questions/__init__.py [new file with mode: 0644]
questions/admin.py [new file with mode: 0755]
questions/forms.py [new file with mode: 0755]
questions/migrations/0001_initial.py [new file with mode: 0644]
questions/migrations/__init__.py [new file with mode: 0644]
questions/models.py [new file with mode: 0644]
questions/templates/questions/answered_mail.txt [new file with mode: 0755]
questions/templates/questions/question_detail.html [new file with mode: 0755]
questions/templates/questions/question_form.html [new file with mode: 0755]
questions/templates/questions/question_list.html [new file with mode: 0755]
questions/templates/questions/question_thanks.html [new file with mode: 0755]
questions/urls.py [new file with mode: 0755]
questions/views.py [new file with mode: 0644]
requirements.txt

index 0eb98e1..4ae5e23 100644 (file)
@@ -4,6 +4,7 @@ INSTALLED_APPS = (
     'menu',
     'events',
     'migdal',
     'menu',
     'events',
     'migdal',
+    'questions',
 
     'gravatar',
     'south',
 
     'gravatar',
     'south',
index 1e2683b..761afeb 100644 (file)
@@ -30,6 +30,7 @@ if 'django_cas' in settings.INSTALLED_APPS:
 urlpatterns += i18n_patterns('',
     url(string_concat(r'^', _('events'), r'/'), include('events.urls')),
     url(r'^comments/', include('django_comments_xtd.urls')),
 urlpatterns += i18n_patterns('',
     url(string_concat(r'^', _('events'), r'/'), include('events.urls')),
     url(r'^comments/', include('django_comments_xtd.urls')),
+    url(r'^prawnik/', include('questions.urls')),
 ) + migdal_urlpatterns 
 
 if settings.DEBUG:
 ) + migdal_urlpatterns 
 
 if settings.DEBUG:
diff --git a/questions/__init__.py b/questions/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/questions/admin.py b/questions/admin.py
new file mode 100755 (executable)
index 0000000..d8676dc
--- /dev/null
@@ -0,0 +1,22 @@
+from django.contrib import admin
+from .models import Question
+
+class QuestionAdmin(admin.ModelAdmin):
+    model = Question
+    list_filter = ('approved', 'answered', 'published')
+    list_display = ('question', 'email', 'created_at', 'approved', 'answered', 'published')
+    date_hierarchy = 'created_at'
+    fields = (
+        ('email', 'created_at'),
+        'question',
+        'approved',
+        'edited_question',
+        'answer',
+        ('answered', 'answered_at'),
+        ('published', 'published_at'),
+        
+    )
+    readonly_fields = ['created_at', 'answered_at', 'published_at']
+
+
+admin.site.register(Question, QuestionAdmin)
diff --git a/questions/forms.py b/questions/forms.py
new file mode 100755 (executable)
index 0000000..3a80db1
--- /dev/null
@@ -0,0 +1,8 @@
+from django.forms import ModelForm
+from .models import Question
+
+class QuestionForm(ModelForm):
+    class Meta:
+        model = Question
+        fields = ['email', 'question']
+        # TODO: honeypot!
diff --git a/questions/migrations/0001_initial.py b/questions/migrations/0001_initial.py
new file mode 100644 (file)
index 0000000..09ce67c
--- /dev/null
@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+    def forwards(self, orm):
+        # Adding model 'Question'
+        db.create_table('questions_question', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('email', self.gf('django.db.models.fields.EmailField')(max_length=75, null=True, blank=True)),
+            ('question', self.gf('django.db.models.fields.TextField')(db_index=True)),
+            ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+            ('approved', self.gf('django.db.models.fields.BooleanField')(default=False)),
+            ('edited_question', self.gf('django.db.models.fields.TextField')(db_index=True, null=True, blank=True)),
+            ('answer', self.gf('markupfield.fields.MarkupField')(rendered_field=True, blank=True)),
+            ('answered', self.gf('django.db.models.fields.BooleanField')(default=False, db_index=True)),
+            ('answer_markup_type', self.gf('django.db.models.fields.CharField')(default='textile_pl', max_length=30, blank=True)),
+            ('answered_at', self.gf('django.db.models.fields.DateTimeField')(db_index=True, null=True, blank=True)),
+            ('_answer_rendered', self.gf('django.db.models.fields.TextField')()),
+            ('published', self.gf('django.db.models.fields.BooleanField')(default=False, db_index=True)),
+            ('published_at', self.gf('django.db.models.fields.DateTimeField')(db_index=True, null=True, blank=True)),
+        ))
+        db.send_create_signal('questions', ['Question'])
+
+
+    def backwards(self, orm):
+        # Deleting model 'Question'
+        db.delete_table('questions_question')
+
+
+    models = {
+        'questions.question': {
+            'Meta': {'ordering': "['-created_at']", 'object_name': 'Question'},
+            '_answer_rendered': ('django.db.models.fields.TextField', [], {}),
+            'answer': ('markupfield.fields.MarkupField', [], {'rendered_field': 'True', 'blank': 'True'}),
+            'answer_markup_type': ('django.db.models.fields.CharField', [], {'default': "'textile_pl'", 'max_length': '30', 'blank': 'True'}),
+            'answered': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+            'answered_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'approved': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+            'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+            'edited_question': ('django.db.models.fields.TextField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'null': 'True', 'blank': 'True'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'published': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'db_index': 'True'}),
+            'published_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
+            'question': ('django.db.models.fields.TextField', [], {'db_index': 'True'})
+        }
+    }
+
+    complete_apps = ['questions']
\ No newline at end of file
diff --git a/questions/migrations/__init__.py b/questions/migrations/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/questions/models.py b/questions/models.py
new file mode 100644 (file)
index 0000000..47dc697
--- /dev/null
@@ -0,0 +1,61 @@
+# -*- coding: utf-8
+from datetime import datetime
+from django.contrib.sites.models import Site
+from django.core.mail import EmailMultiAlternatives
+from django.db import models
+from django.template import loader, Context
+from django.utils.translation import ugettext_lazy as _
+from markupfield.fields import MarkupField
+
+class Question(models.Model):
+    email = models.EmailField(_('contact e-mail'), null=True, blank=True)
+    question = models.TextField(_('question'), db_index=True)
+    created_at = models.DateTimeField(_('created at'), auto_now_add=True)
+    approved = models.BooleanField(_('approved'), default=False)
+    edited_question = models.TextField(_('edited question'), db_index=True, null=True, blank=True,
+            help_text=_("Leave empty if question doesn't need editing."))
+    answer = MarkupField(_('answer'), markup_type='textile_pl', blank=True,
+            help_text=_('Use <a href="http://textile.thresholdstate.com/">Textile</a> syntax.'))
+    answered = models.BooleanField(_('answered'), db_index=True, default=False,
+            help_text=_('Check to send the answer to user.'))
+    answered_at = models.DateTimeField(_('answered at'), null=True, blank=True, db_index=True)
+    published = models.BooleanField(_('published'), db_index=True, default=False,
+        help_text=_('Check to display answered question on site.'))
+    published_at = models.DateTimeField(_('published at'), null=True, blank=True, db_index=True)
+
+    class Meta:
+        ordering = ['-created_at']
+
+    def __unicode__(self):
+        return self.edited_question or self.question
+
+    @models.permalink
+    def get_absolute_url(self):
+        return ('questions_question', (self.pk,))
+
+    def notify_author(self):
+        if not self.email:
+            return
+        site = Site.objects.get_current()
+        context = Context({
+                'question': self,
+                'site': site,
+            })
+        text_content = loader.get_template('questions/answered_mail.txt'
+            ).render(context)
+        html_content = loader.get_template('questions/answered_mail.html'
+            ).render(context)
+        msg = EmailMultiAlternatives(
+            u'Odpowiedź na Twoje pytanie w serwisie %s.' % site.domain,
+            text_content, settings.SERVER_EMAIL, [self.email])
+        msg.attach_alternative(html_content, "text/html")
+        msg.send()
+
+    def save(self, *args, **kwargs):
+        now = datetime.now()
+        if self.answered and not self.answered_at:
+            self.notify_author()
+            self.answered_at = now
+        if self.published and not self.published_at:
+            self.published_at = now
+        super(Question, self).save(*args, **kwargs)
diff --git a/questions/templates/questions/answered_mail.txt b/questions/templates/questions/answered_mail.txt
new file mode 100755 (executable)
index 0000000..57ed289
--- /dev/null
@@ -0,0 +1,19 @@
+{% load i18n %}{% language 'pl' %}{{ question.created_at }} zadałeś/zadałaś pytanie:
+
+{{ question.question|safe }}
+
+
+Odpowiedź:
+
+{{ question.answer.raw|safe }}
+
+{% if question.published %}
+Pytanie wraz z odpowiedzią można znaleźć na stronie:
+http://{{ site.domain }}{{ question.get_absolute_url }}
+{% endif %}
+
+Dziękujemy!
+
+-- 
+{{ site }}
+{% endlanguage %}
\ No newline at end of file
diff --git a/questions/templates/questions/question_detail.html b/questions/templates/questions/question_detail.html
new file mode 100755 (executable)
index 0000000..be19018
--- /dev/null
@@ -0,0 +1,11 @@
+{% extends "base.html" %}
+
+{% block "titleextra" %}{{ question }} :: {% endblock %}
+{% block "body" %}
+<h1>{{ question }}</h1>
+
+{{ question.answer }}
+
+<p><a href="{% url 'questions' %}">Wróć do listy pytań.</a></p>
+
+{% endblock %}
\ No newline at end of file
diff --git a/questions/templates/questions/question_form.html b/questions/templates/questions/question_form.html
new file mode 100755 (executable)
index 0000000..d712219
--- /dev/null
@@ -0,0 +1,18 @@
+{% extends "base.html" %}
+
+{% block "titleextra" %}Pierwsza pomoc w prawie autorskim: pytanie do prawnika :: {% endblock %}
+{% block "body" %}
+<h1>Pierwsza pomoc w prawie autorskim: pytanie do prawnika</h1>
+
+
+
+<form method="post" action="">
+{% csrf_token %}
+<table>
+    {{ form.as_table }}
+    <tr><td></td><td><button>Wyślij</button></td></tr>
+</table>
+</form>
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/questions/templates/questions/question_list.html b/questions/templates/questions/question_list.html
new file mode 100755 (executable)
index 0000000..9432850
--- /dev/null
@@ -0,0 +1,18 @@
+{% extends "base.html" %}
+{% load url from future %}
+
+{% block "titleextra" %}Pierwsza pomoc w prawie autorskim :: {% endblock %}
+{% block "body" %}
+<h1>Pierwsza pomoc w prawie autorskim</h1>
+
+<p class="normal">Jeśli rozwiązania Twojego problemu nie ma na tej stronie,
+<a href="">zajrzyj do naszego podręcznika</a>. Jeśli i to nie pomoże,
+<a href="{% url 'questions_form' %}">zadaj pytanie naszemu prawnikowi</a>.</p>
+  
+<ul>
+{% for question in object_list %}
+    <li><a href="{{ question.get_absolute_url }}">{{ question }}</a></li>
+{% endfor %}
+</ul>
+
+{% endblock %}
\ No newline at end of file
diff --git a/questions/templates/questions/question_thanks.html b/questions/templates/questions/question_thanks.html
new file mode 100755 (executable)
index 0000000..b137678
--- /dev/null
@@ -0,0 +1,9 @@
+{% extends "base.html" %}
+
+{% block "titleextra" %}Dziękujemy za przesłanie pytania :: {% endblock %}
+{% block "body" %}
+<h1>Dziękujemy za przesłanie pytania</h1>
+
+???
+
+{% endblock %}
\ No newline at end of file
diff --git a/questions/urls.py b/questions/urls.py
new file mode 100755 (executable)
index 0000000..9930956
--- /dev/null
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+# This file is part of PrawoKultury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+from django.conf.urls import patterns, url
+from django.views.generic import DetailView, ListView, TemplateView
+from .models import Question
+from .views import QuestionFormView
+
+urlpatterns = patterns('',
+    url(r'^$',
+        ListView.as_view(queryset=Question.objects.filter(published=True
+            ).order_by('-published_at')),
+        name="questions"
+    ),
+    url(r'^(?P<pk>\d+)/$',
+        DetailView.as_view(model=Question),
+        name="questions_question"),
+    url(r'^pytanie/$',
+        QuestionFormView.as_view(),
+        name="questions_form",
+    ),
+    url(r'^pytanie/dziekujemy/$',
+        TemplateView.as_view(
+            template_name="questions/question_thanks.html",
+        ),
+        name="questions_thanks"
+    ),
+)
diff --git a/questions/views.py b/questions/views.py
new file mode 100644 (file)
index 0000000..1c918c8
--- /dev/null
@@ -0,0 +1,13 @@
+from django.core.urlresolvers import reverse_lazy
+from django.views.generic.edit import FormView
+from .forms import QuestionForm
+
+
+class QuestionFormView(FormView):
+    form_class = QuestionForm
+    template_name = "questions/question_form.html"
+    success_url = reverse_lazy("questions_thanks")
+
+    def form_valid(self, form):
+        form.save()
+        return super(QuestionFormView, self).form_valid(form)
index 64674fb..9a4bc1a 100644 (file)
@@ -1,3 +1,5 @@
+-i http://pypi.nowoczesnapolska.org.pl/simple
+
 Django>=1.4,<1.5
 #django_cas
 -e hg+https://bitbucket.org/cpcc/django-cas@197f156ee943#egg=django_cas
 Django>=1.4,<1.5
 #django_cas
 -e hg+https://bitbucket.org/cpcc/django-cas@197f156ee943#egg=django_cas
@@ -6,8 +8,8 @@ PIL
 sorl-thumbnail>=11.09,<12
 django-pagination
 
 sorl-thumbnail>=11.09,<12
 django-pagination
 
--e git+git://github.com/fnp/fnpdjango.git@9a5b05c52311da4f726fec29d8be7d173f695352#egg=fnpdjango
 -e git+git://github.com/fnp/django-migdal.git@a3983327291548497d9bdd3db5976b895675b25e#egg=django-migdal
 -e git+git://github.com/fnp/django-migdal.git@a3983327291548497d9bdd3db5976b895675b25e#egg=django-migdal
+fnpdjango>=0.1.3,<0.2
 
 textile
 django-markupfield
 
 textile
 django-markupfield