parent
c1d79b5bb3
commit
d356aed11b
59 changed files with 502 additions and 245 deletions
@ -1,76 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-12-13 12:30 |
|
||||||
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 = [ |
|
||||||
('access', '0001_initial'), |
|
||||||
('maps', '0001_initial'), |
|
||||||
('auth', '0008_alter_user_username_max_length'), |
|
||||||
('courses', '0002_auto_20171213_1230'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AddField( |
|
||||||
model_name='progress', |
|
||||||
name='course', |
|
||||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='Курс'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='progress', |
|
||||||
name='teacher', |
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teacher_progress', to=settings.AUTH_USER_MODEL, verbose_name='Преподователь по умолчанию'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='progress', |
|
||||||
name='template', |
|
||||||
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='maps.CourseRoute', verbose_name='Шаблон для прохождения если не указан явно смотри функцию get_template()'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='progress', |
|
||||||
name='user', |
|
||||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='pivotprogressvertex', |
|
||||||
name='progress', |
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='access.Progress'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='pivotprogressvertex', |
|
||||||
name='vertex', |
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Vertex'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='invite', |
|
||||||
name='owner', |
|
||||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Кому приглошение'), |
|
||||||
), |
|
||||||
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')]), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,7 +1,7 @@ |
|||||||
from django.conf.urls import url, include |
from django.conf.urls import url, include |
||||||
|
|
||||||
urlpatterns = [ |
urlpatterns = [ |
||||||
url(r'courses/', include('courses.urls')), |
url(r'courses/', include('course_service.courses.urls')), |
||||||
url(r'users/', include('access.urls')), |
url(r'users/', include('access.urls')), |
||||||
url(r'library/', include('library.urls')), |
url(r'library/', include('library.urls')), |
||||||
url(r'finance/', include('finance.urls')), |
url(r'finance/', include('finance.urls')), |
||||||
|
|||||||
@ -1,5 +1,5 @@ |
|||||||
DEBUG=True |
DEBUG=True |
||||||
SECRET_KEY='!eiquy7_+2#vn3z%zfp51$m-=tmvtcv*cj*@x$!v(_9btq0w=$' |
SECRET_KEY='!eiquy7_+2#vn3z%zfp51$m-=tmvtcv*cj*@x$!v(_9btq0w=$' |
||||||
DATABASE_URL='psql://team:nu5Xefise@127.0.0.1:5432/new_lms' |
DATABASE_URL='sqlite:///None' |
||||||
EMAIL_URL='smtp+tls://9ae31a1a770138:a7d79ee373a14c@smtp.mailtrap.io:2525' |
EMAIL_URL='smtp+tls://9ae31a1a770138:a7d79ee373a14c@smtp.mailtrap.io:2525' |
||||||
CACHE_URL=rediscache://127.0.0.1:6379/1?client_class=django_redis.client.DefaultClient |
CACHE_URL=rediscache://127.0.0.1:6379/1?client_class=django_redis.client.DefaultClient |
||||||
@ -0,0 +1 @@ |
|||||||
|
default_app_config = "course_service.courses.apps.CoursesAppConfig" |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
from django.contrib import admin |
||||||
|
|
||||||
|
from course_service.courses.models import Course, Topic, Vertex |
||||||
|
|
||||||
|
admin.site.register(Topic) |
||||||
|
admin.site.register(Vertex) |
||||||
|
admin.site.register(Course) |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
from course_service.courses.models import Course |
||||||
|
|
||||||
|
|
||||||
|
class InApiTeacher: |
||||||
|
@staticmethod |
||||||
|
def add_teacher(slug: str, token: str) -> Course: |
||||||
|
course = Course.objects.get(slug=slug) |
||||||
|
course.teachers.append(token) |
||||||
|
course.save() |
||||||
|
return course |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def delete_teacher(slug: str, token: str) -> None: |
||||||
|
course = Course.objects.get(slug=slug) |
||||||
|
course.teachers.remove(token) |
||||||
|
course.save() |
||||||
|
return None |
||||||
|
|
||||||
|
@staticmethod |
||||||
|
def get_token_list(slug: str) -> list: |
||||||
|
return Course.objects.get(slug=slug).teachers |
||||||
@ -0,0 +1,25 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
# Generated by Django 1.11.6 on 2017-12-14 15:13 |
||||||
|
from __future__ import unicode_literals |
||||||
|
|
||||||
|
from django.db import migrations, models |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
('courses', '0002_course_route'), |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.AddField( |
||||||
|
model_name='topic', |
||||||
|
name='description', |
||||||
|
field=models.TextField(blank=True, null=True, verbose_name='Описание'), |
||||||
|
), |
||||||
|
migrations.AlterField( |
||||||
|
model_name='vertex', |
||||||
|
name='description', |
||||||
|
field=models.TextField(blank=True, null=True, verbose_name='Описание'), |
||||||
|
), |
||||||
|
] |
||||||
@ -1,6 +1,6 @@ |
|||||||
from rest_framework import serializers |
from rest_framework import serializers |
||||||
|
|
||||||
from courses.models import Course, Vertex, Topic |
from course_service.courses.models import Course, Vertex, Topic |
||||||
|
|
||||||
|
|
||||||
class TopicSerializer(serializers.ModelSerializer): |
class TopicSerializer(serializers.ModelSerializer): |
||||||
@ -1,7 +1,7 @@ |
|||||||
from django.db.models.signals import pre_delete |
from django.db.models.signals import pre_delete |
||||||
from django.dispatch import receiver |
from django.dispatch import receiver |
||||||
|
|
||||||
from courses.models import Vertex |
from course_service.courses.models import Vertex |
||||||
|
|
||||||
|
|
||||||
@receiver(pre_delete, sender=Vertex) |
@receiver(pre_delete, sender=Vertex) |
||||||
@ -0,0 +1,51 @@ |
|||||||
|
from django.test import TestCase |
||||||
|
from course_service.courses.models import Course |
||||||
|
from lms.tools import EXAMPLE_BASE64 |
||||||
|
|
||||||
|
from course_service.courses.api import InApiTeacher |
||||||
|
|
||||||
|
|
||||||
|
class CourseInApiTestCase(TestCase): |
||||||
|
def setUp(self): |
||||||
|
self.first_course = Course.objects.create( |
||||||
|
title='Первый курс', |
||||||
|
slug='perviy-kuourse', |
||||||
|
) |
||||||
|
self.CDTeacher = InApiTeacher() |
||||||
|
|
||||||
|
def test_teacher(self): |
||||||
|
token1 = "token1" |
||||||
|
token2 = "token2" |
||||||
|
token3 = "token3" |
||||||
|
self.CDTeacher.add_teacher(slug=self.first_course.slug, token=token1) |
||||||
|
self.CDTeacher.add_teacher(slug=self.first_course.slug, token=token2) |
||||||
|
self.CDTeacher.add_teacher(slug=self.first_course.slug, token=token3) |
||||||
|
self.CDTeacher.delete_teacher(slug=self.first_course.slug, token=token2) |
||||||
|
self.assertEqual(self.CDTeacher.get_token_list(self.first_course.slug), ['token1', 'token3']) |
||||||
|
|
||||||
|
|
||||||
|
class CourseCRUDTest(TestCase): |
||||||
|
def setUp(self): |
||||||
|
self.first_course = Course.objects.update_or_create_course( |
||||||
|
title='Новый курс', |
||||||
|
level="Базовый", |
||||||
|
direction="Бизнес", |
||||||
|
) |
||||||
|
|
||||||
|
def test_slug(self): |
||||||
|
self.assertIsNotNone(self.first_course.slug) |
||||||
|
|
||||||
|
def test_upload_img(self): |
||||||
|
Course.objects.update_or_create_course( |
||||||
|
id=self.first_course.id, |
||||||
|
title='Новый курс', |
||||||
|
image=EXAMPLE_BASE64, |
||||||
|
big_image=EXAMPLE_BASE64, |
||||||
|
level="Базовый", |
||||||
|
direction="Бизнес", |
||||||
|
) |
||||||
|
|
||||||
|
self.assertIsNone(self.first_course.big_mobile_image) |
||||||
|
self.assertIsNotNone(self.first_course.image) |
||||||
|
|
||||||
|
|
||||||
@ -1,5 +1,6 @@ |
|||||||
from django.conf.urls import url |
from django.conf.urls import url |
||||||
from courses import views as views |
|
||||||
|
from course_service.courses import views as views |
||||||
|
|
||||||
urlpatterns = [ |
urlpatterns = [ |
||||||
url(r'detail/([0-9]{1,99})/$', views.CourseDetailView.as_view()), |
url(r'detail/([0-9]{1,99})/$', views.CourseDetailView.as_view()), |
||||||
@ -1,11 +1,11 @@ |
|||||||
from rest_framework.views import APIView |
from course_service.courses.models import Course, Vertex |
||||||
from rest_framework.renderers import JSONRenderer |
from rest_framework.renderers import JSONRenderer |
||||||
from rest_framework.response import Response |
from rest_framework.response import Response |
||||||
|
from rest_framework.views import APIView |
||||||
|
|
||||||
from access.models import Progress |
from access.models import Progress |
||||||
from maps.serializers import CourseMapSerializer |
from course_service.courses.serializers import CourseDetailSerializer, CourseListSerializer, VertexSerializer |
||||||
from courses.models import Course, Vertex |
from course_service.maps.serializers import CourseMapSerializer |
||||||
from courses.serializers import CourseDetailSerializer, CourseListSerializer, VertexSerializer, MiniVertexSerializer |
|
||||||
|
|
||||||
|
|
||||||
class TreeView(APIView): |
class TreeView(APIView): |
||||||
@ -1,6 +1,6 @@ |
|||||||
from django.contrib import admin |
from django.contrib import admin |
||||||
|
|
||||||
from maps.models import CourseMap, CourseRoute, PivotCourseMap, PivotVertex |
from course_service.maps.models import CourseMap, CourseRoute, PivotCourseMap, PivotVertex |
||||||
|
|
||||||
admin.site.register(CourseMap) |
admin.site.register(CourseMap) |
||||||
admin.site.register(CourseRoute) |
admin.site.register(CourseRoute) |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
from course_service.maps.models import CourseRoute |
||||||
|
|
||||||
|
|
||||||
|
class OutApiRoute: |
||||||
|
@staticmethod |
||||||
|
def change_id(id: int) -> str: |
||||||
|
return CourseRoute.objects.get(id=id).out_key |
||||||
@ -1,6 +1,6 @@ |
|||||||
from rest_framework import serializers |
from rest_framework import serializers |
||||||
|
|
||||||
from maps.models import CourseRoute, CourseMap |
from course_service.maps.models import CourseRoute, CourseMap |
||||||
|
|
||||||
|
|
||||||
class CourseRouteSerializer(serializers.ModelSerializer): |
class CourseRouteSerializer(serializers.ModelSerializer): |
||||||
@ -0,0 +1,23 @@ |
|||||||
|
# from django.test import TestCase |
||||||
|
# from course_service.maps.models import CourseRoute |
||||||
|
# |
||||||
|
# from course_service.maps.api import OutApiRoute |
||||||
|
# |
||||||
|
# |
||||||
|
# class RouteOutApiTestCase(TestCase): |
||||||
|
# def setUp(self): |
||||||
|
# self.first_course = Course.objects.create( |
||||||
|
# title='Первый курс', |
||||||
|
# slug='perviy-kuourse', |
||||||
|
# ) |
||||||
|
# self.CDTeacher = OutApiRoute() |
||||||
|
# |
||||||
|
# def test_teacher(self): |
||||||
|
# token1 = "token1" |
||||||
|
# token2 = "token2" |
||||||
|
# token3 = "token3" |
||||||
|
# self.CDTeacher.add_teacher(slug=self.first_course.slug, token=token1) |
||||||
|
# self.CDTeacher.add_teacher(slug=self.first_course.slug, token=token2) |
||||||
|
# self.CDTeacher.add_teacher(slug=self.first_course.slug, token=token3) |
||||||
|
# self.CDTeacher.delete_teacher(slug=self.first_course.slug, token=token2) |
||||||
|
# self.assertEqual(self.CDTeacher.get_token_list(self.first_course.slug), ['token1', 'token3']) |
||||||
@ -1 +0,0 @@ |
|||||||
default_app_config = "courses.apps.CoursesAppConfig" |
|
||||||
@ -1,7 +0,0 @@ |
|||||||
from django.contrib import admin |
|
||||||
|
|
||||||
from courses.models import Course, Topic, Vertex |
|
||||||
|
|
||||||
admin.site.register(Topic) |
|
||||||
admin.site.register(Vertex) |
|
||||||
admin.site.register(Course) |
|
||||||
@ -0,0 +1,18 @@ |
|||||||
|
import csv |
||||||
|
import os |
||||||
|
import sys |
||||||
|
|
||||||
|
import django |
||||||
|
|
||||||
|
sys.path.append("../") |
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings") |
||||||
|
django.setup() |
||||||
|
|
||||||
|
from storage.api import upload_file |
||||||
|
|
||||||
|
if __name__ == '__main__': |
||||||
|
with open('./course/storage.csv') as storage_csv: |
||||||
|
storage_reader = csv.DictReader(storage_csv) |
||||||
|
for row in storage_reader: |
||||||
|
if row['original']: |
||||||
|
upload_file(original=row['original']) |
||||||
@ -0,0 +1,29 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
# Generated by Django 1.11.6 on 2017-12-14 14:05 |
||||||
|
from __future__ import unicode_literals |
||||||
|
|
||||||
|
from django.db import migrations, models |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
('finance', '0001_initial'), |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.AddField( |
||||||
|
model_name='bill', |
||||||
|
name='route', |
||||||
|
field=models.CharField(default='', max_length=15, unique=True, verbose_name='Токен роута'), |
||||||
|
preserve_default=False, |
||||||
|
), |
||||||
|
migrations.AlterUniqueTogether( |
||||||
|
name='bill', |
||||||
|
unique_together=set([]), |
||||||
|
), |
||||||
|
migrations.RemoveField( |
||||||
|
model_name='bill', |
||||||
|
name='course', |
||||||
|
), |
||||||
|
] |
||||||
@ -0,0 +1,26 @@ |
|||||||
|
# -*- coding: utf-8 -*- |
||||||
|
# Generated by Django 1.11.6 on 2017-12-14 14:06 |
||||||
|
from __future__ import unicode_literals |
||||||
|
|
||||||
|
from django.conf import settings |
||||||
|
from django.db import migrations, models |
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration): |
||||||
|
|
||||||
|
dependencies = [ |
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL), |
||||||
|
('finance', '0002_auto_20171214_1405'), |
||||||
|
] |
||||||
|
|
||||||
|
operations = [ |
||||||
|
migrations.AlterField( |
||||||
|
model_name='bill', |
||||||
|
name='route', |
||||||
|
field=models.CharField(max_length=15, verbose_name='Токен роута'), |
||||||
|
), |
||||||
|
migrations.AlterUniqueTogether( |
||||||
|
name='bill', |
||||||
|
unique_together=set([('route', 'opener', 'user')]), |
||||||
|
), |
||||||
|
] |
||||||
@ -1,3 +0,0 @@ |
|||||||
from django.test import TestCase |
|
||||||
|
|
||||||
# Create your tests here. |
|
||||||
Loading…
Reference in new issue