Enable questions tagging.
authorRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Fri, 22 Feb 2013 12:35:58 +0000 (13:35 +0100)
committerRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Fri, 22 Feb 2013 12:35:58 +0000 (13:35 +0100)
prawokultury/settings.d/50-contrib.py
questions/admin.py
questions/migrations/0003_auto__add_tag__add_tagitem.py [new file with mode: 0644]
questions/models.py
questions/templates/questions/question_detail.html
questions/templates/questions/question_list.html
questions/urls.py
questions/views.py
requirements.txt

index 10b4f39..4423184 100644 (file)
@@ -17,3 +17,5 @@ CAS_SERVER_URL = 'http://logowanie.nowoczesnapolska.org.pl/cas/'
 CAS_VERSION = '1'
 
 HONEYPOT_FIELD_NAME='miut'
 CAS_VERSION = '1'
 
 HONEYPOT_FIELD_NAME='miut'
+
+TAGGIT_AUTOSUGGEST_MODEL = ('questions', 'Tag')
index 9db5ff7..ec6d715 100755 (executable)
@@ -1,5 +1,5 @@
 from django.contrib import admin
 from django.contrib import admin
-from .models import Question
+from .models import Question, Tag
 
 class QuestionAdmin(admin.ModelAdmin):
     model = Question
 
 class QuestionAdmin(admin.ModelAdmin):
     model = Question
@@ -22,3 +22,4 @@ class QuestionAdmin(admin.ModelAdmin):
 
 
 admin.site.register(Question, QuestionAdmin)
 
 
 admin.site.register(Question, QuestionAdmin)
+admin.site.register(Tag)
diff --git a/questions/migrations/0003_auto__add_tag__add_tagitem.py b/questions/migrations/0003_auto__add_tag__add_tagitem.py
new file mode 100644 (file)
index 0000000..7bf22f7
--- /dev/null
@@ -0,0 +1,77 @@
+# -*- 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 'Tag'
+        db.create_table('questions_tag', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
+            ('slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=100)),
+        ))
+        db.send_create_signal('questions', ['Tag'])
+
+        # Adding model 'TagItem'
+        db.create_table('questions_tagitem', (
+            ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+            ('object_id', self.gf('django.db.models.fields.IntegerField')(db_index=True)),
+            ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(related_name='questions_tagitem_tagged_items', to=orm['contenttypes.ContentType'])),
+            ('tag', self.gf('django.db.models.fields.related.ForeignKey')(related_name='items', to=orm['questions.Tag'])),
+        ))
+        db.send_create_signal('questions', ['TagItem'])
+
+
+    def backwards(self, orm):
+        # Deleting model 'Tag'
+        db.delete_table('questions_tag')
+
+        # Deleting model 'TagItem'
+        db.delete_table('questions_tagitem')
+
+
+    models = {
+        'contenttypes.contenttype': {
+            'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
+            'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+        },
+        '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'}),
+            'changed_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
+            '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'})
+        },
+        'questions.tag': {
+            'Meta': {'object_name': 'Tag'},
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+            'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100'})
+        },
+        'questions.tagitem': {
+            'Meta': {'object_name': 'TagItem'},
+            'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'questions_tagitem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
+            'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+            'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
+            'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'items'", 'to': "orm['questions.Tag']"})
+        }
+    }
+
+    complete_apps = ['questions']
\ No newline at end of file
index 2955ddb..1540191 100644 (file)
@@ -7,9 +7,27 @@ from django.db import models
 from django.template import loader, Context
 from django.utils.translation import ugettext_lazy as _
 from markupfield.fields import MarkupField
 from django.template import loader, Context
 from django.utils.translation import ugettext_lazy as _
 from markupfield.fields import MarkupField
+from taggit.models import TagBase, GenericTaggedItemBase
 from taggit_autosuggest.managers import TaggableManager
 from taggit_autosuggest.managers import TaggableManager
+from fnpdjango.utils.text.slughifi import slughifi
 
 
 
 
+class Tag(TagBase):
+    def slugify(self, tag, i=None):
+        slug = slughifi(tag)
+        if i is not None:
+            slug += "_%d" % i
+        return slug
+
+    class Meta:
+        verbose_name = _("Tag")
+        verbose_name_plural = _("Tags")
+
+
+class TagItem(GenericTaggedItemBase):
+    tag = models.ForeignKey(Tag, related_name="items")
+
 class Question(models.Model):
     email = models.EmailField(_('contact e-mail'), null=True, blank=True)
     question = models.TextField(_('question'), db_index=True)
 class Question(models.Model):
     email = models.EmailField(_('contact e-mail'), null=True, blank=True)
     question = models.TextField(_('question'), db_index=True)
@@ -27,7 +45,7 @@ class Question(models.Model):
         help_text=_('Check to display answered question on site.'))
     published_at = models.DateTimeField(_('published at'), null=True, blank=True, db_index=True)
 
         help_text=_('Check to display answered question on site.'))
     published_at = models.DateTimeField(_('published at'), null=True, blank=True, db_index=True)
 
-    tags = TaggableManager()
+    tags = TaggableManager(through=TagItem)
 
     class Meta:
         ordering = ['-created_at']
 
     class Meta:
         ordering = ['-created_at']
index 2fc5ce0..dea7e14 100755 (executable)
@@ -6,6 +6,14 @@
 <h1>{{ question|linebreaksbr }}</h1>
 
 <div class="normal">
 <h1>{{ question|linebreaksbr }}</h1>
 
 <div class="normal">
+{% if question.tags.all.count %}
+<p>Tematy: 
+{% for tag in question.tags.all %}
+    <a href="{% url 'questions' %}?tag={{ tag.slug }}">{{ tag }}</a>{% if not forloop.last %} / {% endif %}
+{% endfor %}
+{% endif %}
+</p>
+
 {{ question.answer }}
 
 <p><a href="{% url 'questions' %}">Wróć do listy pytań.</a></p>
 {{ question.answer }}
 
 <p><a href="{% url 'questions' %}">Wróć do listy pytań.</a></p>
index 4cad0e9..06fb866 100755 (executable)
@@ -1,5 +1,6 @@
 {% extends "base.html" %}
 {% load url from future %}
 {% extends "base.html" %}
 {% load url from future %}
+{% load pagination_tags fnp_prevnext %}
 
 {% block "titleextra" %}Pierwsza pomoc w prawie autorskim :: {% endblock %}
 {% block "body" %}
 
 {% block "titleextra" %}Pierwsza pomoc w prawie autorskim :: {% endblock %}
 {% block "body" %}
@@ -26,13 +27,39 @@ autorem szeregu publikacji naukowych poświęconych korzystaniu z
 technologii informacyjno-komunikacyjnych oraz posiada wieloletnie
 doświadczenie doradcze w tej tematyce.</p>
 
 technologii informacyjno-komunikacyjnych oraz posiada wieloletnie
 doświadczenie doradcze w tej tematyce.</p>
 
-<h2>Odpowiedzi na już zadane pytania:</h2>
+Tematy: 
+{% if tag %}<a href=".">wszystkie</a>
+{% else %}<strong>wszystkie</strong>
+{% endif %}
+
+{% for atag in tags %} /
+    {% if atag == tag %}<strong>{{ atag }}</strong>
+    {% else %}<a href="?tag={{ atag.slug }}">{{ atag }}</a>
+    {% endif %}
+{% endfor %}
+
+<h2>Odpowiedzi na już zadane pytania
+    {% if tag %}na temat: {{ tag }}{% endif %}
+    ({{ object_list.count }}):</h2>
+
+{% autopaginate object_list 1 %}
 
 <ul class='questions'>
 {% for question in object_list %}
 
 <ul class='questions'>
 {% for question in object_list %}
-    <li><a href="{{ question.get_absolute_url }}">{{ question }}</a></li>
+    <li><a href="{{ question.get_absolute_url }}">{{ question }}</a>
+        {% if question.tags.all.count %}
+        <br/>Tematy: 
+        {% for tag in question.tags.all %}
+            <a href="?tag={{ tag.slug }}">{{ tag }}</a>{% if not forloop.last %} / {% endif %}
+        {% endfor %}
+        {% endif %}
+    </li>
 {% endfor %}
 </ul>
 {% endfor %}
 </ul>
+
 </div>
 
 </div>
 
+{% prevnext %}
+
+
 {% endblock %}
 {% endblock %}
index 2f3c5f2..3073290 100755 (executable)
@@ -3,14 +3,13 @@
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 from django.conf.urls import patterns, url
 # 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 django.views.generic import DetailView, TemplateView
 from .models import Question
 from .models import Question
-from .views import QuestionFormView
+from .views import QuestionFormView, QuestionListView
 
 urlpatterns = patterns('',
     url(r'^$',
 
 urlpatterns = patterns('',
     url(r'^$',
-        ListView.as_view(queryset=Question.objects.filter(published=True
-            ).order_by('-published_at')),
+        QuestionListView.as_view(),
         name="questions"
     ),
     url(r'^(?P<pk>\d+)/$',
         name="questions"
     ),
     url(r'^(?P<pk>\d+)/$',
index 1c918c8..b68d24b 100644 (file)
@@ -1,6 +1,12 @@
+# -*- 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.core.urlresolvers import reverse_lazy
 from django.core.urlresolvers import reverse_lazy
+from django.views.generic import ListView
 from django.views.generic.edit import FormView
 from .forms import QuestionForm
 from django.views.generic.edit import FormView
 from .forms import QuestionForm
+from .models import Question, Tag
 
 
 class QuestionFormView(FormView):
 
 
 class QuestionFormView(FormView):
@@ -11,3 +17,27 @@ class QuestionFormView(FormView):
     def form_valid(self, form):
         form.save()
         return super(QuestionFormView, self).form_valid(form)
     def form_valid(self, form):
         form.save()
         return super(QuestionFormView, self).form_valid(form)
+
+
+class QuestionListView(ListView):
+    def get(self, request, *args, **kwargs):
+        self.tag = None
+        if 'tag' in request.GET:
+            try:
+                self.tag = Tag.objects.get(slug=request.GET['tag'])
+            except Tag.DoesNotExist:
+                pass
+        return super(QuestionListView, self).get(request, *args, **kwargs)
+
+    def get_queryset(self):
+        qs = Question.objects.filter(published=True
+                ).order_by('-published_at')
+        if 'tag' in self.request.GET:
+            qs = qs.filter(tags__slug=self.request.GET['tag'])
+        return qs
+
+    def get_context_data(self, *args, **kwargs):
+        context = super(QuestionListView, self).get_context_data(*args, **kwargs)
+        context['tags'] = Tag.objects.all()
+        context['tag'] = self.tag
+        return context
index ef0a9ff..7697e38 100644 (file)
@@ -9,7 +9,7 @@ django-pagination
 django-honeypot
 
 django-migdal>=0.3.1,<0.4
 django-honeypot
 
 django-migdal>=0.3.1,<0.4
-fnpdjango>=0.1.4,<0.2
+fnpdjango>=0.1.5,<0.2
 
 textile
 django-markupfield
 
 textile
 django-markupfield