Commit 2b6bc762e81b07833bd963bb6f45fddf6873c8b0

Authored by Andrew Buss
1 parent 4401f6495c
Exists in master

expanded registration

Showing 6 changed files with 178 additions and 46 deletions Inline Diff

flashcards/admin.py View file @ 2b6bc76
from django.contrib import admin 1 1 from django.contrib import admin
from flashcards.models import Flashcard, UserFlashcard, Section, FlashcardMask, \ 2 2 from flashcards.models import Flashcard, UserFlashcard, Section, FlashcardMask, \
UserFlashcardReview 3 3 UserFlashcardReview, LecturePeriod, User
4 from simple_email_confirmation import EmailAddress
4 5
admin.site.register([ 5 6 admin.site.register([
7 User,
Flashcard, 6 8 Flashcard,
FlashcardMask, 7 9 FlashcardMask,
UserFlashcard, 8 10 UserFlashcard,
UserFlashcardReview, 9 11 UserFlashcardReview,
Section 10 12 Section,
13 LecturePeriod
]) 11 14 ])
flashcards/api.py View file @ 2b6bc76
1 from django.contrib.auth import login, authenticate
from django.core.mail import send_mail 1 2 from django.core.mail import send_mail
from rest_framework.views import APIView 2 3 from rest_framework.views import APIView
from rest_framework.response import Response 3 4 from rest_framework.response import Response
from rest_framework import status 4 5 from rest_framework import status
from rest_framework.exceptions import ValidationError 5 6 from rest_framework.exceptions import ValidationError
from flashcards.serializers import * 6 7 from flashcards.serializers import *
7 8
8 9
class UserDetail(APIView): 9 10 class UserDetail(APIView):
def patch(self, request, format=None): 10 11 def patch(self, request, format=None):
""" 11 12 """
Updates a user's password after they enter a valid old password. 12 13 Updates a user's password after they enter a valid old password.
TODO: email verification 13 14 TODO: email verification
""" 14 15 """
15 16
if 'old_password' not in request.data: 16 17 if 'old_password' not in request.data:
raise ValidationError('Old password is required') 17 18 raise ValidationError('Old password is required')
if 'new_password' not in request.data: 18 19 if 'new_password' not in request.data:
raise ValidationError('New password is required') 19 20 raise ValidationError('New password is required')
if not request.data['new_password']: 20 21 if not request.data['new_password']:
raise ValidationError('Password cannot be blank') 21 22 raise ValidationError('Password cannot be blank')
22 23
currentuser = request.user 23 24 currentuser = request.user
24 25
if not currentuser.check_password(request.data['old_password']): 25 26 if not currentuser.check_password(request.data['old_password']):
raise ValidationError('Invalid old password') 26 27 raise ValidationError('Invalid old password')
27 28
currentuser.set_password(request.data['new_password']) 28 29 currentuser.set_password(request.data['new_password'])
currentuser.save() 29 30 currentuser.save()
30 31
return Response(status=status.HTTP_204_NO_CONTENT) 31 32 return Response(status=status.HTTP_204_NO_CONTENT)
32 33
def get(self, request, format=None): 33 34 def get(self, request, format=None):
serializer = UserSerializer(request.user) 34 35 serializer = UserSerializer(request.user)
return Response(serializer.data) 35 36 return Response(serializer.data)
36 37
def post(self, request, format=None): 37 38 def post(self, request, format=None):
if 'email' not in request.data: 38 39 if 'email' not in request.data:
raise ValidationError('Email is required') 39 40 raise ValidationError('Email is required')
if 'password' not in request.data: 40 41 if 'password' not in request.data:
raise ValidationError('Password is required') 41 42 raise ValidationError('Password is required')
42 43
email = request.data['email'] 43 44 email = request.data['email']
user = User.objects.create_user(email) 44 45 user = User.objects.create_user(email, email=email)
45 46 user.confirm_email(user.confirmation_key)
body = ''' 46 47 body = '''
Visit the following link to confirm your email address: 47 48 Visit the following link to confirm your email address:
http://flashy.cards/app/verify_email/%s 48 49 http://flashy.cards/app/verify_email/%s
49 50
flashcards/migrations/0001_initial.py View file @ 2b6bc76
File was created 1 # -*- coding: utf-8 -*-
2 from __future__ import unicode_literals
3
4 from django.db import models, migrations
5 import django.contrib.auth.models
6 import django.utils.timezone
7 from django.conf import settings
8 import django.core.validators
9 import simple_email_confirmation.models
10
11
12 class Migration(migrations.Migration):
13
14 dependencies = [
15 ('auth', '0007_customuser_extensionuser'),
16 ]
17
18 operations = [
19 migrations.CreateModel(
20 name='User',
21 fields=[
22 ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
23 ('password', models.CharField(max_length=128, verbose_name='password')),
24 ('last_login', models.DateTimeField(null=True, verbose_name='last login', blank=True)),
25 ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
26 ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, max_length=30, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.', 'invalid')], help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', unique=True, verbose_name='username')),
27 ('first_name', models.CharField(max_length=30, verbose_name='first name', blank=True)),
28 ('last_name', models.CharField(max_length=30, verbose_name='last name', blank=True)),
29 ('email', models.EmailField(max_length=254, verbose_name='email address', blank=True)),
30 ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
31 ('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')),
32 ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
33 ('groups', models.ManyToManyField(related_query_name='user', related_name='user_set', to='auth.Group', blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', verbose_name='groups')),
34 ],
35 options={
36 'abstract': False,
37 'verbose_name': 'user',
38 'verbose_name_plural': 'users',
39 },
40 bases=(models.Model, simple_email_confirmation.models.SimpleEmailConfirmationUserMixin),
41 managers=[
42 (b'objects', django.contrib.auth.models.UserManager()),
43 ],
44 ),
45 migrations.CreateModel(
46 name='Flashcard',
47 fields=[
48 ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
49 ('text', models.CharField(help_text=b'The text on the card', max_length=255)),
50 ('pushed', models.DateTimeField(help_text=b'When the card was first pushed', auto_now_add=True)),
51 ('material_date', models.DateTimeField(help_text=b'The date with which the card is associated')),
52 ('is_hidden', models.BooleanField(default=False)),
53 ('hide_reason', models.CharField(help_text=b'Reason for hiding this card', max_length=255, blank=True)),
54 ('author', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
55 ],
56 options={
57 'ordering': ['-pushed'],
58 },
59 ),
60 migrations.CreateModel(
61 name='FlashcardMask',
62 fields=[
63 ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
64 ('ranges', models.CharField(max_length=255)),
65 ],
66 ),
67 migrations.CreateModel(
68 name='LecturePeriod',
69 fields=[
70 ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
71 ('week_day', models.IntegerField(help_text=b'0-indexed day of week, starting at Monday')),
72 ('start_time', models.TimeField()),
73 ('end_time', models.TimeField()),
74 ],
75 ),
76 migrations.CreateModel(
77 name='Section',
78 fields=[
79 ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
80 ('department', models.CharField(max_length=50)),
81 ('course_num', models.CharField(max_length=6)),
82 ('course_title', models.CharField(max_length=50)),
83 ('instructor', models.CharField(max_length=50)),
84 ('quarter', models.CharField(max_length=4)),
85 ],
86 options={
87 'ordering': ['-quarter'],
88 },
89 ),
90 migrations.CreateModel(
91 name='UserFlashcard',
92 fields=[
93 ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
94 ('pulled', models.DateTimeField(help_text=b'When the user pulled the card', null=True, blank=True)),
95 ('unpulled', models.DateTimeField(help_text=b'When the user unpulled this card', null=True, blank=True)),
96 ('flashcard', models.ForeignKey(to='flashcards.Flashcard')),
97 ('mask', models.ForeignKey(help_text=b"A mask which overrides the card's mask", to='flashcards.FlashcardMask')),
98 ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)),
99 ],
100 options={
101 'ordering': ['-pulled'],
102 },
103 ),
104 migrations.CreateModel(
105 name='UserFlashcardReview',
106 fields=[
107 ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
108 ('when', models.DateTimeField()),
109 ('blanked_word', models.CharField(help_text=b'The character range which was blanked', max_length=8, blank=True)),
110 ('response', models.CharField(help_text=b"The user's response", max_length=255, null=True, blank=True)),
111 ('correct', models.NullBooleanField(help_text=b"The user's self-evaluation of their response")),
112 ('user_flashcard', models.ForeignKey(to='flashcards.UserFlashcard')),
113 ],
114 ),
115 migrations.AlterUniqueTogether(
116 name='section',
117 unique_together=set([('department', 'course_num', 'quarter', 'instructor')]),
118 ),
119 migrations.AddField(
120 model_name='lectureperiod',
121 name='section',
122 field=models.ForeignKey(to='flashcards.Section'),
123 ),
124 migrations.AddField(
125 model_name='flashcard',
126 name='mask',
127 field=models.ForeignKey(blank=True, to='flashcards.FlashcardMask', help_text=b'The default mask for this card', null=True),
128 ),
129 migrations.AddField(
130 model_name='flashcard',
131 name='previous',
132 field=models.ForeignKey(blank=True, to='flashcards.Flashcard', help_text=b'The previous version of this card, if one exists', null=True),
133 ),
134 migrations.AddField(
135 model_name='flashcard',
136 name='section',
137 field=models.ForeignKey(help_text=b'The section with which the card is associated', to='flashcards.Section'),
138 ),
139 migrations.AddField(
140 model_name='user',
141 name='sections',
142 field=models.ManyToManyField(to='flashcards.Section'),
143 ),
144 migrations.AddField(
145 model_name='user',
146 name='user_permissions',
147 field=models.ManyToManyField(related_query_name='user', related_name='user_set', to='auth.Permission', blank=True, help_text='Specific permissions for this user.', verbose_name='user permissions'),
148 ),
149 migrations.AlterUniqueTogether(
150 name='userflashcard',
151 unique_together=set([('user', 'flashcard')]),
152 ),
flashcards/models.py View file @ 2b6bc76
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin 1 1 from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin, AbstractUser
from django.contrib.auth.tests.custom_user import CustomUser 2 2 from django.contrib.auth.tests.custom_user import CustomUser
from django.db.models import * 3 3 from django.db.models import *
from simple_email_confirmation import SimpleEmailConfirmationUserMixin 4 4 from simple_email_confirmation import SimpleEmailConfirmationUserMixin
5 5
6 # Hack to fix AbstractUser before subclassing it
7 AbstractUser._meta.get_field('email')._unique = True
6 8
class UserManager(BaseUserManager): 7 9 class User(AbstractUser, SimpleEmailConfirmationUserMixin, ):
def create_user(self, email, password=None): 8
""" 9
Creates and saves a User with the given email, date of 10
birth and password. 11
""" 12
if not email: 13
raise ValueError('Users must have an email address') 14
15
user = self.model(email=self.normalize_email(email)) 16
17
user.set_password(password) 18
user.save(using=self._db) 19
return user 20
21
def create_superuser(self, email, password): 22
""" 23
Creates and saves a superuser with the given email and password. 24
""" 25
user = self.create_user(email, password=password) 26
user.is_staff = True 27
user.save(using=self._db) 28
return user 29
30
31
class User(AbstractBaseUser, SimpleEmailConfirmationUserMixin, ): 32
USERNAME_FIELD = 'email' 33 10 USERNAME_FIELD = 'email'
REQUIRED_FIELDS = [] 34 11 REQUIRED_FIELDS = []
35
objects = UserManager() 36
is_staff = BooleanField(default=False) 37
38
email = EmailField( 39
verbose_name='email address', 40
max_length=255, 41
unique=True, 42
) 43
date_joined = DateTimeField(auto_now_add=True) 44
sections = ManyToManyField('Section') 45 12 sections = ManyToManyField('Section')
46 13
47 14
class UserFlashcard(Model): 48 15 class UserFlashcard(Model):
""" 49 16 """
Represents the relationship between a user and a flashcard by: 50 17 Represents the relationship between a user and a flashcard by:
1. A user has a flashcard in their deck 51 18 1. A user has a flashcard in their deck
2. A user used to have a flashcard in their deck 52 19 2. A user used to have a flashcard in their deck
3. A user has a flashcard hidden from them 53 20 3. A user has a flashcard hidden from them
""" 54 21 """
user = ForeignKey(User) 55 22 user = ForeignKey('User')
mask = ForeignKey('FlashcardMask', help_text="A mask which overrides the card's mask") 56 23 mask = ForeignKey('FlashcardMask', help_text="A mask which overrides the card's mask")
pulled = DateTimeField(blank=True, null=True, help_text="When the user pulled the card") 57 24 pulled = DateTimeField(blank=True, null=True, help_text="When the user pulled the card")
flashcard = ForeignKey('Flashcard') 58 25 flashcard = ForeignKey('Flashcard')
unpulled = DateTimeField(blank=True, null=True, help_text="When the user unpulled this card") 59 26 unpulled = DateTimeField(blank=True, null=True, help_text="When the user unpulled this card")
60 27
class Meta: 61 28 class Meta:
# There can be at most one UserFlashcard for each User and Flashcard 62 29 # There can be at most one UserFlashcard for each User and Flashcard
unique_together = (('user', 'flashcard'),) 63 30 unique_together = (('user', 'flashcard'),)
index_together = ["user", "flashcard"] 64 31 index_together = ["user", "flashcard"]
# By default, order by most recently pulled 65 32 # By default, order by most recently pulled
ordering = ['-pulled'] 66 33 ordering = ['-pulled']
67 34
def is_hidden(self): 68 35 def is_hidden(self):
""" 69 36 """
A card is hidden only if a user has not ever added it to their deck. 70 37 A card is hidden only if a user has not ever added it to their deck.
:return: Whether the flashcard is hidden from the user 71 38 :return: Whether the flashcard is hidden from the user
""" 72 39 """
return not self.pulled 73 40 return not self.pulled
74 41
def is_in_deck(self): 75 42 def is_in_deck(self):
""" 76 43 """
:return:Whether the flashcard is in the user's deck 77 44 :return:Whether the flashcard is in the user's deck
""" 78 45 """
return self.pulled and not self.unpulled 79 46 return self.pulled and not self.unpulled
80 47
81 48
class FlashcardMask(Model): 82 49 class FlashcardMask(Model):
""" 83 50 """
A serialized list of character ranges that can be blanked out during review. 84 51 A serialized list of character ranges that can be blanked out during review.
This is encoded as '13-145,150-195' 85 52 This is encoded as '13-145,150-195'
""" 86 53 """
ranges = CharField(max_length=255) 87 54 ranges = CharField(max_length=255)
88 55
89 56
class Flashcard(Model): 90 57 class Flashcard(Model):
text = CharField(max_length=255, help_text='The text on the card') 91 58 text = CharField(max_length=255, help_text='The text on the card')
section = ForeignKey('Section', help_text='The section with which the card is associated') 92 59 section = ForeignKey('Section', help_text='The section with which the card is associated')
pushed = DateTimeField(auto_now_add=True, help_text="When the card was first pushed") 93 60 pushed = DateTimeField(auto_now_add=True, help_text="When the card was first pushed")
material_date = DateTimeField(help_text="The date with which the card is associated") 94 61 material_date = DateTimeField(help_text="The date with which the card is associated")
previous = ForeignKey('Flashcard', null=True, blank=True, 95 62 previous = ForeignKey('Flashcard', null=True, blank=True,
help_text="The previous version of this card, if one exists") 96 63 help_text="The previous version of this card, if one exists")
author = ForeignKey(User) 97 64 author = ForeignKey(User)
is_hidden = BooleanField(default=False) 98 65 is_hidden = BooleanField(default=False)
hide_reason = CharField(blank=True, max_length=255, help_text="Reason for hiding this card") 99 66 hide_reason = CharField(blank=True, max_length=255, help_text="Reason for hiding this card")
mask = ForeignKey(FlashcardMask, blank=True, null=True, help_text="The default mask for this card") 100 67 mask = ForeignKey(FlashcardMask, blank=True, null=True, help_text="The default mask for this card")
101 68
class Meta: 102 69 class Meta:
# By default, order by most recently pushed 103 70 # By default, order by most recently pushed
ordering = ['-pushed'] 104 71 ordering = ['-pushed']
105 72
def is_hidden_from(self, user): 106 73 def is_hidden_from(self, user):
""" 107 74 """
A card can be hidden globally, but if a user has the card in their deck, 108 75 A card can be hidden globally, but if a user has the card in their deck,
this visibility overrides a global hide. 109 76 this visibility overrides a global hide.
:param user: 110 77 :param user:
:return: Whether the card is hidden from the user. 111 78 :return: Whether the card is hidden from the user.
""" 112 79 """
result = user.userflashcard_set.filter(flashcard=self) 113 80 result = user.userflashcard_set.filter(flashcard=self)
if not result.exists(): return self.is_hidden 114 81 if not result.exists(): return self.is_hidden
return result[0].is_hidden() 115 82 return result[0].is_hidden()
116 83
117 84
@classmethod 118 85 @classmethod
def cards_visible_to(cls, user): 119 86 def cards_visible_to(cls, user):
""" 120 87 """
:param user: 121 88 :param user:
:return: A queryset with all cards that should be visible to a user. 122 89 :return: A queryset with all cards that should be visible to a user.
""" 123 90 """
return cls.objects.filter(hidden=False).exclude(userflashcard=user, userflashcard__pulled=None) 124 91 return cls.objects.filter(hidden=False).exclude(userflashcard=user, userflashcard__pulled=None)
125 92
126 93
class UserFlashcardReview(Model): 127 94 class UserFlashcardReview(Model):
""" 128 95 """
An event of a user reviewing a flashcard. 129 96 An event of a user reviewing a flashcard.
""" 130 97 """
user_flashcard = ForeignKey(UserFlashcard) 131 98 user_flashcard = ForeignKey(UserFlashcard)
when = DateTimeField() 132 99 when = DateTimeField()
blanked_word = CharField(max_length=8, blank=True, help_text="The character range which was blanked") 133 100 blanked_word = CharField(max_length=8, blank=True, help_text="The character range which was blanked")
response = CharField(max_length=255, blank=True, null=True, help_text="The user's response") 134 101 response = CharField(max_length=255, blank=True, null=True, help_text="The user's response")
correct = NullBooleanField(help_text="The user's self-evaluation of their response") 135 102 correct = NullBooleanField(help_text="The user's self-evaluation of their response")
136 103
def status(self): 137 104 def status(self):
""" 138 105 """
There are three stages of a review object: 139 106 There are three stages of a review object:
1. the user has been shown the card 140 107 1. the user has been shown the card
2. the user has answered the card 141 108 2. the user has answered the card
3. the user has self-evaluated their response's correctness 142 109 3. the user has self-evaluated their response's correctness
143 110
:return: string (evaluated, answered, viewed) 144 111 :return: string (evaluated, answered, viewed)
""" 145 112 """
if self.correct is not None: return "evaluated" 146 113 if self.correct is not None: return "evaluated"
if self.response: return "answered" 147 114 if self.response: return "answered"
return "viewed" 148 115 return "viewed"
flashcards/serializers.py View file @ 2b6bc76
from flashcards.models import Section, LecturePeriod, User 1 1 from flashcards.models import Section, LecturePeriod, User
from rest_framework.fields import EmailField 2 2 from rest_framework.fields import EmailField
from rest_framework.relations import HyperlinkedRelatedField 3 3 from rest_framework.relations import HyperlinkedRelatedField
from rest_framework.serializers import HyperlinkedModelSerializer 4 4 from rest_framework.serializers import HyperlinkedModelSerializer
5 5
6 6
class SectionSerializer(HyperlinkedModelSerializer): 7 7 class SectionSerializer(HyperlinkedModelSerializer):
lectureperiod_set = HyperlinkedRelatedField(many=True, view_name='lectureperiod-detail', read_only=True) 8 8 lectureperiod_set = HyperlinkedRelatedField(many=True, view_name='lectureperiod-detail', read_only=True)
9 9
class Meta: 10 10 class Meta:
model = Section 11 11 model = Section
# exclude = ('members',) 12 12 # exclude = ('members',)
13 13
14 14
class LecturePeriodSerializer(HyperlinkedModelSerializer): 15 15 class LecturePeriodSerializer(HyperlinkedModelSerializer):
class Meta: 16 16 class Meta:
model = LecturePeriod 17 17 model = LecturePeriod
18 18
19 19
flashy/settings.py View file @ 2b6bc76
""" 1 1 """
Django settings for flashy project. 2 2 Django settings for flashy project.
3 3
Generated by 'django-admin startproject' using Django 1.8. 4 4 Generated by 'django-admin startproject' using Django 1.8.
5 5
For more information on this file, see 6 6 For more information on this file, see
https://docs.djangoproject.com/en/1.8/topics/settings/ 7 7 https://docs.djangoproject.com/en/1.8/topics/settings/
8 8
For the full list of settings and their values, see 9 9 For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.8/ref/settings/ 10 10 https://docs.djangoproject.com/en/1.8/ref/settings/
""" 11 11 """
12 12
# Build paths inside the project like this: os.path.join(BASE_DIR, ...) 13 13 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os 14 14 import os
15 15
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 16 16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
17 17
# SECURITY WARNING: don't run with debug turned on in production! 18 18 # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True 19 19 DEBUG = True
20 20
ALLOWED_HOSTS = [] 21 21 ALLOWED_HOSTS = []
22 22
AUTH_USER_MODEL = 'flashcards.User' 23 23 AUTH_USER_MODEL = 'flashcards.User'
# Application definition 24 24 # Application definition
25 25
INSTALLED_APPS = ( 26 26 INSTALLED_APPS = (
'simple_email_confirmation', 27 27 'simple_email_confirmation',
'flashcards', 28 28 'flashcards',
'django.contrib.admin', 29 29 'django.contrib.admin',
'django.contrib.admindocs', 30 30 'django.contrib.admindocs',
'django.contrib.auth', 31 31 'django.contrib.auth',
'django.contrib.contenttypes', 32 32 'django.contrib.contenttypes',
'django.contrib.sessions', 33 33 'django.contrib.sessions',
'django.contrib.messages', 34 34 'django.contrib.messages',
'django.contrib.staticfiles', 35 35 'django.contrib.staticfiles',
'django_ses', 36 36 'django_ses',
'rest_framework', 37 37 'rest_framework',
38 38
39 39
) 40 40 )
41 41
REST_FRAMEWORK = { 42 42 REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination', 43 43 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
'PAGE_SIZE': 20 44 44 'PAGE_SIZE': 20
} 45 45 }
46 46
MIDDLEWARE_CLASSES = ( 47 47 MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware', 48 48 'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware', 49 49 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware', 50 50 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', 51 51 'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 52 52 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', 53 53 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware', 54 54 'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware', 55 55 'django.middleware.security.SecurityMiddleware',
) 56 56 )
57 57
ROOT_URLCONF = 'flashy.urls' 58 58 ROOT_URLCONF = 'flashy.urls'
59 59 # Authentication backends
60 AUTHENTICATION_BACKENDS = (
61 'django.contrib.auth.backends.ModelBackend',
62 )
TEMPLATES = [ 60 63 TEMPLATES = [
{ 61 64 {
'BACKEND': 'django.template.backends.django.DjangoTemplates', 62 65 'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['templates/'], 63 66 'DIRS': ['templates/'],
'APP_DIRS': True, 64 67 'APP_DIRS': True,
'OPTIONS': { 65 68 'OPTIONS': {
'context_processors': [ 66 69 'context_processors': [
'django.template.context_processors.debug', 67 70 'django.template.context_processors.debug',
'django.template.context_processors.request', 68 71 'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth', 69 72 'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages', 70 73 'django.contrib.messages.context_processors.messages',
], 71 74 ],
}, 72 75 },
}, 73 76 },
] 74 77 ]
75 78
WSGI_APPLICATION = 'flashy.wsgi.application' 76 79 WSGI_APPLICATION = 'flashy.wsgi.application'
77 80
78 81
# Database 79 82 # Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases 80 83 # https://docs.djangoproject.com/en/1.8/ref/settings/#databases
81 84
DATABASES = { 82 85 DATABASES = {
'default': { 83 86 'default': {
'ENGINE': 'django.db.backends.sqlite3', 84 87 'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 85 88 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
} 86 89 }
} 87 90 }
88 91