parent
01b6d3b5fe
commit
14ad75259b
29 changed files with 426 additions and 362 deletions
@ -1,65 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-11-28 11:50 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.conf import settings |
|
||||||
from django.db import migrations, models |
|
||||||
import django.db.models.deletion |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
initial = True |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('auth', '0008_alter_user_username_max_length'), |
|
||||||
('access', '0001_initial'), |
|
||||||
('courses', '0001_initial'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AddField( |
|
||||||
model_name='progress', |
|
||||||
name='course', |
|
||||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='Курс'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='progress', |
|
||||||
name='progress_list', |
|
||||||
field=models.ManyToManyField(blank=True, to='courses.Vertex', verbose_name='Лист пройденных объектов'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='progress', |
|
||||||
name='template', |
|
||||||
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.CourseRoute', verbose_name='Шаблон для прохождения если не указан явно смотри функцию get_template()'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='progress', |
|
||||||
name='user', |
|
||||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='invite', |
|
||||||
name='owner', |
|
||||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='account', |
|
||||||
name='owner', |
|
||||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='user', |
|
||||||
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='user', |
|
||||||
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'), |
|
||||||
), |
|
||||||
migrations.AlterUniqueTogether( |
|
||||||
name='progress', |
|
||||||
unique_together=set([('user', 'course')]), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -0,0 +1,9 @@ |
|||||||
|
from django.contrib import admin |
||||||
|
|
||||||
|
from achievements.models import Skills, Achievements, SkillJ, DiplomaGen, Diploma |
||||||
|
|
||||||
|
admin.site.register(Skills) |
||||||
|
admin.site.register(Achievements) |
||||||
|
admin.site.register(SkillJ) |
||||||
|
admin.site.register(Diploma) |
||||||
|
admin.site.register(DiplomaGen) |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
from django.apps import AppConfig |
||||||
|
|
||||||
|
|
||||||
|
class AchievementsConfig(AppConfig): |
||||||
|
name = 'achievements' |
||||||
@ -0,0 +1,73 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
# Generated by Django 1.11.6 on 2017-11-28 15:18 |
||||||
|
from __future__ import unicode_literals |
||||||
|
|
||||||
|
from django.db import migrations, models |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
initial = True |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.CreateModel( |
||||||
|
name='Achievements', |
||||||
|
fields=[ |
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||||
|
('icon', models.ImageField(blank=True, null=True, upload_to='diplomas', verbose_name='Отображение достижения')), |
||||||
|
], |
||||||
|
options={ |
||||||
|
'verbose_name': 'Достижение', |
||||||
|
'verbose_name_plural': 'Достижения', |
||||||
|
}, |
||||||
|
), |
||||||
|
migrations.CreateModel( |
||||||
|
name='Diploma', |
||||||
|
fields=[ |
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||||
|
('icon', models.ImageField(upload_to='diplomas', verbose_name='Иконка')), |
||||||
|
], |
||||||
|
options={ |
||||||
|
'verbose_name': 'Диплом', |
||||||
|
'verbose_name_plural': 'Дипломы', |
||||||
|
}, |
||||||
|
), |
||||||
|
migrations.CreateModel( |
||||||
|
name='DiplomaGen', |
||||||
|
fields=[ |
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||||
|
('template', models.URLField(verbose_name='Путь до шаблона')), |
||||||
|
], |
||||||
|
options={ |
||||||
|
'verbose_name': 'Генератор дипломов', |
||||||
|
'verbose_name_plural': 'Генераторы дипловов', |
||||||
|
}, |
||||||
|
), |
||||||
|
migrations.CreateModel( |
||||||
|
name='SkillJ', |
||||||
|
fields=[ |
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||||
|
], |
||||||
|
options={ |
||||||
|
'verbose_name': 'Размер навыка', |
||||||
|
'verbose_name_plural': 'Размеры навыков', |
||||||
|
}, |
||||||
|
), |
||||||
|
migrations.CreateModel( |
||||||
|
name='Skills', |
||||||
|
fields=[ |
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||||
|
('title', models.CharField(max_length=255, verbose_name='Наименование')), |
||||||
|
('color', models.CharField(max_length=255, verbose_name='Цвет')), |
||||||
|
('icon', models.ImageField(help_text='65x65', null=True, upload_to='skills', verbose_name='Большая картинка')), |
||||||
|
('description', models.TextField(blank=True, verbose_name='Описание')), |
||||||
|
], |
||||||
|
options={ |
||||||
|
'verbose_name': 'Навык', |
||||||
|
'verbose_name_plural': 'Навыки', |
||||||
|
}, |
||||||
|
), |
||||||
|
] |
||||||
@ -0,0 +1,56 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
# Generated by Django 1.11.6 on 2017-11-28 15:18 |
||||||
|
from __future__ import unicode_literals |
||||||
|
|
||||||
|
from django.conf import settings |
||||||
|
from django.db import migrations, models |
||||||
|
import django.db.models.deletion |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
initial = True |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
('achievements', '0001_initial'), |
||||||
|
('courses', '0001_initial'), |
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL), |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.AddField( |
||||||
|
model_name='skillj', |
||||||
|
name='lesson', |
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Vertex', verbose_name='Урок'), |
||||||
|
), |
||||||
|
migrations.AddField( |
||||||
|
model_name='skillj', |
||||||
|
name='skill', |
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='achievements.Skills', verbose_name='Навык'), |
||||||
|
), |
||||||
|
migrations.AddField( |
||||||
|
model_name='diplomagen', |
||||||
|
name='course', |
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course'), |
||||||
|
), |
||||||
|
migrations.AddField( |
||||||
|
model_name='diploma', |
||||||
|
name='template', |
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='achievements.DiplomaGen', verbose_name='Использовать шаблон'), |
||||||
|
), |
||||||
|
migrations.AddField( |
||||||
|
model_name='diploma', |
||||||
|
name='user', |
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), |
||||||
|
), |
||||||
|
migrations.AddField( |
||||||
|
model_name='achievements', |
||||||
|
name='course', |
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course'), |
||||||
|
), |
||||||
|
migrations.AddField( |
||||||
|
model_name='achievements', |
||||||
|
name='user', |
||||||
|
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), |
||||||
|
), |
||||||
|
] |
||||||
@ -0,0 +1,66 @@ |
|||||||
|
from django.db import models |
||||||
|
from django.conf import settings |
||||||
|
|
||||||
|
from courses.models import Course, Vertex |
||||||
|
|
||||||
|
|
||||||
|
class Achievements(models.Model): |
||||||
|
course = models.ForeignKey(to=Course) |
||||||
|
icon = models.ImageField(verbose_name='Отображение достижения', upload_to='diplomas', blank=True, null=True) |
||||||
|
user = models.ForeignKey(to=settings.AUTH_USER_MODEL) |
||||||
|
|
||||||
|
def __str__(self): |
||||||
|
return 'Студенту %s за курс %s' % (self.user.username, self.course.title) |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = 'Достижение' |
||||||
|
verbose_name_plural = 'Достижения' |
||||||
|
|
||||||
|
|
||||||
|
class Skills(models.Model): |
||||||
|
title = models.CharField(verbose_name='Наименование', max_length=255) |
||||||
|
color = models.CharField(verbose_name='Цвет', max_length=255) |
||||||
|
icon = models.ImageField(verbose_name='Большая картинка', upload_to='skills', null=True, help_text='65x65') |
||||||
|
description = models.TextField(verbose_name='Описание', blank=True) |
||||||
|
|
||||||
|
def __str__(self): return '%s' % self.title |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = 'Навык' |
||||||
|
verbose_name_plural = 'Навыки' |
||||||
|
|
||||||
|
|
||||||
|
class SkillJ(models.Model): |
||||||
|
skill = models.ForeignKey(to=Skills, verbose_name='Навык') |
||||||
|
lesson = models.ForeignKey(to=Vertex, verbose_name='Урок') |
||||||
|
|
||||||
|
def __str__(self): return '%s' % self.skill |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = 'Размер навыка' |
||||||
|
verbose_name_plural = 'Размеры навыков' |
||||||
|
|
||||||
|
|
||||||
|
class DiplomaGen(models.Model): |
||||||
|
course = models.ForeignKey(to=Course) |
||||||
|
template = models.URLField(verbose_name="Путь до шаблона") |
||||||
|
|
||||||
|
def __str__(self): |
||||||
|
return 'Шаблон можно найти по адресу: %s, диплом выдаётся за курс %s' % (self.template, self.course.title) |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = 'Генератор дипломов' |
||||||
|
verbose_name_plural = 'Генераторы дипловов' |
||||||
|
|
||||||
|
|
||||||
|
class Diploma(models.Model): |
||||||
|
icon = models.ImageField(verbose_name='Иконка', upload_to='diplomas') |
||||||
|
template = models.ForeignKey(to=DiplomaGen, verbose_name='Использовать шаблон', blank=True, null=True) |
||||||
|
user = models.ForeignKey(to=settings.AUTH_USER_MODEL) |
||||||
|
|
||||||
|
def __str__(self): |
||||||
|
return 'Студенту %s за курс %s' % (self.user.username, self.template.course.title) |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = 'Диплом' |
||||||
|
verbose_name_plural = 'Дипломы' |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
from django.test import TestCase |
||||||
|
|
||||||
|
# Create your tests here. |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
from django.shortcuts import render |
||||||
|
|
||||||
|
# Create your views here. |
||||||
@ -1,16 +1,9 @@ |
|||||||
from django.contrib import admin |
from django.contrib import admin |
||||||
|
|
||||||
from courses.models import Course, Skills, Achievements, SkillJ,\ |
from courses.models import Course, Tutorial, Topic, Task, Vertex |
||||||
CourseMap, Topic, Task, Vertex, Diploma, Tutorial, DiplomaGen |
|
||||||
|
|
||||||
admin.site.register(CourseMap) |
|
||||||
admin.site.register(Topic) |
admin.site.register(Topic) |
||||||
admin.site.register(Task) |
admin.site.register(Task) |
||||||
admin.site.register(Vertex) |
admin.site.register(Vertex) |
||||||
admin.site.register(Tutorial) |
admin.site.register(Tutorial) |
||||||
admin.site.register(Course) |
admin.site.register(Course) |
||||||
admin.site.register(Skills) |
|
||||||
admin.site.register(Achievements) |
|
||||||
admin.site.register(SkillJ) |
|
||||||
admin.site.register(Diploma) |
|
||||||
admin.site.register(DiplomaGen) |
|
||||||
@ -0,0 +1,6 @@ |
|||||||
|
from django.contrib import admin |
||||||
|
|
||||||
|
from maps.models import CourseMap, CourseRoute |
||||||
|
|
||||||
|
admin.site.register(CourseMap) |
||||||
|
admin.site.register(CourseRoute) |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
from django.apps import AppConfig |
||||||
|
|
||||||
|
|
||||||
|
class MapsConfig(AppConfig): |
||||||
|
name = 'maps' |
||||||
@ -0,0 +1,77 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
# Generated by Django 1.11.6 on 2017-11-28 15:18 |
||||||
|
from __future__ import unicode_literals |
||||||
|
|
||||||
|
from django.db import migrations, models |
||||||
|
import django.db.models.deletion |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
initial = True |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
('courses', '0001_initial'), |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.CreateModel( |
||||||
|
name='CourseMap', |
||||||
|
fields=[ |
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||||
|
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='К какому курсу привязан')), |
||||||
|
], |
||||||
|
options={ |
||||||
|
'verbose_name': 'Карта линейного прохождения курсов', |
||||||
|
'verbose_name_plural': 'Карты линейного прохождения курсов', |
||||||
|
}, |
||||||
|
), |
||||||
|
migrations.CreateModel( |
||||||
|
name='CourseRoute', |
||||||
|
fields=[ |
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||||
|
('name', models.CharField(blank=True, max_length=255, null=True, unique=True, verbose_name='Имя шаблона')), |
||||||
|
('is_template', models.BooleanField(default=True, verbose_name='Может ли быть использован как шаблон')), |
||||||
|
], |
||||||
|
options={ |
||||||
|
'verbose_name': 'Маршрут прохождения', |
||||||
|
'verbose_name_plural': 'Маршруты прохождения', |
||||||
|
}, |
||||||
|
), |
||||||
|
migrations.CreateModel( |
||||||
|
name='PivotCourseMap', |
||||||
|
fields=[ |
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||||
|
('sort', models.SmallIntegerField(unique=True, verbose_name='Порядок сортировки')), |
||||||
|
('map_course', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='maps.CourseMap', verbose_name='К какой сортеровке имеетотношение')), |
||||||
|
('route', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='maps.CourseRoute', verbose_name='К какому узлу')), |
||||||
|
], |
||||||
|
options={ |
||||||
|
'verbose_name': 'Порядок сортировки узла', |
||||||
|
'verbose_name_plural': 'Порядки сортировок узла', |
||||||
|
'ordering': ('sort',), |
||||||
|
}, |
||||||
|
), |
||||||
|
migrations.CreateModel( |
||||||
|
name='PivotVertex', |
||||||
|
fields=[ |
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||||
|
('sort', models.SmallIntegerField(unique=True, verbose_name='Порядок сортировки')), |
||||||
|
('map_course', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='maps.CourseMap', verbose_name='К какой сортеровке имеетотношение')), |
||||||
|
('vertex', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Vertex', verbose_name='К какому узлу')), |
||||||
|
], |
||||||
|
options={ |
||||||
|
'verbose_name': 'Порядок сортировки узла', |
||||||
|
'verbose_name_plural': 'Порядки сортировок узла', |
||||||
|
'ordering': ('sort',), |
||||||
|
}, |
||||||
|
), |
||||||
|
migrations.AlterUniqueTogether( |
||||||
|
name='pivotvertex', |
||||||
|
unique_together=set([('map_course', 'vertex')]), |
||||||
|
), |
||||||
|
migrations.AlterUniqueTogether( |
||||||
|
name='pivotcoursemap', |
||||||
|
unique_together=set([('map_course', 'route')]), |
||||||
|
), |
||||||
|
] |
||||||
@ -0,0 +1,86 @@ |
|||||||
|
from django.db import models |
||||||
|
|
||||||
|
from lms.global_decorators import transaction_decorator |
||||||
|
|
||||||
|
|
||||||
|
class CourseRoute(models.Model): |
||||||
|
""" |
||||||
|
Объединение нескольких мап курса, одназначно |
||||||
|
определяет способ прохождения по курсу. |
||||||
|
""" |
||||||
|
name = models.CharField(max_length=255, verbose_name='Имя шаблона', blank=True, null=True, unique=True) |
||||||
|
is_template = models.BooleanField(default=True, verbose_name='Может ли быть использован как шаблон') |
||||||
|
|
||||||
|
def is_finish(self, user): |
||||||
|
return bool(sum([int(i.map_course.is_finish(user)) for i in self.pivotcoursemap_set.all()])) |
||||||
|
|
||||||
|
def get_active_objects(self, user): |
||||||
|
return (i.map_course.getactive_object(user) for i in self.pivotcoursemap_set.all()) |
||||||
|
|
||||||
|
def get_view(self): |
||||||
|
return (i.map_course for i in self.pivotcoursemap_set.all()) |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = 'Маршрут прохождения' |
||||||
|
verbose_name_plural = 'Маршруты прохождения' |
||||||
|
|
||||||
|
|
||||||
|
class CourseMap(models.Model): |
||||||
|
""" |
||||||
|
Способы отображения курса. Упорядочены в порядке возрастания приоретета. |
||||||
|
""" |
||||||
|
course = models.ForeignKey(to='courses.Course', verbose_name='К какому курсу привязан') |
||||||
|
|
||||||
|
@transaction_decorator |
||||||
|
def add_vertex(self, vertex, sort): |
||||||
|
if sort > self.pivotvertex_set.count()+1: |
||||||
|
raise ValueError("list index out of range") |
||||||
|
for i in self.pivotvertex_set.filter(sort__gte=sort): |
||||||
|
i.sort += 1 |
||||||
|
i.save() |
||||||
|
|
||||||
|
pivot = PivotVertex.objects.create(vertex=vertex, sort=sort, map_course=self) |
||||||
|
pivot.save() |
||||||
|
return pivot |
||||||
|
|
||||||
|
def merge(self, another): |
||||||
|
return # TODO: Доделать!!! |
||||||
|
|
||||||
|
def get_difference(self, user) -> list: |
||||||
|
return list(set( |
||||||
|
[i.vertex for i in self.pivotvertex_set.all()]).difference(set(user.progress.progress_list.all()) |
||||||
|
)) |
||||||
|
|
||||||
|
def is_finish(self, user) -> bool: |
||||||
|
return self.get_difference(user) == [] |
||||||
|
|
||||||
|
def get_active_object(self, user): |
||||||
|
return self.pivotvertex_set.exclude(vertex__in=self.get_difference(user))[0] |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = 'Карта линейного прохождения курсов' |
||||||
|
verbose_name_plural = 'Карты линейного прохождения курсов' |
||||||
|
|
||||||
|
|
||||||
|
class PivotCourseMap(models.Model): |
||||||
|
route = models.ForeignKey(to=CourseRoute, verbose_name="К какому узлу") |
||||||
|
sort = models.SmallIntegerField(verbose_name='Порядок сортировки', unique=True) |
||||||
|
map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортеровке имеетотношение', blank=True, null=True) |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = 'Порядок сортировки узла' |
||||||
|
verbose_name_plural = 'Порядки сортировок узла' |
||||||
|
unique_together = (('map_course', 'route'),) |
||||||
|
ordering = ('sort', ) |
||||||
|
|
||||||
|
|
||||||
|
class PivotVertex(models.Model): |
||||||
|
vertex = models.ForeignKey(to='courses.Vertex', verbose_name="К какому узлу") |
||||||
|
sort = models.SmallIntegerField(verbose_name='Порядок сортировки', unique=True) |
||||||
|
map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортеровке имеетотношение', blank=True, null=True) |
||||||
|
|
||||||
|
class Meta: |
||||||
|
verbose_name = 'Порядок сортировки узла' |
||||||
|
verbose_name_plural = 'Порядки сортировок узла' |
||||||
|
unique_together = (('map_course', 'vertex'),) |
||||||
|
ordering = ('sort', ) |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
from django.test import TestCase |
||||||
|
|
||||||
|
# Create your tests here. |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
from django.shortcuts import render |
||||||
|
|
||||||
|
# Create your views here. |
||||||
Loading…
Reference in new issue