Compare commits

..

3 Commits

Author SHA1 Message Date
335467a30d renamed users application to user 2018-09-05 14:13:47 -04:00
ab5061c2fa edit_quest page added 2018-09-05 12:48:24 -04:00
eaef094444 page titles populate drop down on quest page 2018-09-05 12:22:45 -04:00
35 changed files with 216 additions and 320 deletions

View File

@ -5,7 +5,7 @@ By popular demand, I'm building a better anonkun. It doesn't do much right now t
Python 3.6+
PostgreSQL 10.4+
Redis 4.0.10+
Python packages: `django psycopg2 channels channels_redis jinja2 argon2-cffi`
Python packages: `django psycopg2 channels channels_redis jinja2 argon2-cffi bleach`
## Install
```

View File

@ -6,13 +6,14 @@ from django.contrib import messages
from django.shortcuts import redirect, render
from .forms import QuestForm, PostForm
from quest.models import Quest, Post
from quest.models import Quest, Post, PageTitle
def index(request):
"""
The index page for creating new quests.
"""
if request.method == 'POST':
# TODO: clean the post body
quest = Quest(owner=request.user)
quest_form = QuestForm(request.POST, instance=quest)
post = Post(post_type='text', page_num=1)
@ -21,6 +22,12 @@ def index(request):
quest.save()
post.quest = quest
post.save()
page = PageTitle(
quest=quest,
page_num=1,
title="Page 1"
)
page.save()
return redirect('quest:quest', quest_id=quest.id)
else:
quest_form = QuestForm()

View File

@ -0,0 +1,31 @@
{% extends "base.html" %}
{% block title %}Edit {{ quest.title }}{% endblock %}
{% block content %}
<center><h1>{{ quest.title }}</h1></center>
<form method="post" action="{{ url('quest:edit_quest', args=[quest_id]) }}">
{{ csrf_input }}
<table>
<tr>
<td>Quest Title:</td>
<td><input type="text" name="quest_title" value="{{ quest.title }}"></td>
</tr>
<tr>
<td>Visible:</td>
<td><input type="checkbox" name="visible" value="on"></td>
</tr>
<tr>
<td>Anonymous Name:</td>
<td><input type="text" name="anon_name" value="Anonymous"></td>
</tr>
<tr>
<td>Live:</td>
<td><input type="checkbox" name="live" value="off"></td>
</tr>
<tr>
<td>Live In:</td>
<td>Placeholder</td>
</tr>
</table>
<input type="submit">
</form>
{% endblock %}

View File

@ -15,13 +15,13 @@
{% endblock %}
{% block header %}
{% if request.user == quest.owner %}
<li><a href="{# url('edit_quest:index', quest_id=quest_id) #}">Edit Quest</a></li>
<li><a href="{{ url('quest:edit_quest', args=[quest_id]) }}">Edit Quest</a></li>
{% endif %}
<li>
<select onChange="window.location.href=this.value">
{# for page in pages %}
<option value="{{ url_for('.quest', quest_id=quest_id, page_num=page[1]) }}"{% if page[1] == page_num %} selected="yes"{% endif %}>{{ page[2] }}</option>
{% endfor #}
{% for page in pages %}
<option value="{{ url('quest:quest', args=[quest_id, page.page_num]) }}"{% if page.page_num == page_num %} selected="yes"{% endif %}>{{ page.title }}</option>
{% endfor %}
</select>
</li>
{% endblock %}

View File

@ -1,6 +1,6 @@
# Generated by Django 2.1 on 2018-08-12 20:09
# Generated by Django 2.1.1 on 2018-09-05 17:44
from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
@ -10,10 +10,17 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Message',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('timestamp', models.DateTimeField(auto_now=True)),
('message', models.TextField(max_length=512)),
],
),
migrations.CreateModel(
name='PageTitle',
fields=[
@ -22,6 +29,20 @@ class Migration(migrations.Migration):
('title', models.CharField(max_length=200)),
],
),
migrations.CreateModel(
name='PollOption',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('text', models.CharField(max_length=200)),
],
),
migrations.CreateModel(
name='PollVote',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('ip_address', models.GenericIPAddressField()),
],
),
migrations.CreateModel(
name='Post',
fields=[
@ -36,19 +57,36 @@ class Migration(migrations.Migration):
name='Quest',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('quest_name', models.CharField(max_length=200)),
('open_post_id', models.IntegerField(null=True)),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('title', models.CharField(max_length=200)),
],
),
migrations.AddField(
model_name='post',
name='quest',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.Quest'),
migrations.CreateModel(
name='DiceCall',
fields=[
('post', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='quest.Post')),
('dice_roll', models.CharField(max_length=9)),
('strict', models.BooleanField()),
('dice_challenge', models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(999), django.core.validators.MinValueValidator(1)])),
('rolls_taken', models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(99), django.core.validators.MinValueValidator(1)])),
('open', models.BooleanField()),
],
),
migrations.AddField(
model_name='pagetitle',
name='quest',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.Quest'),
migrations.CreateModel(
name='DiceRoll',
fields=[
('message', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='quest.Message')),
('roll', models.CharField(max_length=9)),
('results', models.TextField()),
('total', models.IntegerField()),
],
),
migrations.CreateModel(
name='Poll',
fields=[
('post', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='quest.Post')),
('multi_choice', models.BooleanField()),
('allow_writein', models.BooleanField()),
('open', models.BooleanField()),
],
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 2.1 on 2018-08-12 20:12
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('quest', '0001_initial'),
]
operations = [
migrations.RenameField(
model_name='quest',
old_name='quest_name',
new_name='title',
),
]

View File

@ -0,0 +1,67 @@
# Generated by Django 2.1.1 on 2018-09-05 17:44
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('quest', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='quest',
name='owner',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='post',
name='quest',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.Quest'),
),
migrations.AddField(
model_name='pollvote',
name='option',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.PollOption'),
),
migrations.AddField(
model_name='pollvote',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='pagetitle',
name='quest',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.Quest'),
),
migrations.AddField(
model_name='message',
name='quest',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.Quest'),
),
migrations.AddField(
model_name='message',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AlterUniqueTogether(
name='pollvote',
unique_together={('option', 'ip_address')},
),
migrations.AddField(
model_name='polloption',
name='poll',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.Poll'),
),
migrations.AddField(
model_name='diceroll',
name='dicecall',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.DiceCall'),
),
]

View File

@ -1,26 +0,0 @@
# Generated by Django 2.1 on 2018-08-17 11:19
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('quest', '0002_auto_20180812_1612'),
]
operations = [
migrations.CreateModel(
name='Message',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField(auto_now=True)),
('message', models.TextField(max_length=512)),
('quest', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.Quest')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -1,20 +0,0 @@
# Generated by Django 2.1 on 2018-08-17 11:24
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('quest', '0003_message'),
]
operations = [
migrations.AlterField(
model_name='message',
name='user',
field=models.ForeignKey(blank=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]

View File

@ -1,20 +0,0 @@
# Generated by Django 2.1 on 2018-08-17 11:39
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('quest', '0004_auto_20180817_0724'),
]
operations = [
migrations.AlterField(
model_name='message',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 2.1 on 2018-08-17 13:21
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('quest', '0005_auto_20180817_0739'),
]
operations = [
migrations.RenameField(
model_name='message',
old_name='date',
new_name='timestamp',
),
]

View File

@ -1,25 +0,0 @@
# Generated by Django 2.1 on 2018-08-23 15:46
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('quest', '0006_auto_20180817_0921'),
]
operations = [
migrations.CreateModel(
name='DiceCall',
fields=[
('post', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='quest.Post')),
('dice_roll', models.CharField(max_length=9)),
('strict', models.BooleanField()),
('dice_challenge', models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(999), django.core.validators.MinValueValidator(1)])),
('rolls_taken', models.IntegerField(blank=True, null=True, validators=[django.core.validators.MaxValueValidator(99), django.core.validators.MinValueValidator(1)])),
],
),
]

View File

@ -1,22 +0,0 @@
# Generated by Django 2.1 on 2018-08-24 12:55
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('quest', '0007_dicecall'),
]
operations = [
migrations.RemoveField(
model_name='quest',
name='open_post_id',
),
migrations.AddField(
model_name='dicecall',
name='open',
field=models.BooleanField(default=False),
),
]

View File

@ -1,24 +0,0 @@
# Generated by Django 2.1 on 2018-08-25 01:06
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('quest', '0008_auto_20180824_0855'),
]
operations = [
migrations.CreateModel(
name='DiceRoll',
fields=[
('message', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='quest.Message')),
('roll', models.CharField(max_length=9)),
('results', models.TextField()),
('total', models.IntegerField()),
('dicecall', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.DiceCall')),
],
),
]

View File

@ -1,47 +0,0 @@
# Generated by Django 2.1 on 2018-08-29 17:08
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('quest', '0009_diceroll'),
]
operations = [
migrations.CreateModel(
name='Poll',
fields=[
('post', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to='quest.Post')),
('multi_choice', models.BooleanField()),
('allow_writein', models.BooleanField()),
('open', models.BooleanField()),
],
),
migrations.CreateModel(
name='PollOption',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('text', models.CharField(max_length=200)),
('poll', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.Poll')),
],
),
migrations.CreateModel(
name='PollVote',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('ip_address', models.GenericIPAddressField()),
('option', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='quest.PollOption')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.AlterField(
model_name='dicecall',
name='open',
field=models.BooleanField(),
),
]

View File

@ -1,20 +0,0 @@
# Generated by Django 2.1 on 2018-09-03 00:07
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('quest', '0010_auto_20180829_1308'),
]
operations = [
migrations.AlterField(
model_name='pollvote',
name='user',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]

View File

@ -1,17 +0,0 @@
# Generated by Django 2.1 on 2018-09-04 11:32
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('quest', '0011_auto_20180902_2007'),
]
operations = [
migrations.AlterUniqueTogether(
name='pollvote',
unique_together={('option', 'ip_address')},
),
]

View File

@ -11,4 +11,6 @@ urlpatterns = [
path('', views.index, name='index'),
path('<int:quest_id>', views.quest, name='quest'),
path('<int:quest_id>/<int:page_num>', views.quest, name='quest'),
path('<int:quest_id>/edit_quest', views.edit_quest, name='edit_quest'),
path('<int:quest_id>/<int:page_num>/edit_quest', views.edit_quest, name='edit_quest'),
]

View File

@ -2,16 +2,15 @@
"""
Quest and quest accessory views.
"""
from django.shortcuts import render
from django.shortcuts import render, redirect
from django.http import HttpResponse
from .models import Quest, DiceRoll, PollOption, PollVote
from .models import Quest, DiceRoll, PollOption, PollVote, PageTitle
def index(request):
"""
/quest page index. Possibly not needed.
"""
#return render(request, "Hello, world. You're at the quest index.", {})
return HttpResponse("Hello, world. You're at the quest index.")
@ -20,11 +19,27 @@ def quest(request, quest_id, page_num=1):
Arbituary quest page view.
"""
quest = Quest.objects.get(id=quest_id)
pages = PageTitle.objects.filter(quest=quest).order_by('page_num')
messages = quest.message_set.all()
posts = quest.post_set.all()
dice_rolls = DiceRoll.objects.filter(dicecall__post__quest__id=quest_id)
poll_options = PollOption.objects.filter(poll__post__quest__id=quest_id)
poll_votes = PollVote.objects.filter(option__poll__post__quest__id=quest_id)
dice_rolls = DiceRoll.objects.filter(dicecall__post__quest=quest)
poll_options = PollOption.objects.filter(poll__post__quest=quest)
poll_votes = PollVote.objects.filter(option__poll__post__quest=quest)
ip_address = request.META['REMOTE_ADDR']
context = locals()
return render(request, 'quest/quest.html', context)
def edit_quest(request, quest_id, page_num=1):
"""
Edit quest page. Only available to the QM.
"""
quest = Quest.objects.get(id=quest_id)
if quest.owner != request.user:
return redirect('quest:quest', quest_id=quest_id, page_num=page_num)
if request.method == 'POST':
pass
else:
pass
context = locals()
return render(request, 'quest/edit_quest.html', context)

View File

@ -5,7 +5,7 @@ Form(s) for the signup app.
from django import forms
from django.contrib.auth.forms import UserCreationForm
from users.models import User
from user.models import User
class SignupForm(UserCreationForm):
"""

View File

@ -32,7 +32,7 @@ INSTALLED_APPS = [
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'users.apps.UsersConfig',
'user.apps.UserConfig',
'homepage.apps.HomepageConfig',
'create_quest.apps.CreateQuestConfig',
'quest.apps.QuestConfig',
@ -107,7 +107,7 @@ AUTH_PASSWORD_VALIDATORS = [
}
},
{
'NAME': 'users.validators.MaximumLengthValidator',
'NAME': 'user.validators.MaximumLengthValidator',
'OPTIONS': {
'max_length': 1024,
}
@ -138,7 +138,7 @@ STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
AUTH_USER_MODEL = 'users.User'
AUTH_USER_MODEL = 'user.User'
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.Argon2PasswordHasher',

3
todo
View File

@ -31,6 +31,5 @@ Adjust quote preview postioning
Port from old code:
Edit post
Edit quest
Pages
Images
User page

BIN
user/.views.py.swo Normal file

Binary file not shown.

5
user/apps.py Normal file
View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class UserConfig(AppConfig):
name = 'user'

View File

@ -1,9 +1,10 @@
# Generated by Django 2.0.7 on 2018-08-10 20:30
# Generated by Django 2.1.1 on 2018-09-05 17:44
import django.contrib.auth.models
import django.contrib.auth.validators
import django.core.validators
from django.db import migrations, models
import django.utils.timezone
import user.validators
class Migration(migrations.Migration):
@ -25,7 +26,7 @@ class Migration(migrations.Migration):
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 20 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=20, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Must be between 3 and 20 characters. Letters and digits only.', max_length=20, unique=True, validators=[user.validators.CharValidator('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 'Username must only contain alphanumeric characters.'), django.core.validators.MinLengthValidator(3, 'Username must contain more than 3 characters.'), django.core.validators.MaxLengthValidator(20, 'Username must contain less than 20 characters.')], verbose_name='username')),
('email', models.EmailField(max_length=254, verbose_name='email address')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),

16
user/views.py Normal file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
"""
/user app views.
"""
from django.http import HttpResponse
from django.shortcuts import redirect, render
from django.core.exceptions import ObjectDoesNotExist
from .models import User
from quest.models import Quest
def index(request):
"""
The user index page.
"""
return HttpResponse("Hello, world. You're at the user index.")

View File

@ -1,5 +0,0 @@
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'

View File

@ -1,20 +0,0 @@
# Generated by Django 2.1 on 2018-08-12 20:09
import django.core.validators
from django.db import migrations, models
import users.validators
class Migration(migrations.Migration):
dependencies = [
('users', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='user',
name='username',
field=models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Must be between 3 and 20 characters. Letters and digits only.', max_length=20, unique=True, validators=[users.validators.CharValidator('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 'Username must only contain alphanumeric characters.'), django.core.validators.MinLengthValidator(3, 'Username must contain more than 3 characters.'), django.core.validators.MaxLengthValidator(20, 'Username must contain less than 20 characters.')], verbose_name='username'),
),
]

View File

@ -1,3 +0,0 @@
from django.shortcuts import render
# Create your views here.