├── .gitignore ├── README.md ├── accounts ├── __init__.py ├── admin.py ├── apps.py ├── managers.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── serializers.py ├── tests.py ├── urls.py └── views.py ├── application ├── __init__.py ├── admin.py ├── apps.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ └── prepare_random_quiz.py ├── migrations │ ├── 0001_initial.py │ └── __init__.py ├── models.py ├── serializers.py ├── tests.py ├── urls.py └── views.py ├── manage.py ├── quiz ├── __init__.py ├── settings.py └── urls.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/django,python,visualstudiocode 2 | 3 | ### Django ### 4 | *.log 5 | *.pot 6 | *.pyc 7 | __pycache__/ 8 | local_settings.py 9 | db.sqlite3 10 | media 11 | 12 | # If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/ 13 | # in your Git repository. Update and uncomment the following line accordingly. 14 | # /staticfiles/ 15 | 16 | ### Python ### 17 | # Byte-compiled / optimized / DLL files 18 | *.py[cod] 19 | *$py.class 20 | 21 | # C extensions 22 | *.so 23 | 24 | # Distribution / packaging 25 | .Python 26 | build/ 27 | develop-eggs/ 28 | dist/ 29 | downloads/ 30 | eggs/ 31 | .eggs/ 32 | lib/ 33 | lib64/ 34 | parts/ 35 | sdist/ 36 | var/ 37 | wheels/ 38 | *.egg-info/ 39 | .installed.cfg 40 | *.egg 41 | 42 | # PyInstaller 43 | # Usually these files are written by a python script from a template 44 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 45 | *.manifest 46 | *.spec 47 | 48 | # Installer logs 49 | pip-log.txt 50 | pip-delete-this-directory.txt 51 | 52 | # Unit test / coverage reports 53 | htmlcov/ 54 | .tox/ 55 | .coverage 56 | .coverage.* 57 | .cache 58 | .pytest_cache/ 59 | nosetests.xml 60 | coverage.xml 61 | *.cover 62 | .hypothesis/ 63 | 64 | # Translations 65 | *.mo 66 | 67 | # Flask stuff: 68 | instance/ 69 | .webassets-cache 70 | 71 | # Scrapy stuff: 72 | .scrapy 73 | 74 | # Sphinx documentation 75 | docs/_build/ 76 | 77 | # PyBuilder 78 | target/ 79 | 80 | # Jupyter Notebook 81 | .ipynb_checkpoints 82 | 83 | # pyenv 84 | .python-version 85 | 86 | # celery beat schedule file 87 | celerybeat-schedule.* 88 | 89 | # SageMath parsed files 90 | *.sage.py 91 | 92 | # Environments 93 | .env 94 | .venv 95 | env/ 96 | venv/ 97 | ENV/ 98 | env.bak/ 99 | venv.bak/ 100 | 101 | # Spyder project settings 102 | .spyderproject 103 | .spyproject 104 | 105 | # Rope project settings 106 | .ropeproject 107 | 108 | # mkdocs documentation 109 | /site 110 | 111 | # mypy 112 | .mypy_cache/ 113 | 114 | ### VisualStudioCode ### 115 | .vscode/* 116 | !.vscode/settings.json 117 | !.vscode/tasks.json 118 | !.vscode/launch.json 119 | !.vscode/extensions.json 120 | .history 121 | 122 | 123 | # End of https://www.gitignore.io/api/django,python,visualstudiocode 124 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Django REST Framework Quiz 2 | 3 | A simple quiz application using Django-REST Framework 4 | 5 | ## Installation 6 | 7 | Clone the repository using https/ssh 8 | ```git clone https://github.com/arunshaji95/django-rest-quiz.git``` 9 | 10 | Create a virtual environment 11 | ``` 12 | virtualenv venv -p python3 13 | source venv/bin/activate 14 | ``` 15 | 16 | Install the required packages using 17 | ``` 18 | pip install -r requirements.txt 19 | ``` 20 | 21 | Migrate 22 | ```python manage.py migrate``` 23 | 24 | Create a superuser 25 | ```python manage.py createsuperuser``` 26 | 27 | Run the development server 28 | ```python manage.py runserver``` 29 | 30 | Visit http://localhost:8000/admin. Login with superuser credentials. Add some categories, questions and choices. Create a quiz using the command - 31 | ```python manage.py prepare_random_quiz``` 32 | 33 | -------------------------------------------------------------------------------- /accounts/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arunshaji95/django-rest-quiz/61a2a06b36cda7f15b6a6ea9e613e71d06e0f5d6/accounts/__init__.py -------------------------------------------------------------------------------- /accounts/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.contrib.auth import get_user_model 3 | 4 | 5 | User = get_user_model() 6 | 7 | admin.site.register(User) 8 | -------------------------------------------------------------------------------- /accounts/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AccountsConfig(AppConfig): 5 | name = 'accounts' 6 | -------------------------------------------------------------------------------- /accounts/managers.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.base_user import BaseUserManager 2 | 3 | 4 | class UserManager(BaseUserManager): 5 | use_in_migrations = True 6 | 7 | def _create_user(self, email, password, **extra_fields): 8 | """ 9 | Creates a new user and saves name and password along with extra fields. 10 | """ 11 | if not email: 12 | raise ValueError('Email is required') 13 | 14 | email = self.normalize_email(email) 15 | user = self.model(email=email, **extra_fields) 16 | user.set_password(password) 17 | user.save(using=self._db) 18 | return user 19 | 20 | def create_user(self, email, password=None, **extra_fields): 21 | extra_fields.setdefault('is_superuser', False) 22 | return self._create_user(email, password, **extra_fields) 23 | 24 | def create_superuser(self, email, password, **extra_fields): 25 | extra_fields.setdefault('is_superuser', True) 26 | extra_fields.setdefault('is_staff', True) 27 | if extra_fields.get('is_superuser') is not True: 28 | raise ValueError('Superuser must have is_superuser=True.') 29 | return self._create_user(email, password, **extra_fields) 30 | -------------------------------------------------------------------------------- /accounts/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.4 on 2018-05-16 11:07 2 | 3 | import accounts.managers 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | initial = True 10 | 11 | dependencies = [ 12 | ('auth', '0009_alter_user_last_name_max_length'), 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='User', 18 | fields=[ 19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 | ('password', models.CharField(max_length=128, verbose_name='password')), 21 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), 22 | ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), 23 | ('email', models.EmailField(max_length=254, unique=True, verbose_name='email address')), 24 | ('first_name', models.CharField(max_length=40, verbose_name='first_name')), 25 | ('last_name', models.CharField(max_length=40, verbose_name='last name')), 26 | ('date_joined', models.DateTimeField(auto_now_add=True, verbose_name='date joined')), 27 | ('is_active', models.BooleanField(default=True, verbose_name='active')), 28 | ('is_staff', models.BooleanField(default=False, verbose_name='staff_status')), 29 | ('profile_picture', models.ImageField(blank=True, null=True, upload_to='')), 30 | ('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')), 31 | ('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')), 32 | ], 33 | options={ 34 | 'verbose_name': 'user', 35 | 'verbose_name_plural': 'users', 36 | }, 37 | managers=[ 38 | ('objects', accounts.managers.UserManager()), 39 | ], 40 | ), 41 | ] 42 | -------------------------------------------------------------------------------- /accounts/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arunshaji95/django-rest-quiz/61a2a06b36cda7f15b6a6ea9e613e71d06e0f5d6/accounts/migrations/__init__.py -------------------------------------------------------------------------------- /accounts/models.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.base_user import AbstractBaseUser 2 | from django.contrib.auth.models import PermissionsMixin 3 | from django.db import models 4 | from django.utils.translation import ugettext_lazy as _ 5 | 6 | from .managers import UserManager 7 | 8 | 9 | class User(AbstractBaseUser, PermissionsMixin): 10 | email = models.EmailField(_('email address'), unique=True) 11 | first_name = models.CharField(_('first_name'), max_length=40) 12 | last_name = models.CharField(_('last name'), max_length=40) 13 | date_joined = models.DateTimeField(_('date joined'), auto_now_add=True) 14 | is_active = models.BooleanField(_('active'), default=True) 15 | is_staff = models.BooleanField(_('staff_status'), default=False) 16 | profile_picture = models.ImageField(null=True, blank=True) 17 | 18 | objects = UserManager() 19 | 20 | USERNAME_FIELD = 'email' 21 | REQUIRED_FIELDS = [] 22 | 23 | class Meta: 24 | verbose_name = _('user') 25 | verbose_name_plural = _('users') 26 | 27 | def get_short_name(self): 28 | return self.first_name 29 | 30 | def get_full_name(self): 31 | return '{} {}'.format(self.first_name, self.last_name).strip() 32 | -------------------------------------------------------------------------------- /accounts/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | from django.contrib.auth import get_user_model 3 | 4 | User = get_user_model() 5 | 6 | class UserSerializer(serializers.ModelSerializer): 7 | class Meta: 8 | model = User 9 | fields = ('email', 'password', 'first_name', 'last_name', 'profile_picture') 10 | extra_kwargs = { 11 | 'password': {'write_only': True} 12 | } 13 | -------------------------------------------------------------------------------- /accounts/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /accounts/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | urlpatterns = [ 6 | path('register/', views.RegistrationAPI.as_view()), 7 | ] 8 | -------------------------------------------------------------------------------- /accounts/views.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth import get_user_model 2 | from rest_framework import generics 3 | from rest_framework.permissions import AllowAny 4 | 5 | from .serializers import UserSerializer 6 | 7 | 8 | User = get_user_model() 9 | 10 | 11 | class RegistrationAPI(generics.CreateAPIView): 12 | serializer_class = UserSerializer 13 | permission_classes = (AllowAny, ) 14 | queryset = User.objects.all() 15 | -------------------------------------------------------------------------------- /application/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arunshaji95/django-rest-quiz/61a2a06b36cda7f15b6a6ea9e613e71d06e0f5d6/application/__init__.py -------------------------------------------------------------------------------- /application/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Answer, Category, Question, Quiz 4 | 5 | admin.site.register(Question) 6 | admin.site.register(Answer) 7 | admin.site.register(Quiz) 8 | admin.site.register(Category) 9 | -------------------------------------------------------------------------------- /application/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ApplicationConfig(AppConfig): 5 | name = 'application' 6 | -------------------------------------------------------------------------------- /application/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arunshaji95/django-rest-quiz/61a2a06b36cda7f15b6a6ea9e613e71d06e0f5d6/application/management/__init__.py -------------------------------------------------------------------------------- /application/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arunshaji95/django-rest-quiz/61a2a06b36cda7f15b6a6ea9e613e71d06e0f5d6/application/management/commands/__init__.py -------------------------------------------------------------------------------- /application/management/commands/prepare_random_quiz.py: -------------------------------------------------------------------------------- 1 | from django.core.management.base import BaseCommand, CommandError 2 | 3 | from application.models import Category, Question, Quiz 4 | 5 | 6 | class Command(BaseCommand): 7 | help = 'Creates random quizes based on available categorys' 8 | 9 | def handle(self, *args, **options): 10 | if not Category.objects.count(): 11 | raise CommandError('No categorys are available') 12 | Quiz.objects.all().delete() 13 | for category in Category.objects.all(): 14 | quiz = Quiz(quiz_name='{} quiz'.format(category.category_name), 15 | category=category) 16 | quiz.save() 17 | questions = list(Question.objects.filter(category=category)) 18 | quiz.question.add(*questions) 19 | quiz.save() 20 | self.stdout.write(self.style.SUCCESS('Quiz Created')) 21 | -------------------------------------------------------------------------------- /application/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.0.4 on 2018-05-16 11:07 2 | 3 | from django.db import migrations, models 4 | import django.db.models.deletion 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | initial = True 10 | 11 | dependencies = [ 12 | ] 13 | 14 | operations = [ 15 | migrations.CreateModel( 16 | name='Answer', 17 | fields=[ 18 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 19 | ('answer_text', models.CharField(max_length=150)), 20 | ], 21 | ), 22 | migrations.CreateModel( 23 | name='Category', 24 | fields=[ 25 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 26 | ('category_name', models.CharField(max_length=150)), 27 | ], 28 | ), 29 | migrations.CreateModel( 30 | name='Question', 31 | fields=[ 32 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 33 | ('question_text', models.CharField(max_length=150)), 34 | ('answer', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='correct_answer', to='application.Answer')), 35 | ('category', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='application.Category')), 36 | ('choices', models.ManyToManyField(related_name='choices', to='application.Answer')), 37 | ], 38 | ), 39 | migrations.CreateModel( 40 | name='Quiz', 41 | fields=[ 42 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 43 | ('quiz_name', models.CharField(max_length=150)), 44 | ('category', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='application.Category')), 45 | ('question', models.ManyToManyField(blank=True, to='application.Question')), 46 | ], 47 | options={ 48 | 'verbose_name_plural': 'Quizes', 49 | }, 50 | ), 51 | ] 52 | -------------------------------------------------------------------------------- /application/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arunshaji95/django-rest-quiz/61a2a06b36cda7f15b6a6ea9e613e71d06e0f5d6/application/migrations/__init__.py -------------------------------------------------------------------------------- /application/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth import get_user_model 3 | 4 | 5 | User = get_user_model() 6 | 7 | 8 | class Category(models.Model): 9 | category_name = models.CharField(max_length=150) 10 | 11 | def __str__(self): 12 | return self.category_name 13 | 14 | class Answer(models.Model): 15 | answer_text = models.CharField(max_length=150) 16 | 17 | def __str__(self): 18 | return self.answer_text 19 | 20 | 21 | class Question(models.Model): 22 | category = models.ForeignKey(Category, on_delete=models.DO_NOTHING) 23 | question_text = models.CharField(max_length=150) 24 | answer = models.OneToOneField('Answer', on_delete=models.CASCADE, 25 | related_name='correct_answer', null=True, blank=True) 26 | choices = models.ManyToManyField(Answer, related_name='choices') 27 | 28 | def __str__(self): 29 | return self.question_text 30 | 31 | 32 | class Quiz(models.Model): 33 | category = models.OneToOneField(Category, on_delete=models.CASCADE) 34 | quiz_name = models.CharField(max_length=150) 35 | question = models.ManyToManyField(Question, blank=True) 36 | 37 | class Meta: 38 | verbose_name_plural = 'Quizes' 39 | 40 | def __str__(self): 41 | return self.quiz_name 42 | -------------------------------------------------------------------------------- /application/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | from .models import Answer, Category, Question 4 | 5 | #pylint: disable=R0903, C1001, W0232 6 | 7 | class CategorySerializer(serializers.ModelSerializer): 8 | class Meta: 9 | model = Category 10 | fields = '__all__' 11 | read_only_fields = ('__all__',) 12 | 13 | class ChoiceSerializer(serializers.ModelSerializer): 14 | class Meta: 15 | model = Answer 16 | fields = ('id', 'answer_text') 17 | 18 | 19 | class QuestionSerializer(serializers.ModelSerializer): 20 | choices = serializers.SerializerMethodField() 21 | 22 | def get_choices(self, obj): 23 | ordered_queryset = Answer.objects.filter(choices__id=obj.id).order_by('?') 24 | return ChoiceSerializer(ordered_queryset, many=True, context=self.context).data 25 | class Meta: 26 | model = Question 27 | fields = ('question_text', 'choices') 28 | -------------------------------------------------------------------------------- /application/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /application/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from . import views 3 | 4 | 5 | urlpatterns = [ 6 | path('list_category', views.ListCategories.as_view()), 7 | path('start/', views.StartQuiz.as_view()), 8 | path('start//', views.StartQuiz.as_view()), 9 | ] 10 | -------------------------------------------------------------------------------- /application/views.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | from django.db.models import Max 4 | from django.http import Http404 5 | from rest_framework import generics, status, views 6 | from rest_framework.response import Response 7 | from rest_framework.views import APIView 8 | 9 | from .models import Category, Quiz 10 | from .serializers import CategorySerializer, QuestionSerializer 11 | 12 | # pylint:disable=E1101 13 | 14 | class ListCategories(generics.ListAPIView): 15 | serializer_class = CategorySerializer 16 | queryset = Category.objects.all() 17 | 18 | 19 | class StartQuiz(APIView): 20 | 21 | def get(self, request, category_id=None): 22 | try: 23 | quiz = Quiz.objects.get(category__id=category_id) 24 | except Quiz.DoesNotExist: 25 | raise Http404 26 | serializer = QuestionSerializer(quiz.question.all(), many=True) 27 | return Response(serializer.data) 28 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "quiz.settings") 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError as exc: 10 | raise ImportError( 11 | "Couldn't import Django. Are you sure it's installed and " 12 | "available on your PYTHONPATH environment variable? Did you " 13 | "forget to activate a virtual environment?" 14 | ) from exc 15 | execute_from_command_line(sys.argv) 16 | -------------------------------------------------------------------------------- /quiz/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arunshaji95/django-rest-quiz/61a2a06b36cda7f15b6a6ea9e613e71d06e0f5d6/quiz/__init__.py -------------------------------------------------------------------------------- /quiz/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for quiz project. 3 | 4 | Generated by 'django-admin startproject' using Django 2.0.4. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/2.0/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = '*bluc3((=fdo#6s^ot4)#&5yr=5==7)uwsg79afl%l-pm)(sqq' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 'django_extensions', 41 | 'rest_framework', 42 | 'rest_framework.authtoken', 43 | 'accounts.apps.AccountsConfig', 44 | 'application.apps.ApplicationConfig', 45 | ] 46 | 47 | MIDDLEWARE = [ 48 | 'django.middleware.security.SecurityMiddleware', 49 | 'django.contrib.sessions.middleware.SessionMiddleware', 50 | 'django.middleware.common.CommonMiddleware', 51 | 'django.middleware.csrf.CsrfViewMiddleware', 52 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 53 | 'django.contrib.messages.middleware.MessageMiddleware', 54 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 55 | ] 56 | 57 | ROOT_URLCONF = 'quiz.urls' 58 | 59 | TEMPLATES = [ 60 | { 61 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 62 | 'DIRS': [], 63 | 'APP_DIRS': True, 64 | 'OPTIONS': { 65 | 'context_processors': [ 66 | 'django.template.context_processors.debug', 67 | 'django.template.context_processors.request', 68 | 'django.contrib.auth.context_processors.auth', 69 | 'django.contrib.messages.context_processors.messages', 70 | ], 71 | }, 72 | }, 73 | ] 74 | 75 | WSGI_APPLICATION = 'quiz.wsgi.application' 76 | 77 | 78 | # Database 79 | # https://docs.djangoproject.com/en/2.0/ref/settings/#databases 80 | 81 | DATABASES = { 82 | 'default': { 83 | 'ENGINE': 'django.db.backends.sqlite3', 84 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 85 | } 86 | } 87 | 88 | 89 | # Password validation 90 | # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators 91 | 92 | AUTH_PASSWORD_VALIDATORS = [ 93 | { 94 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 95 | }, 96 | { 97 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 98 | }, 99 | { 100 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 101 | }, 102 | { 103 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 104 | }, 105 | ] 106 | 107 | 108 | # Internationalization 109 | # https://docs.djangoproject.com/en/2.0/topics/i18n/ 110 | 111 | LANGUAGE_CODE = 'en-us' 112 | 113 | TIME_ZONE = 'UTC' 114 | 115 | USE_I18N = True 116 | 117 | USE_L10N = True 118 | 119 | USE_TZ = True 120 | 121 | 122 | # Static files (CSS, JavaScript, Images) 123 | # https://docs.djangoproject.com/en/2.0/howto/static-files/ 124 | 125 | STATIC_URL = '/static/' 126 | AUTH_USER_MODEL = 'accounts.User' 127 | 128 | REST_FRAMEWORK = { 129 | 'DEFAULT_AUTHENTICATION_CLASSES': ( 130 | 'rest_framework.authentication.BasicAuthentication', 131 | 'rest_framework.authentication.TokenAuthentication', 132 | ), 133 | 'DEFAULT_PERMISSION_CLASSES': ( 134 | 'rest_framework.permissions.IsAuthenticated', 135 | ) 136 | } 137 | -------------------------------------------------------------------------------- /quiz/urls.py: -------------------------------------------------------------------------------- 1 | """quiz URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/2.0/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import include, path 18 | from rest_framework.authtoken import views 19 | 20 | urlpatterns = [ 21 | path('admin/', admin.site.urls), 22 | path('api-token-auth', views.ObtainAuthToken.as_view()), 23 | path('accounts/', include('accounts.urls')), 24 | path('quiz/', include('application.urls')), 25 | ] 26 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Django==2.2.28 2 | django-extensions==2.0.7 3 | djangorestframework==3.11.2 4 | Pillow==9.0.1 5 | pkg-resources==0.0.0 6 | pytz==2018.4 7 | six==1.11.0 8 | --------------------------------------------------------------------------------