diff --git a/ttadmin/guestbook/admin.py b/ttadmin/guestbook/admin.py new file mode 100644 index 0000000..30b12a9 --- /dev/null +++ b/ttadmin/guestbook/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from .models import GuestbookMessage + +@admin.register(GuestbookMessage) +class TicketAdmin(admin.ModelAdmin): + list_display = ('name', 'datetime_created', 'msg') diff --git a/ttadmin/guestbook/forms.py b/ttadmin/guestbook/forms.py new file mode 100644 index 0000000..2be32c6 --- /dev/null +++ b/ttadmin/guestbook/forms.py @@ -0,0 +1,47 @@ +from datetime import datetime, timedelta + +from django.core.exceptions import ValidationError +from django.forms import Form, CharField, EmailField, Textarea, ChoiceField + +from common.forms import CaptchaField + + +# this should go in something like redis. I refuse, however, to involve redis +# in all of this until i have 2-3 more usecases. +# TODO generalize +submission_throttle = {} + +def throttle_submission(name): + last_submission = submission_throttle.get(name) + now = datetime.now() + if last_submission is None\ + or now - last_submission > timedelta(minutes=30): + submission_throttle[name] = datetime.now() + else: + raise ValidationError('you have submitted pretty recently. try again in a bit.') + +def validate_msg_text(msg): + if len(msg) == 0: + raise ValidationError('message cannot be empty') + if len(msg) > 500: + raise ValidationError('too long') + + +class GuestbookForm(Form): + name = CharField(label='name!') + msg = CharField( + widget=Textarea, + label="message!", + validators=(validate_msg_text,), + ) + captcha = CaptchaField() + + def clean(self): + result = super().clean() + + throttle_submission(result['name']) + + if self.errors: + raise ValidationError('oops, looks like there were some problems below.') + + return result diff --git a/ttadmin/guestbook/migrations/0001_initial.py b/ttadmin/guestbook/migrations/0001_initial.py new file mode 100644 index 0000000..7c9a534 --- /dev/null +++ b/ttadmin/guestbook/migrations/0001_initial.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.2 on 2016-12-20 05:08 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='GuestbookMessage', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=50)), + ('msg', models.TextField(max_length=500)), + ('datetime_created', models.DateTimeField(auto_now_add=True)), + ], + ), + ] diff --git a/ttadmin/guestbook/migrations/__init__.py b/ttadmin/guestbook/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ttadmin/guestbook/models.py b/ttadmin/guestbook/models.py new file mode 100644 index 0000000..62b80a5 --- /dev/null +++ b/ttadmin/guestbook/models.py @@ -0,0 +1,7 @@ +from django.db.models import Model, TextField, CharField, DateTimeField + + +class GuestbookMessage(Model): + name = CharField(blank=False, null=False, max_length=50) + msg = TextField(blank=False, null=False, max_length=500) + datetime_created = DateTimeField(auto_now_add=True) diff --git a/ttadmin/guestbook/templates/guestbook/guestbook.html b/ttadmin/guestbook/templates/guestbook/guestbook.html new file mode 100644 index 0000000..03cfba0 --- /dev/null +++ b/ttadmin/guestbook/templates/guestbook/guestbook.html @@ -0,0 +1,56 @@ + + + + tilde.town guestbook + + + + +

tilde.town guestbook

+ ~*~*~*~*say hello*~*~*~*~ +
+ {% csrf_token %} + + {{form.as_table}} +
+ +
+ + {% for m in messages %} +

+ {{m.name}} says: {{m.msg}} +

+ {% endfor %} + + diff --git a/ttadmin/guestbook/urls.py b/ttadmin/guestbook/urls.py new file mode 100644 index 0000000..14a9653 --- /dev/null +++ b/ttadmin/guestbook/urls.py @@ -0,0 +1,8 @@ +from django.conf.urls import url + +from .views import GuestbookView + +app_name = 'guestbook' +urlpatterns = [ + url(r'^$', GuestbookView.as_view(), name='guestbook'), +] diff --git a/ttadmin/guestbook/views.py b/ttadmin/guestbook/views.py new file mode 100644 index 0000000..ce8f43c --- /dev/null +++ b/ttadmin/guestbook/views.py @@ -0,0 +1,21 @@ +from django.shortcuts import redirect +from django.views.generic import TemplateView +from django.views.generic.edit import FormView + +from .forms import GuestbookForm +from .models import GuestbookMessage + + +class GuestbookView(FormView): + form_class = GuestbookForm + template_name = 'guestbook/guestbook.html' + + def get_context_data(self, **kwargs): + ctx = super().get_context_data(**kwargs) + ctx['messages'] = GuestbookMessage.objects.order_by('-datetime_created') + return ctx + + def form_valid(self, form): + del form.cleaned_data['captcha'] + t = GuestbookMessage.objects.create(**form.cleaned_data) + return redirect('guestbook:guestbook') diff --git a/ttadmin/settings.py b/ttadmin/settings.py index 8ab6658..d912b38 100644 --- a/ttadmin/settings.py +++ b/ttadmin/settings.py @@ -26,6 +26,7 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'users', 'help', + 'guestbook' ] MIDDLEWARE = [ diff --git a/ttadmin/urls.py b/ttadmin/urls.py index f1c10ee..5f457e5 100644 --- a/ttadmin/urls.py +++ b/ttadmin/urls.py @@ -4,5 +4,6 @@ from django.contrib import admin urlpatterns = [ url(r'^help/', include('help.urls')), url(r'^users/', include('users.urls')), + url(r'^guestbook/', include('guestbook.urls')), url(r'^admin/', admin.site.urls), ]