Skip to content

Commit

Permalink
Merge pull request #25 from Ayshyama/phil_set_up_postgresql_db
Browse files Browse the repository at this point in the history
Set up postgresql db
  • Loading branch information
Ayshyama authored Nov 17, 2023
2 parents 57267a9 + 0bfdf90 commit f26fecd
Show file tree
Hide file tree
Showing 10 changed files with 373 additions and 17 deletions.
92 changes: 92 additions & 0 deletions app_accounts/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Generated by Django 4.2.5 on 2023-11-16 11:03

from django.conf import settings
import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone


class Migration(migrations.Migration):

initial = True

dependencies = [
('app_exercises', '0001_initial'),
('auth', '0012_alter_user_first_name_max_length'),
]

operations = [
migrations.CreateModel(
name='CustomUser',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('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')),
('bio', models.TextField(blank=True, max_length=500)),
('image', models.ImageField(blank=True, upload_to='images/')),
('email', models.EmailField(max_length=254, unique=True)),
('life', models.PositiveSmallIntegerField(default=10)),
('day_streak', models.PositiveSmallIntegerField(default=0)),
],
options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
migrations.CreateModel(
name='UserStatistic',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField(auto_now_add=True)),
('progress', models.PositiveSmallIntegerField(default=0)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='UserProgress',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField(auto_now_add=True)),
('exercise', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app_exercises.exercise')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='UserExerciseConversation',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('message', models.TextField()),
('is_human', models.BooleanField(default=False)),
('exercise', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app_exercises.exercise')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.AddField(
model_name='customuser',
name='exercises_done',
field=models.ManyToManyField(through='app_accounts.UserProgress', to='app_exercises.exercise'),
),
migrations.AddField(
model_name='customuser',
name='groups',
field=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'),
),
migrations.AddField(
model_name='customuser',
name='user_permissions',
field=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'),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 4.2.5 on 2023-11-16 15:30

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('app_accounts', '0001_initial'),
]

operations = [
migrations.RenameField(
model_name='userprogress',
old_name='date',
new_name='datetime',
),
migrations.AlterField(
model_name='userstatistic',
name='date',
field=models.DateField(auto_now_add=True),
),
]
43 changes: 42 additions & 1 deletion app_accounts/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,44 @@
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.db.models.signals import m2m_changed
from django.dispatch import receiver
from app_exercises.models import Exercise

# Create your models here.

class CustomUser(AbstractUser):
bio = models.TextField(max_length=500, blank=True)
image = models.ImageField(upload_to='images/', blank=True)
email = models.EmailField(unique=True)
life = models.PositiveSmallIntegerField(default=10)
exercises_done = models.ManyToManyField(Exercise, through='UserProgress')
day_streak = models.PositiveSmallIntegerField(default=0)


class UserExerciseConversation(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
exercise = models.ForeignKey(Exercise, on_delete=models.CASCADE)
message = models.TextField()
is_human = models.BooleanField(default=False)


class UserProgress(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
exercise = models.ForeignKey(Exercise, on_delete=models.CASCADE)
datetime = models.DateTimeField(auto_now_add=True)


class UserStatistic(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
date = models.DateField(auto_now_add=True)
progress = models.PositiveSmallIntegerField(default=0)


@receiver(m2m_changed, sender=CustomUser.exercises_done.through)
def create_user_progress(sender, instance, action, reverse, model, pk_set, **kwargs):
if action == "post_add" and not reverse:
for exercise_pk in pk_set:
UserProgress.objects.create(user=instance, exercise_id=exercise_pk)


# Connect the signal
m2m_changed.connect(create_user_progress, sender=CustomUser.exercises_done.through)
2 changes: 0 additions & 2 deletions app_accounts/tests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
from django.test import TestCase

# Create your tests here.
76 changes: 76 additions & 0 deletions app_exercises/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Generated by Django 4.2.5 on 2023-11-16 11:03

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='Exercise',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.TextField()),
('is_test', models.BooleanField(default=False)),
],
),
migrations.CreateModel(
name='Keywords',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('keyword', models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name='Subject',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('description', models.TextField(blank=True, max_length=500)),
('image', models.ImageField(upload_to='images/')),
],
),
migrations.CreateModel(
name='TestAnswer',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=500)),
('is_correct', models.BooleanField(default=False)),
('exercise', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app_exercises.exercise')),
],
),
migrations.CreateModel(
name='Module',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('description', models.TextField(blank=True, max_length=500)),
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app_exercises.subject')),
],
),
migrations.CreateModel(
name='Lesson',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('description', models.TextField(blank=True, max_length=500)),
('module', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app_exercises.module')),
],
),
migrations.AddField(
model_name='exercise',
name='keywords',
field=models.ManyToManyField(to='app_exercises.keywords'),
),
migrations.AddField(
model_name='exercise',
name='lesson',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app_exercises.lesson'),
),
]
41 changes: 40 additions & 1 deletion app_exercises/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
from django.db import models

# Create your models here.

class Subject(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(max_length=500, blank=True)
image = models.ImageField(upload_to='images/')


class Module(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(max_length=500, blank=True)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)


class Lesson(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(max_length=500, blank=True)
module = models.ForeignKey(Module, on_delete=models.CASCADE)


class Exercise(models.Model):
name = models.TextField()
lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE)
keywords = models.ManyToManyField('Keywords')
is_test = models.BooleanField(default=False)


class Keywords(models.Model):
keyword = models.CharField(max_length=100)


class TestAnswer(models.Model):
name = models.CharField(max_length=500)
exercise = models.ForeignKey(Exercise, on_delete=models.CASCADE)
is_correct = models.BooleanField(default=False)






87 changes: 86 additions & 1 deletion app_exercises/tests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,88 @@
from django.test import TestCase
from django.utils import timezone

from app_accounts.models import CustomUser, UserExerciseConversation, UserStatistic, UserProgress
from app_exercises.models import Subject, Module, Lesson, Exercise, Keywords, TestAnswer


class ModelCreationTestCase(TestCase):

lesson = None
module = None
subject = None
keyword = None
exercise = None
user = None
progress = None

@classmethod
def setUpTestData(cls):
# Set up non-modified objects used by all test methods
cls.subject = Subject.objects.create(name='Mathematics', description='Study of numbers')
cls.module = Module.objects.create(name='Algebra',
description='About algebra',
subject=cls.subject)
cls.lesson = Lesson.objects.create(name='Quadratic Equations',
description='Introduction to Quadratic Equations',
module=cls.module)
cls.exercise = Exercise.objects.create(name='Solve Quadratic Equations x^2 - 5x + 6 = 0',
lesson=cls.lesson,
is_test=True)
cls.keyword = Keywords.objects.create(keyword='quadratic')
cls.exercise.keywords.add(cls.keyword)
cls.test_answer = TestAnswer.objects.create(name='x=2 and x=3',
exercise=cls.exercise,
is_correct=True)

cls.user = CustomUser.objects.create_user(username='john', email='[email protected]', password='123')
cls.conversation = UserExerciseConversation.objects.create(user=cls.user, exercise=cls.exercise,
message='Hello', is_human=True)

cls.statistic = UserStatistic.objects.create(user=cls.user, progress=UserProgress.objects.count())

def test_subject_creation(self):
self.assertEqual(self.subject.name, 'Mathematics')
self.assertEqual(self.subject.description, 'Study of numbers')

def test_module_creation(self):
self.assertEqual(self.module.name, 'Algebra')
self.assertEqual(self.module.subject, self.subject)

def test_lesson_creation(self):
self.assertEqual(self.lesson.name, 'Quadratic Equations')
self.assertEqual(self.lesson.module, self.module)

def test_exercise_creation(self):
self.assertEqual(self.exercise.name, 'Solve Quadratic Equations x^2 - 5x + 6 = 0')
self.assertEqual(self.exercise.lesson, self.lesson)
self.assertTrue(self.exercise.is_test)

def test_keywords_association(self):
self.assertIn(self.keyword, self.exercise.keywords.all())

def test_test_answer_creation(self):
self.assertEqual(self.test_answer.name, 'x=2 and x=3')
self.assertEqual(self.test_answer.exercise, self.exercise)
self.assertTrue(self.test_answer.is_correct)

def test_custom_user_creation(self):
self.assertEqual(self.user.username, 'john')
self.assertEqual(self.user.email, '[email protected]')
self.assertEqual(self.user.life, 10)
self.assertEqual(self.user.day_streak, 0)

def test_user_exercise_conversation_creation(self):
self.assertEqual(self.conversation.user, self.user)
self.assertEqual(self.conversation.exercise, self.exercise)
self.assertEqual(self.conversation.message, 'Hello')
self.assertTrue(self.conversation.is_human)

def test_user_progress_auto_creation(self):
# Assume user and exercise have been created in setUpTestData
self.user.exercises_done.add(self.exercise)

# Now check if a UserProgress instance was created
progress_exists = UserProgress.objects.filter(user=self.user, exercise=self.exercise).exists()
self.assertTrue(progress_exists,
"UserProgress instance was not created when an exercise was added to exercises_done.")

# Create your tests here.
Binary file removed db.sqlite3
Binary file not shown.
Loading

0 comments on commit f26fecd

Please sign in to comment.