diff --git a/app/urls.py b/app/urls.py index 55f7523..b8b2c32 100644 --- a/app/urls.py +++ b/app/urls.py @@ -7,6 +7,7 @@ import core.views.book_search import core.views.chat import core.views.calendar +import core.views.newsletter_signup urlpatterns = [ @@ -17,4 +18,5 @@ path('example/', core.views.example.example, name='example'), path('chat/', core.views.chat.chat, name='chat'), path('calendar/', core.views.calendar.calendar, name="calendar"), + path('newsletter-signup', core.views.newsletter_signup.view, name='newsletter-signup') ] + staticfiles_urlpatterns() diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..d3a0aa0 --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,22 @@ +# Generated by Django 3.2 on 2021-04-25 17:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='NewsletterSubscription', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('email', models.EmailField(max_length=254)), + ('name', models.CharField(max_length=256)), + ], + ), + ] diff --git a/core/models.py b/core/models.py index 71a8362..94f28bd 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,6 @@ from django.db import models -# Create your models here. + +class NewsletterSubscription(models.Model): + email = models.EmailField() + name = models.CharField(max_length=256) diff --git a/core/reflexes/newsletter_signup_reflex.py b/core/reflexes/newsletter_signup_reflex.py new file mode 100644 index 0000000..2f78573 --- /dev/null +++ b/core/reflexes/newsletter_signup_reflex.py @@ -0,0 +1,15 @@ +from sockpuppet.reflex import Reflex + +from core.models import NewsletterSubscription + + +class SubscriptionReflex(Reflex): + def add_person(self): + o = NewsletterSubscription.objects.update_or_create( + name=self.params['name'], + email=self.params['email'] + ) + + def remove_person(self): + id = self.element.dataset['id'] + NewsletterSubscription.objects.filter(id=id).delete() diff --git a/core/templates/_newsletter_signup.html b/core/templates/_newsletter_signup.html new file mode 100644 index 0000000..9513ba4 --- /dev/null +++ b/core/templates/_newsletter_signup.html @@ -0,0 +1,30 @@ +{% load static %} + + +

Sign up for newsletter!

+
+ {{ form }} + +
+

Signed:

+ + + + + + + + + + {% for p in people %} + + + + + + {% endfor %} + +
NameEmailRemove
{{ p.name }} {{ p.email }}Remove
+
+
diff --git a/core/templates/base.html b/core/templates/base.html index f467c00..b91f595 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -38,6 +38,7 @@

  • Example
  • BookSearch
  • Chat
  • +
  • Newsletter Signup
  • diff --git a/core/views/mixins.py b/core/views/mixins.py index 366d751..f5abed5 100644 --- a/core/views/mixins.py +++ b/core/views/mixins.py @@ -51,6 +51,7 @@ class ExampleMixin(MixinBase): ('core/templates/_example_demo.html', 'html', 'htmldjango'), ) + class ChatMixin(MixinBase): files = ( ('core/views/chat.py', 'python', 'python3'), @@ -59,12 +60,19 @@ class ChatMixin(MixinBase): ('core/templates/_chat_demo.html', 'html', 'htmldjango'), ) + class CalendarMixin(MixinBase): files = ( ('core/views/calendar.py', 'python', 'python3'), -# ('core/reflexes/calendar_reflex.py', 'python', 'python3'), -# ('core/javascript/controllers/calendar_controller.js', 'javascript', 'javascript'), ('core/templates/_calendar.html', 'html', 'htmldjango'), ('core/templates/_td_calendar.html', 'html', 'htmldjango'), ) + + +class NewsletterSignupMixin(MixinBase): + files = ( + ('core/views/newsletter_signup.py', 'python', 'python3'), + ('core/reflexes/newsletter_signup_reflex.py', 'python', 'python3'), + ('core/templates/_newsletter_signup.html', 'html', 'htmldjango') + ) diff --git a/core/views/newsletter_signup.py b/core/views/newsletter_signup.py new file mode 100644 index 0000000..03a9b76 --- /dev/null +++ b/core/views/newsletter_signup.py @@ -0,0 +1,25 @@ +from django.forms import ModelForm +from django.views.generic.edit import FormView + +from core.models import NewsletterSubscription +from core.views.mixins import NewsletterSignupMixin + + +class NewsletterSubscriptionForm(ModelForm): + class Meta: + model = NewsletterSubscription + fields = ['name', 'email'] + + +class NewsletterSignupView(NewsletterSignupMixin, FormView): + demo_template = '_newsletter_signup.html' + form_class = NewsletterSubscriptionForm + subtitle = 'Newsletter Signup' + + def get_context_data(self, *args, **kwargs): + context = super().get_context_data(*args, **kwargs) + context['people'] = NewsletterSubscription.objects.all() + return context + + +view = NewsletterSignupView.as_view() diff --git a/requirements.in b/requirements.in index 32f98a0..4d32287 100644 --- a/requirements.in +++ b/requirements.in @@ -5,7 +5,7 @@ django-pygments-renderer django-widget-tweaks django-redis -https://github.com/gilmrjc/django-webpack-loader/archive/webpack-bundle-tracker-1.zip +django-webpack-loader # deployment fabric diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7a3e166 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,65 @@ +# +# This file is autogenerated by pip-compile +# To update, run: +# +# pip-compile --output-file=requirements.txt requirements.in +# +aioredis==1.3.1 # via channels-redis +asgiref==3.3.4 # via channels, channels-redis, daphne, django +async-timeout==3.0.1 # via aioredis +attrs==21.2.0 # via automat, service-identity, twisted +autobahn==21.3.1 # via daphne +automat==20.2.0 # via twisted +bcrypt==3.2.0 # via paramiko +beautifulsoup4==4.9.3 # via bs4 +bs4==0.0.1 # via django-sockpuppet +certifi==2020.12.5 # via requests +cffi==1.14.5 # via bcrypt, cryptography, pynacl +channels-redis==3.2.0 # via django-sockpuppet +channels==3.0.3 # via channels-redis, django-sockpuppet +chardet==4.0.0 # via requests +constantly==15.1.0 # via twisted +cryptography==3.4.7 # via autobahn, paramiko, pyopenssl, service-identity +daphne==3.0.2 # via channels +django-pygments-renderer==0.0.1 # via -r requirements.in +django-redis==4.12.1 # via -r requirements.in +django-seed==0.2.2 # via -r requirements.in +django-sockpuppet==0.6.0 # via -r requirements.in +django-webpack-loader==0.7.0 # via -r requirements.in +django-widget-tweaks==1.4.8 # via -r requirements.in +django==3.2.2 # via -r requirements.in, channels, django-pygments-renderer, django-redis, django-seed +fabric==2.6.0 # via -r requirements.in, patchwork +faker==8.1.2 # via django-seed +gunicorn==20.1.0 # via -r requirements.in +hiredis==2.0.0 # via aioredis +hyperlink==21.0.0 # via autobahn, twisted +idna==2.10 # via hyperlink, requests, twisted +incremental==21.3.0 # via twisted +invoke==1.5.0 # via fabric +msgpack==1.0.2 # via channels-redis +paramiko==2.7.2 # via fabric +patchwork==1.0.1 # via -r requirements.in +pathlib2==2.3.5 # via fabric +pyasn1-modules==0.2.8 # via service-identity +pyasn1==0.4.8 # via pyasn1-modules, service-identity +pycparser==2.20 # via cffi +pygments==2.9.0 # via django-pygments-renderer +pynacl==1.4.0 # via paramiko +pyopenssl==20.0.1 # via twisted +python-dateutil==2.8.1 # via faker +pytz==2021.1 # via django +redis==3.5.3 # via django-redis +requests==2.25.1 # via -r requirements.in +service-identity==21.1.0 # via twisted +six==1.16.0 # via automat, bcrypt, pathlib2, pynacl, pyopenssl, python-dateutil, service-identity +soupsieve==2.2.1 # via beautifulsoup4 +sqlparse==0.4.1 # via django +text-unidecode==1.3 # via faker +twisted[tls]==21.2.0 # via daphne +txaio==21.2.1 # via autobahn +urllib3==1.26.4 # via requests +whitenoise==5.2.0 # via -r requirements.in +zope.interface==5.4.0 # via twisted + +# The following packages are considered to be unsafe in a requirements file: +# setuptools