--- /dev/null
+# encoding: 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 'Poem'
+ db.create_table('lesmianator_poem', (
+ ('view_count', self.gf('django.db.models.fields.IntegerField')(default=1)),
+ ('text', self.gf('django.db.models.fields.TextField')()),
+ ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+ ('created_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'])),
+ ('slug', self.gf('django.db.models.fields.SlugField')(max_length=120, db_index=True)),
+ ('created_from', self.gf('catalogue.fields.JSONField')(null=True, blank=True)),
+ ('seen_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ))
+ db.send_create_signal('lesmianator', ['Poem'])
+
+ # Adding model 'Continuations'
+ db.create_table('lesmianator_continuations', (
+ ('pickle', self.gf('django.db.models.fields.files.FileField')(max_length=100)),
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('content_type', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['contenttypes.ContentType'])),
+ ('object_id', self.gf('django.db.models.fields.PositiveIntegerField')()),
+ ))
+ db.send_create_signal('lesmianator', ['Continuations'])
+
+
+ def backwards(self, orm):
+
+ # Deleting model 'Poem'
+ db.delete_table('lesmianator_poem')
+
+ # Deleting model 'Continuations'
+ db.delete_table('lesmianator_continuations')
+
+
+ models = {
+ 'auth.group': {
+ 'Meta': {'object_name': 'Group'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
+ 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
+ },
+ 'auth.permission': {
+ 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
+ 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ },
+ 'auth.user': {
+ 'Meta': {'object_name': 'User'},
+ 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
+ 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}),
+ 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}),
+ 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
+ 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
+ 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
+ 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
+ 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
+ },
+ 'contenttypes.contenttype': {
+ 'Meta': {'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'})
+ },
+ 'lesmianator.continuations': {
+ 'Meta': {'object_name': 'Continuations'},
+ 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'object_id': ('django.db.models.fields.PositiveIntegerField', [], {}),
+ 'pickle': ('django.db.models.fields.files.FileField', [], {'max_length': '100'})
+ },
+ 'lesmianator.poem': {
+ 'Meta': {'object_name': 'Poem'},
+ 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'created_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
+ 'created_from': ('catalogue.fields.JSONField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'seen_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '120', 'db_index': 'True'}),
+ 'text': ('django.db.models.fields.TextField', [], {}),
+ 'view_count': ('django.db.models.fields.IntegerField', [], {'default': '1'})
+ }
+ }
+
+ complete_apps = ['lesmianator']
--- /dev/null
+# -*- coding: utf-8 -*-
+# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+import cPickle
+from datetime import datetime
+from random import randint
+from StringIO import StringIO
+
+from django.core.files.base import ContentFile
+from django.db import models
+from django.db.models import permalink
+from django.utils.translation import ugettext_lazy as _
+from django.core.urlresolvers import reverse
+from django.db.models.signals import m2m_changed
+from django.contrib.auth.models import User
+from django.contrib.contenttypes.models import ContentType
+from django.contrib.contenttypes import generic
+from django.conf import settings
+
+from librarian import text
+from catalogue.fields import JSONField
+from catalogue.models import Book, Tag
+
+
+class Poem(models.Model):
+ slug = models.SlugField(_('slug'), max_length=120, db_index=True)
+ text = models.TextField(_('text'))
+ created_by = models.ForeignKey(User)
+ created_from = JSONField(_('extra information'), null=True, blank=True)
+ created_at = models.DateTimeField(_('creation date'), auto_now_add=True, editable=False)
+ seen_at = models.DateTimeField(_('last view date'), auto_now_add=True, editable=False)
+ view_count = models.IntegerField(_('view count'), default=1)
+
+ try:
+ f = open(settings.LESMIANATOR_PICKLE)
+ global_dictionary = cPickle.load(f)
+ f.close()
+ except:
+ global_dictionary = {}
+
+ def visit(self):
+ self.view_count += 1
+ self.seen_at = datetime.now()
+ self.save()
+
+ def __unicode__(self):
+ return "%s (%s...)" % (self.slug, self.text[:20])
+
+ @classmethod
+ def write(cls, continuations=None, length=3, maxlen=1000):
+ def choose_word(word, continuations):
+ try:
+ choices = sum((continuations[word][post] for post in continuations[word]))
+ r = randint(0, choices - 1)
+
+ for post in continuations[word]:
+ r -= continuations[word][post]
+ if r < 0:
+ return post
+ except KeyError:
+ return ''
+
+
+ if continuations is None:
+ continuations = cls.global_dictionary
+
+ letters = []
+ word = u''
+ empty = -10
+ lines = 0
+ if not continuations:
+ maxlen = 0
+ # want at least two lines, but let Lesmianator end his stanzas
+ while (empty < 2 or lines < 2) and maxlen:
+ letter = choose_word(word, continuations)
+ letters.append(letter)
+ word = word[-length+1:] + letter
+ if letter == u'\n':
+ # count non-empty lines
+ if empty == 0:
+ lines += 1
+ #
+ if lines >= 2:
+ empty += 1
+ lines += 1
+ else:
+ empty = 0
+ maxlen -= 1
+
+ return ''.join(letters).strip()
+
+ def get_absolute_url(self):
+ return reverse('get_poem', kwargs={'poem': self.slug})
+
+
+class Continuations(models.Model):
+ pickle = models.FileField(_('Continuations file'), upload_to='lesmianator')
+ content_type = models.ForeignKey(ContentType)
+ object_id = models.PositiveIntegerField()
+ content_object = generic.GenericForeignKey('content_type', 'object_id')
+
+ def __unicode__(self):
+ return "Continuations for: %s" % unicode(self.content_object)
+
+ @staticmethod
+ def join_conts(a, b):
+ for pre in b:
+ a.setdefault(pre, {})
+ for post in b[pre]:
+ a[pre].setdefault(post, 0)
+ a[pre][post] += b[pre][post]
+ return a
+
+ @classmethod
+ def for_book(cls, book, length=3):
+ # count from this book only
+ print 'for_book', book
+ output = StringIO()
+ f = open(book.xml_file.path)
+ text.transform(f, output, False, ('raw-text',))
+ f.close()
+ conts = {}
+ last_word = ''
+ for letter in output.getvalue().decode('utf-8').strip().lower():
+ mydict = conts.setdefault(last_word, {})
+ mydict.setdefault(letter, 0)
+ mydict[letter] += 1
+ last_word = last_word[-length+1:] + letter
+ # add children
+ return reduce(cls.join_conts,
+ (cls.get(child) for child in book.children.all()),
+ conts)
+
+ @classmethod
+ def for_set(cls, tag):
+ # book contains its descendants, we don't want them twice
+ books = Book.tagged.with_any((tag,))
+ l_tags = Tag.objects.filter(category='book', slug__in=[book.book_tag_slug() for book in books])
+ descendants_keys = [book.pk for book in Book.tagged.with_any(l_tags)]
+ if descendants_keys:
+ books = books.exclude(pk__in=descendants_keys)
+
+ cont_tabs = (cls.get(b) for b in books)
+ return reduce(cls.join_conts, cont_tabs)
+
+ @classmethod
+ def get(cls, sth):
+ object_type = ContentType.objects.get_for_model(sth)
+ try:
+ obj = cls.objects.get(content_type=object_type, object_id=sth.id)
+ f = open(obj.pickle.path)
+ conts = cPickle.load(f)
+ f.close()
+ return conts
+ except cls.DoesNotExist:
+ if isinstance(sth, Book):
+ conts = cls.for_book(sth)
+ elif isinstance(sth, Tag):
+ conts = cls.for_set(sth)
+ else:
+ raise NotImplemented('Lesmianator continuations: only Book and Tag supported')
+
+ c = cls(content_object=sth)
+ c.pickle.save(sth.slug+'.p', ContentFile(cPickle.dumps(conts)))
+ c.save()
+ return conts
+
+
--- /dev/null
+# -*- coding: utf-8 -*-
+# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('lesmianator.views',
+ url(r'^$', 'main_page', name='lesmianator'),
+ url(r'^wiersz/$', 'new_poem', name='new_poem'),
+ url(r'^lektura/(?P<slug>[a-zA-Z0-9-]+)/$', 'poem_from_book', name='poem_from_book'),
+ url(r'^polka/(?P<shelf>[a-zA-Z0-9-]+)/$', 'poem_from_set', name='poem_from_set'),
+ url(r'^wiersz/(?P<poem>[a-zA-Z0-9-]+)/$', 'get_poem', name='get_poem'),
+)
+
# Create your views here.
-import cPickle
-from django.shortcuts import render_to_response
+from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
-from random import randint
-
-
-def _choose_word(word):
- try:
- choices = sum((_dictionary[word][post] for post in _dictionary[word]))
- r = randint(0, choices - 1)
-
- for post in _dictionary[word]:
- r -= _dictionary[word][post]
- if r < 0:
- return post
- except KeyError:
- return ''
-
-# load dictionary on start, it won't change
-from django.conf import settings
-
-try:
- f = open(settings.LESMIANATOR_PICKLE)
- _dictionary = cPickle.load(f)
-except:
- _dictionary = {}
-
-
-def poem(request):
- letters = []
- word = u''
- empty = -10
- left = 1000
- lines = 0
- if not _dictionary:
- left = 0
- # want at least two lines, but let Lesmianator end his stanzas
- while (empty < 2 or lines < 2) and left:
- letter = _choose_word(word)
- letters.append(letter)
- word = word[-2:] + letter
- if letter == u'\n':
- # count non-empty lines
- if empty == 0:
- lines += 1
- #
- if lines >= 2:
- empty += 1
- lines += 1
- else:
- empty = 0
- left -= 1
-
- poem = ''.join(letters).strip()
+from django.contrib.auth.decorators import login_required
+from django.views.decorators import cache
+
+from catalogue.utils import get_random_hash
+from catalogue.models import Book, Tag
+from catalogue import forms
+from lesmianator.models import Poem, Continuations
+
+
+def main_page(request):
+ last = Poem.objects.all().order_by('-created_at')[:10]
+ form = forms.SearchForm()
+ shelves = Tag.objects.filter(user__username='lesmianator')
+
+ return render_to_response('lesmianator/lesmianator.html',
+ {"last": last, "form": form, "shelves": shelves},
+ context_instance=RequestContext(request))
+
+
+@cache.never_cache
+def new_poem(request):
+ user = request.user if request.user.is_authenticated else None
+ text = Poem.write()
+ p = Poem(slug=get_random_hash(text), text=text, created_by=user)
+ p.save()
+
+ return render_to_response('lesmianator/poem.html',
+ {"poem": p},
+ context_instance=RequestContext(request))
+
+
+@cache.never_cache
+def poem_from_book(request, slug):
+ book = get_object_or_404(Book, slug=slug)
+ user = request.user if request.user.is_authenticated else None
+ text = Poem.write(Continuations.get(book))
+ p = Poem(slug=get_random_hash(text), text=text, created_by=user)
+ p.set_created_from_value([book.id])
+ p.save()
return render_to_response('lesmianator/poem.html',
- {"object": poem},
+ {"poem": p, "books": [book], "book": book},
context_instance=RequestContext(request))
+
+
+@cache.never_cache
+@login_required
+def poem_from_set(request, shelf):
+ user = request.user
+ tag = get_object_or_404(Tag, category='set', slug=shelf)
+ text = Poem.write(Continuations.get(tag))
+ p = Poem(slug=get_random_hash(text), text=text, created_by=user)
+ books = Book.tagged.with_any((tag,))
+ p.set_created_from_value([b.id for b in books])
+ p.save()
+
+ book = books[0] if len(books) == 1 else None
+
+ return render_to_response('lesmianator/poem.html',
+ {"poem": p, "shelf": tag, "books": books, "book": book},
+ context_instance=RequestContext(request))
+
+def get_poem(request, poem):
+ p = get_object_or_404(Poem, slug=poem)
+ p.visit()
+ books = Book.objects.filter(id__in=p.get_created_from_value())
+ book = books[0] if len(books) == 1 else None
+
+ return render_to_response('lesmianator/poem.html',
+ {"poem": p, "books": books, "book": book},
+ context_instance=RequestContext(request))
+
+
-Subproject commit c69605017947202b0bbd0a2a2335cb37752141b9
+Subproject commit f492e325efb42a3348b2479a0fd0ffc3c484657b
top: -4px;
}
+#footnotes {
+ margin-top: 3em;
+}
+
#footnotes .annotation {
display: block;
float: left;
margin: 1.5em 0 0 0;
}
-#footnotes p {
+#footnotes p, #footnotes ul {
margin-left: 2.5em;
font-size: 0.875em;
}
+#footnotes .permalink {
+ font-size: .75em;
+}
+
blockquote {
font-size: 0.875em;
}
border-right: 0.15em solid #E3D888;
}
+#lesmianator #tags-list,
#tagged-object-list #tags-list, #book-detail #tags-list {
margin-left: 39em;
}
{% endif %}
</ul>
<p><a href="{{ book.xml_file.url }}">{% trans "View XML source" %}</a></p>
+ <p><a href="{% url poem_from_book book.slug %}">Miksuj ten utwór</a></p>
</div>
<div id="themes-list">
<h2>{% trans "Work's themes " %}</h2>
<h2>{% trans "Epochs" %}</h2>
{% tag_list categories.epoch tags %}
{% endif %}
+ {% if only_shelf %}
+ <p><a href="{% url poem_from_set tags.0.slug %}">Miksuj utwory z tej półki</a>
+ {% endif %}
</div>
<div id="themes-list">
{% if categories.theme %}
--- /dev/null
+{% extends "base.html" %}
+{% load i18n %}
+{% load catalogue_tags %}
+
+{% block title %}Leśmianator w WolneLektury.pl{% endblock %}
+
+{% block bodyid %}lesmianator{% endblock %}
+
+{% block body %}
+ <h1>Leśmianator</h1>
+ <form action="{% url search %}" method="get" accept-charset="utf-8" id="search-form">
+ <p>{{ form.q }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url main_page %}">{% trans "return to main page" %}</a></p>
+ </form>
+
+ <div id="books-list">
+ <p>Leśmianator tworzy wierszmiksy – dzięki niemu
+ <a href="{% url new_poem %}">napiszesz wiersz jednym kliknięciem</a>.
+ W nowej odłonie nowe możliwości zabawy – teraz możesz zdecydować, co wrzucasz do miksera,
+ a swoimi dziełami podzielić się z przyjaciółmi!</p>
+ <p>Przygotowaliśmy kilka propozycji na start – możesz wybrać jedną z nich,
+ albo ułożyć sobie własną, niepowtarzalną mieszankę.</p>
+ <ul>
+ <li><h2><a href="{% url poem_from_book 'liryki-lozanskie' %}">Adam Mickiewicz, Liryki lozańskie</a></h2></li>
+ <li><h2><a href="{% url poem_from_book 'sonety-krymskie' %}">Adam Mickiewicz, Sonety krymskie</a></h2></li>
+ <li><h2><a href="{% url poem_from_book 'hymny' %}">Jan Kasprowicz, Hymny</a></h2></li>
+ <li><h2><a href="{% url poem_from_book 'bogurodzica' %}">Bogurodzica</a></h2></li>
+ {% for s in shelves %}
+ <li><h2><a href="{% url poem_from_set s.slug %}">{{ s.name }}</a></h2></li>
+ {% endfor %}
+
+ </div>
+
+ <div id="tags-list">
+ <h3>Miksuj utwory</h3>
+ <p>Możesz <a href="{% url new_poem %}">zmiksować całą lirykę</a> w naszej bibliotece
+ albo tylko jeden konkretny utwór. Jak? Wejdź na
+ <a href="{% url book_detail 'do-m' %}">stronę utworu</a>,
+ kliknij w link „miksuj ten utwór” – i gotowe!</p>
+
+ <h3>Miksuj półki</h3>
+ <p>Załóż konto, poukładaj swoje ulubione książki na półkach i miksuj
+ w dowolnych konfiguracjach. Nic prostszego, niż zmieszać
+ <a href="{% url tagged_object_list 'autor/boleslaw-lesmian' %}">Leśmiana</a> z
+ <a href="{% url tagged_object_list 'autor/kazimierz-przerwa-tetmajer' %}">Tetmajerem</a>,
+ a <a href="{% url tagged_object_list 'autor/stefan-zeromski' %}">Żeromskiego</a> z
+ <a href="{% url tagged_object_list 'autor/henryk-sienkiewicz' %}">Sienkiewiczem</a>
+ – wystarczy wrzucić ich utwory na półkę i kliknąć
+ w link „miksuj utwory z tej półki”.</p>
+
+ <h3>Dziel się z innymi</h3>
+ <p>Wyszedł Ci wyjątkowo udany wierszmiks? Znajdziesz pod nim link, przy pomocy
+ którego możesz się nim podzielić z przyjaciółmi.</p>
+
+ <p>Miłej zabawy!</p>
+
+ </div>
+{% endblock %}
\ No newline at end of file
{% load i18n %}
-{% load chunks compressed catalogue_tags %}
+{% load compressed %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
</head>
<body>
<div id="menu">
- <a href='' class='menu-link'>Twórzże się jeszcze raz!</a>
- <span style='float: right'>Poezja z Wolnych Lektur przepuszczona przez mikser.</a>
+ {% if shelf or not books %}
+ {# shelf or global mixing #}
+ <a href='' class='menu-link'>Twórzże się jeszcze raz!</a>
+ {% else %}{% if book %}
+ <a href='{% url poem_from_book book.slug %}' class='menu-link'>Twórzże się jeszcze raz!</a>
+ {% endif %}{% endif %}
+ <span style='float: right'>Wolne Lektury przepuszczone przez mikser.</a>
</div>
<div id="header">
<div id="logo">
<span class="author">Leśmianator</span>
<span class="title">***</span>
</h1>
- {{ object|linebreaksbr }}
+ {{ poem.text|linebreaksbr }}
+ <div id="footnotes" >
+ <h3>O utworze</h3>
+ <div><p>
+ Aby pokazać innym ten utwór, użyj linku:<br/>
+ <a class="permalink" href="{{ poem.get_absolute_url }}">http://www.wolnelektury.pl{{ poem.get_absolute_url }}</a>
+ </p></div>
+ <div>
+ {% if book %}
+ <p>Tekst powstał przez zmiksowanie utworu
+ <a href="{{ book.get_absolute_url }}">{{ book.title }}</a>.<br/>
+ <a href="{% url poem_from_book book.slug %}">Zmiksuj go ponownie</a>
+ albo <a href="{% url lesmianator %}">zobacz</a>, co jeszcze możesz zamieszać.</p>
+ {% else %}{% if books %}
+ <p>Tekst powstał przez zmiksowanie utworów:</p>
+ <ul>
+ {% for book in books %}
+ <li><a href="{{ book.get_absolute_url }}">{{ book.title }}</a></li>
+ {% endfor %}
+ </ul>
+ {% if shelf %}
+ <a href="">Zmiksuj</a>
+ półkę <a href="{{ shelf.get_absolute_url }}">{{ shelf.name }}</a>
+ jeszcze raz, albo
+ <a href="{% url lesmianator %}">zobacz</a>, co jeszcze możesz zamieszać.</p>
+ {% else %}
+ <p><a href="{% url lesmianator %}">Zobacz</a>,
+ jak łatwo możesz stworzyć własny wierszmiks.</p>
+ {% endif %}
+ {% else %}
+ <p>Wiersz powstał przez zmiksowanie ze sobą całej liryki z Wolnych Lektur.
+ <a href="">Spróbuj jeszcze raz</a>, albo
+ <a href="{% url lesmianator %}">zobacz</a>, co jeszcze możesz zamieszać.</p>
+ {% endif %}{% endif %}
+ <div>
+ </div>
</div>
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
url(r'^materialy/', include('lessons.urls')),
url(r'^opds/', include('opds.urls')),
url(r'^sugestia/', include('suggest.urls')),
- url(r'^lesmianator/?$', 'lesmianator.views.poem', name='lesmianator'),
+ url(r'^lesmianator/', include('lesmianator.urls')),
# Static pages
url(r'^wolontariat/$', 'infopages.views.infopage', {'slug': 'voluntary_services'}, name='voluntary_services'),