mirror of
https://github.com/Alexander-D-Karpov/akarpov
synced 2024-11-25 17:33:44 +03:00
added test forms
This commit is contained in:
parent
4a70342669
commit
902408ca9d
0
akarpov/test_platform/__init__.py
Normal file
0
akarpov/test_platform/__init__.py
Normal file
21
akarpov/test_platform/admin.py
Normal file
21
akarpov/test_platform/admin.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from akarpov.test_platform.models import (
|
||||
Form,
|
||||
FormHistory,
|
||||
FormPermission,
|
||||
NumberQuestion,
|
||||
NumberRangeQuestion,
|
||||
SelectAnswerQuestion,
|
||||
SelectQuestion,
|
||||
TextQuestion,
|
||||
)
|
||||
|
||||
admin.site.register(Form)
|
||||
admin.site.register(TextQuestion)
|
||||
admin.site.register(NumberQuestion)
|
||||
admin.site.register(NumberRangeQuestion)
|
||||
admin.site.register(SelectQuestion)
|
||||
admin.site.register(SelectAnswerQuestion)
|
||||
admin.site.register(FormPermission)
|
||||
admin.site.register(FormHistory)
|
7
akarpov/test_platform/apps.py
Normal file
7
akarpov/test_platform/apps.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class TestPlatformConfig(AppConfig):
|
||||
name = "akarpov.test_platform"
|
||||
verbose_name = _("Test platform")
|
270
akarpov/test_platform/migrations/0001_initial.py
Normal file
270
akarpov/test_platform/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,270 @@
|
|||
# Generated by Django 4.1.5 on 2023-02-24 16:18
|
||||
|
||||
import akarpov.utils.files
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
("contenttypes", "0002_remove_content_type_name"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="BaseQuestion",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("question", models.CharField(max_length=250)),
|
||||
("help", models.CharField(blank=True, max_length=200)),
|
||||
("required", models.BooleanField(default=True)),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
"base_manager_name": "objects",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Form",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("name", models.CharField(max_length=200)),
|
||||
("description", models.TextField(blank=True)),
|
||||
("slug", models.SlugField(blank=True, max_length=20)),
|
||||
("public", models.BooleanField(default=True)),
|
||||
("anyone_can_access", models.BooleanField(default=True)),
|
||||
("created", models.DateTimeField(auto_now_add=True)),
|
||||
("updated", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"image",
|
||||
models.ImageField(
|
||||
blank=True, upload_to=akarpov.utils.files.user_file_upload_mixin
|
||||
),
|
||||
),
|
||||
("image_cropped", models.ImageField(blank=True, upload_to="cropped/")),
|
||||
("passed", models.IntegerField(default=0)),
|
||||
("time_till", models.DateTimeField(blank=True, null=True)),
|
||||
(
|
||||
"creator",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="SelectAnswerQuestion",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.UUIDField(
|
||||
default=uuid.uuid4,
|
||||
editable=False,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
),
|
||||
),
|
||||
("value", models.CharField(max_length=150)),
|
||||
("correct", models.BooleanField(null=True)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="NumberQuestion",
|
||||
fields=[
|
||||
(
|
||||
"basequestion_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="test_platform.basequestion",
|
||||
),
|
||||
),
|
||||
("correct_answer", models.IntegerField()),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
"base_manager_name": "objects",
|
||||
},
|
||||
bases=("test_platform.basequestion",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="NumberRangeQuestion",
|
||||
fields=[
|
||||
(
|
||||
"basequestion_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="test_platform.basequestion",
|
||||
),
|
||||
),
|
||||
("number_range_min", models.IntegerField()),
|
||||
("number_range_max", models.IntegerField()),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
"base_manager_name": "objects",
|
||||
},
|
||||
bases=("test_platform.basequestion",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="SelectQuestion",
|
||||
fields=[
|
||||
(
|
||||
"basequestion_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="test_platform.basequestion",
|
||||
),
|
||||
),
|
||||
("min_required_answers", models.IntegerField()),
|
||||
("max_required_answers", models.IntegerField()),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
"base_manager_name": "objects",
|
||||
},
|
||||
bases=("test_platform.basequestion",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="TextQuestion",
|
||||
fields=[
|
||||
(
|
||||
"basequestion_ptr",
|
||||
models.OneToOneField(
|
||||
auto_created=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
parent_link=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
to="test_platform.basequestion",
|
||||
),
|
||||
),
|
||||
("correct_answer", models.CharField(max_length=250)),
|
||||
("answer_should_contain", models.CharField(max_length=250)),
|
||||
("answer_should_not_contain", models.CharField(max_length=250)),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
"base_manager_name": "objects",
|
||||
},
|
||||
bases=("test_platform.basequestion",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="FormHistory",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("opened", models.DateTimeField(auto_now_add=True)),
|
||||
(
|
||||
"form",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="users_opened",
|
||||
to="test_platform.form",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="opened_test_platform",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="basequestion",
|
||||
name="form",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="fields",
|
||||
to="test_platform.form",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="basequestion",
|
||||
name="polymorphic_ctype",
|
||||
field=models.ForeignKey(
|
||||
editable=False,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="polymorphic_%(app_label)s.%(class)s_set+",
|
||||
to="contenttypes.contenttype",
|
||||
),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="FormPermission",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"form",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="allowed",
|
||||
to="test_platform.form",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="allowed_test_platform",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"unique_together": {("form", "user")},
|
||||
},
|
||||
),
|
||||
]
|
0
akarpov/test_platform/migrations/__init__.py
Normal file
0
akarpov/test_platform/migrations/__init__.py
Normal file
114
akarpov/test_platform/models.py
Normal file
114
akarpov/test_platform/models.py
Normal file
|
@ -0,0 +1,114 @@
|
|||
import uuid
|
||||
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from polymorphic.models import PolymorphicModel
|
||||
|
||||
from akarpov.users.models import User
|
||||
from akarpov.utils.files import user_file_upload_mixin
|
||||
|
||||
|
||||
class Form(models.Model):
|
||||
name = models.CharField(max_length=200, blank=False)
|
||||
description = models.TextField(blank=True)
|
||||
|
||||
creator = models.ForeignKey("users.User", on_delete=models.CASCADE)
|
||||
slug = models.SlugField(max_length=20, blank=True)
|
||||
|
||||
public = models.BooleanField(default=True)
|
||||
anyone_can_access = models.BooleanField(default=True)
|
||||
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
|
||||
image = models.ImageField(upload_to=user_file_upload_mixin, blank=True)
|
||||
image_cropped = models.ImageField(upload_to="cropped/", blank=True)
|
||||
|
||||
passed = models.IntegerField(default=0)
|
||||
time_till = models.DateTimeField(null=True, blank=True)
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
return (
|
||||
self.time_till.timestamp() >= timezone.now().timestamp()
|
||||
if self.time_till
|
||||
else True
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"form: {self.name}"
|
||||
|
||||
|
||||
class BaseQuestion(PolymorphicModel):
|
||||
type = _("No type")
|
||||
form: Form = models.ForeignKey(
|
||||
"test_platform.Form", related_name="fields", on_delete=models.CASCADE
|
||||
)
|
||||
question = models.CharField(max_length=250, blank=False)
|
||||
help = models.CharField(max_length=200, blank=True)
|
||||
required = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.type} - {self.question}"
|
||||
|
||||
|
||||
class TextQuestion(BaseQuestion):
|
||||
type = _("Text question")
|
||||
correct_answer = models.CharField(max_length=250, blank=False)
|
||||
answer_should_contain = models.CharField(max_length=250, blank=False)
|
||||
answer_should_not_contain = models.CharField(max_length=250, blank=False)
|
||||
|
||||
|
||||
class NumberQuestion(BaseQuestion):
|
||||
type = _("Number question")
|
||||
correct_answer = models.IntegerField()
|
||||
|
||||
|
||||
class NumberRangeQuestion(BaseQuestion):
|
||||
type = _("Number question")
|
||||
number_range_min = models.IntegerField(blank=False)
|
||||
number_range_max = models.IntegerField(blank=False)
|
||||
|
||||
|
||||
class SelectQuestion(BaseQuestion):
|
||||
min_required_answers = models.IntegerField(blank=False)
|
||||
max_required_answers = models.IntegerField(blank=False)
|
||||
|
||||
|
||||
class SelectAnswerQuestion(models.Model):
|
||||
id: uuid.UUID = models.UUIDField(
|
||||
primary_key=True, default=uuid.uuid4, editable=False
|
||||
)
|
||||
value = models.CharField(max_length=150)
|
||||
correct = models.BooleanField(null=True)
|
||||
|
||||
|
||||
class FormPermission(models.Model):
|
||||
form: Form = models.ForeignKey(
|
||||
"test_platform.Form", related_name="allowed", on_delete=models.CASCADE
|
||||
)
|
||||
user: User = models.ForeignKey(
|
||||
"users.User", related_name="allowed_test_platform", on_delete=models.CASCADE
|
||||
)
|
||||
|
||||
class Meta:
|
||||
unique_together = ["form", "user"]
|
||||
|
||||
def __str__(self):
|
||||
return f"user {self.user.username} can access {self.form.name}"
|
||||
|
||||
|
||||
class FormHistory(models.Model):
|
||||
form: Form = models.ForeignKey(
|
||||
"test_platform.Form", related_name="users_opened", on_delete=models.CASCADE
|
||||
)
|
||||
user: User = models.ForeignKey(
|
||||
"users.User", related_name="opened_test_platform", on_delete=models.CASCADE
|
||||
)
|
||||
opened = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
def __str__(self):
|
||||
return (
|
||||
f"user {self.user.username} opened form {self.form.name} at {self.opened}"
|
||||
)
|
0
akarpov/test_platform/views.py
Normal file
0
akarpov/test_platform/views.py
Normal file
|
@ -142,6 +142,7 @@
|
|||
"akarpov.blog",
|
||||
"akarpov.files",
|
||||
"akarpov.pipeliner",
|
||||
"akarpov.test_platform",
|
||||
"akarpov.tools.shortener",
|
||||
"akarpov.tools.qr",
|
||||
]
|
||||
|
|
601
poetry.lock
generated
601
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user