mirror of
https://github.com/Alexander-D-Karpov/akarpov
synced 2024-11-25 08:13:44 +03:00
added test app forms
This commit is contained in:
parent
902408ca9d
commit
878158aa09
|
@ -5,3 +5,9 @@
|
|||
class TestPlatformConfig(AppConfig):
|
||||
name = "akarpov.test_platform"
|
||||
verbose_name = _("Test platform")
|
||||
|
||||
def ready(self):
|
||||
try:
|
||||
import akarpov.test_platform.signals # noqa F401
|
||||
except ImportError:
|
||||
pass
|
||||
|
|
79
akarpov/test_platform/forms.py
Normal file
79
akarpov/test_platform/forms.py
Normal file
|
@ -0,0 +1,79 @@
|
|||
from abc import ABC
|
||||
|
||||
from django import forms
|
||||
|
||||
from akarpov.test_platform.models import (
|
||||
BaseQuestion,
|
||||
Form,
|
||||
NumberQuestion,
|
||||
NumberRangeQuestion,
|
||||
SelectAnswerQuestion,
|
||||
SelectQuestion,
|
||||
TextQuestion,
|
||||
)
|
||||
|
||||
|
||||
class FormFormClass(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Form
|
||||
fields = ["name", "description", "public", "image", "time_since", "time_till"]
|
||||
|
||||
|
||||
class BaseQuestionForm(forms.ModelForm, ABC):
|
||||
class Meta:
|
||||
model = BaseQuestion
|
||||
fields = ["question", "help", "required"]
|
||||
|
||||
|
||||
class TextQuestionForm(BaseQuestionForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(BaseQuestionForm, self).__init__(*args, **kwargs)
|
||||
|
||||
class Meta(BaseQuestionForm.Meta):
|
||||
model = TextQuestion
|
||||
fields = BaseQuestionForm.Meta.fields + [
|
||||
"correct_answer",
|
||||
"answer_should_contain",
|
||||
"answer_should_not_contain",
|
||||
]
|
||||
|
||||
|
||||
class NumberQuestionForm(BaseQuestionForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(BaseQuestionForm, self).__init__(*args, **kwargs)
|
||||
|
||||
class Meta(BaseQuestionForm.Meta):
|
||||
model = NumberQuestion
|
||||
fields = BaseQuestionForm.Meta.fields + [
|
||||
"correct_answer",
|
||||
]
|
||||
|
||||
|
||||
class NumberRangeQuestionForm(BaseQuestionForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(BaseQuestionForm, self).__init__(*args, **kwargs)
|
||||
|
||||
class Meta(BaseQuestionForm.Meta):
|
||||
model = NumberRangeQuestion
|
||||
fields = BaseQuestionForm.Meta.fields + [
|
||||
"number_range_min",
|
||||
"number_range_max",
|
||||
]
|
||||
|
||||
|
||||
class SelectQuestionForm(BaseQuestionForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(BaseQuestionForm, self).__init__(*args, **kwargs)
|
||||
|
||||
class Meta(BaseQuestionForm.Meta):
|
||||
model = SelectQuestion
|
||||
fields = BaseQuestionForm.Meta.fields + [
|
||||
"min_required_answers",
|
||||
"max_required_answers",
|
||||
]
|
||||
|
||||
|
||||
class SelectAnswerQuestionForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = SelectAnswerQuestion
|
||||
fields = ["value", "correct"]
|
|
@ -0,0 +1,30 @@
|
|||
# Generated by Django 4.1.7 on 2023-02-24 20:00
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("test_platform", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="form",
|
||||
name="time_since",
|
||||
field=models.DateTimeField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="selectanswerquestion",
|
||||
name="question",
|
||||
field=models.ForeignKey(
|
||||
default=1,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="answers",
|
||||
to="test_platform.selectquestion",
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -6,6 +6,7 @@
|
|||
from polymorphic.models import PolymorphicModel
|
||||
|
||||
from akarpov.users.models import User
|
||||
from akarpov.utils.base import SubclassesMixin
|
||||
from akarpov.utils.files import user_file_upload_mixin
|
||||
|
||||
|
||||
|
@ -26,6 +27,7 @@ class Form(models.Model):
|
|||
image_cropped = models.ImageField(upload_to="cropped/", blank=True)
|
||||
|
||||
passed = models.IntegerField(default=0)
|
||||
time_since = models.DateTimeField(null=True, blank=True)
|
||||
time_till = models.DateTimeField(null=True, blank=True)
|
||||
|
||||
@property
|
||||
|
@ -40,8 +42,9 @@ def __str__(self):
|
|||
return f"form: {self.name}"
|
||||
|
||||
|
||||
class BaseQuestion(PolymorphicModel):
|
||||
type = _("No type")
|
||||
class BaseQuestion(PolymorphicModel, SubclassesMixin):
|
||||
type = "no_type"
|
||||
type_plural = _("No type")
|
||||
form: Form = models.ForeignKey(
|
||||
"test_platform.Form", related_name="fields", on_delete=models.CASCADE
|
||||
)
|
||||
|
@ -54,24 +57,29 @@ def __str__(self):
|
|||
|
||||
|
||||
class TextQuestion(BaseQuestion):
|
||||
type = _("Text question")
|
||||
type = "text"
|
||||
type_plural = _("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")
|
||||
type = "number"
|
||||
type_plural = _("Number question")
|
||||
correct_answer = models.IntegerField()
|
||||
|
||||
|
||||
class NumberRangeQuestion(BaseQuestion):
|
||||
type = _("Number question")
|
||||
type = "range"
|
||||
type_plural = _("Number question")
|
||||
number_range_min = models.IntegerField(blank=False)
|
||||
number_range_max = models.IntegerField(blank=False)
|
||||
|
||||
|
||||
class SelectQuestion(BaseQuestion):
|
||||
type = "select"
|
||||
type_plural = _("Select question")
|
||||
min_required_answers = models.IntegerField(blank=False)
|
||||
max_required_answers = models.IntegerField(blank=False)
|
||||
|
||||
|
@ -80,6 +88,9 @@ class SelectAnswerQuestion(models.Model):
|
|||
id: uuid.UUID = models.UUIDField(
|
||||
primary_key=True, default=uuid.uuid4, editable=False
|
||||
)
|
||||
question = models.ForeignKey(
|
||||
"test_platform.SelectQuestion", related_name="answers", on_delete=models.CASCADE
|
||||
)
|
||||
value = models.CharField(max_length=150)
|
||||
correct = models.BooleanField(null=True)
|
||||
|
||||
|
|
0
akarpov/test_platform/signals.py
Normal file
0
akarpov/test_platform/signals.py
Normal file
19
akarpov/utils/base.py
Normal file
19
akarpov/utils/base.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
|
||||
def all_subclasses(cls):
|
||||
return set(cls.__subclasses__()).union(
|
||||
[s for c in cls.__subclasses__() for s in all_subclasses(c)]
|
||||
)
|
||||
|
||||
|
||||
class SubclassesMixin:
|
||||
@classmethod
|
||||
def get_subclasses(cls):
|
||||
content_types = ContentType.objects.filter(app_label=cls._meta.app_label)
|
||||
models = [ct.model_class() for ct in content_types]
|
||||
return [
|
||||
model
|
||||
for model in models
|
||||
if (model is not None and issubclass(model, cls) and model is not cls)
|
||||
]
|
8
poetry.lock
generated
8
poetry.lock
generated
|
@ -1492,14 +1492,14 @@ doc = ["Sphinx", "sphinx-rtd-theme", "sphinxcontrib-spelling"]
|
|||
|
||||
[[package]]
|
||||
name = "faker"
|
||||
version = "17.0.0"
|
||||
version = "17.1.0"
|
||||
description = "Faker is a Python package that generates fake data for you."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "Faker-17.0.0-py3-none-any.whl", hash = "sha256:21c3c6c45183308151c14f62afe59bf54ace68f663e0180973698ba2a9a3b2c4"},
|
||||
{file = "Faker-17.0.0.tar.gz", hash = "sha256:17cf85aeb0363a3384ccd4c1f52b52ec8f414c7afaab74ae1f4c3e09a06e14de"},
|
||||
{file = "Faker-17.1.0-py3-none-any.whl", hash = "sha256:abc383d8e02403fe2aa3b5369283dd468494a450533b513ab6d23637f3f25396"},
|
||||
{file = "Faker-17.1.0.tar.gz", hash = "sha256:b94dc47512234fc5fff6f0752aaddd5e6ffea550f6ba31f4865b48d2b35429a1"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -2051,6 +2051,7 @@ category = "main"
|
|||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "livereload-2.6.3-py2.py3-none-any.whl", hash = "sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4"},
|
||||
{file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"},
|
||||
]
|
||||
|
||||
|
@ -3678,7 +3679,6 @@ category = "main"
|
|||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"},
|
||||
{file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"},
|
||||
]
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user