Clean up imports, reformat code
Remove unnecessary method
This commit is contained in:
parent
ba1de78951
commit
cc2b4e9809
|
|
@ -10,51 +10,54 @@
|
|||
|
||||
from graphql_relay import to_global_id
|
||||
|
||||
from api.test_utils import create_client, DefaultUserTestCase
|
||||
from assignments.models import Assignment, StudentSubmission
|
||||
from api.test_utils import create_client
|
||||
from core.tests.base_test import SkillboxTestCase
|
||||
from users.factories import SchoolClassFactory
|
||||
from users.models import SchoolClassMember
|
||||
from .queries.mutations import UPDATE_SUBMISSION_FEEDBACK_MUTATION
|
||||
from ..factories import AssignmentFactory, StudentSubmissionFactory, SubmissionFeedbackFactory
|
||||
from ..factories import (
|
||||
AssignmentFactory,
|
||||
StudentSubmissionFactory,
|
||||
SubmissionFeedbackFactory,
|
||||
)
|
||||
|
||||
|
||||
class SubmissionFeedbackTestCase(SkillboxTestCase):
|
||||
def setUp(self):
|
||||
self.createDefault()
|
||||
|
||||
self.assignment = AssignmentFactory(
|
||||
owner=self.teacher
|
||||
)
|
||||
self.assignment_id = to_global_id('AssignmentNode', self.assignment.pk)
|
||||
self.assignment = AssignmentFactory(owner=self.teacher)
|
||||
self.assignment_id = to_global_id("AssignmentNode", self.assignment.pk)
|
||||
|
||||
self.student_submission = StudentSubmissionFactory(assignment=self.assignment, student=self.student1,
|
||||
final=False)
|
||||
self.student_submission_id = to_global_id('StudentSubmissionNode', self.student_submission.pk)
|
||||
self.student_submission = StudentSubmissionFactory(
|
||||
assignment=self.assignment, student=self.student1, final=False
|
||||
)
|
||||
self.student_submission_id = to_global_id(
|
||||
"StudentSubmissionNode", self.student_submission.pk
|
||||
)
|
||||
|
||||
school_class = SchoolClassFactory()
|
||||
for user in [self.student1, self.teacher]:
|
||||
SchoolClassMember.objects.create(
|
||||
user=user,
|
||||
school_class=school_class
|
||||
)
|
||||
SchoolClassMember.objects.create(user=user, school_class=school_class)
|
||||
user.set_selected_class(school_class)
|
||||
|
||||
|
||||
def _create_submission_feedback(self, user, final, text, student_submission_id):
|
||||
return self.get_client(user).execute(UPDATE_SUBMISSION_FEEDBACK_MUTATION, variables={
|
||||
'input': {
|
||||
"submissionFeedback": {
|
||||
"studentSubmission": student_submission_id,
|
||||
"text": text,
|
||||
"final": final
|
||||
return self.get_client(user).execute(
|
||||
UPDATE_SUBMISSION_FEEDBACK_MUTATION,
|
||||
variables={
|
||||
"input": {
|
||||
"submissionFeedback": {
|
||||
"studentSubmission": student_submission_id,
|
||||
"text": text,
|
||||
"final": final,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
def _fetch_assignment_student(self, user):
|
||||
client = self.get_client(user)
|
||||
query = '''
|
||||
query = """
|
||||
query AssignmentWithSubmissions($id: ID!) {
|
||||
assignment(id: $id) {
|
||||
title
|
||||
|
|
@ -68,14 +71,12 @@ class SubmissionFeedbackTestCase(SkillboxTestCase):
|
|||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
return client.execute(query, variables={
|
||||
'id': self.assignment_id
|
||||
})
|
||||
"""
|
||||
return client.execute(query, variables={"id": self.assignment_id})
|
||||
|
||||
def _fetch_assignment_teacher(self, user):
|
||||
client = self.get_client(user)
|
||||
query = '''
|
||||
query = """
|
||||
query AssignmentWithSubmissions($id: ID!) {
|
||||
assignment(id: $id) {
|
||||
title
|
||||
|
|
@ -89,14 +90,12 @@ class SubmissionFeedbackTestCase(SkillboxTestCase):
|
|||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
return client.execute(query, variables={
|
||||
'id': self.assignment_id
|
||||
})
|
||||
"""
|
||||
return client.execute(query, variables={"id": self.assignment_id})
|
||||
|
||||
def _fetch_submission_teacher(self, user):
|
||||
client = self.get_client(user)
|
||||
query = '''
|
||||
query = """
|
||||
query StudentSubmission($id: ID!) {
|
||||
studentSubmission(id: $id) {
|
||||
id
|
||||
|
|
@ -107,14 +106,12 @@ class SubmissionFeedbackTestCase(SkillboxTestCase):
|
|||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
return client.execute(query, variables={
|
||||
'id': self.student_submission_id
|
||||
})
|
||||
"""
|
||||
return client.execute(query, variables={"id": self.student_submission_id})
|
||||
|
||||
def _fetch_submission_feedback(self, user):
|
||||
client = create_client(user)
|
||||
query = '''
|
||||
query = """
|
||||
query AssignmentWithSubmissions($id: ID!) {
|
||||
assignment(id: $id) {
|
||||
title
|
||||
|
|
@ -128,96 +125,136 @@ class SubmissionFeedbackTestCase(SkillboxTestCase):
|
|||
}
|
||||
}
|
||||
}
|
||||
'''
|
||||
return client.execute(query, variables={
|
||||
'id': self.assignment_id
|
||||
})
|
||||
"""
|
||||
return client.execute(query, variables={"id": self.assignment_id})
|
||||
|
||||
def test_teacher_can_create_feedback(self):
|
||||
result = self._create_submission_feedback(self.teacher, False, 'Balalal', self.student_submission_id)
|
||||
result = self._create_submission_feedback(
|
||||
self.teacher, False, "Balalal", self.student_submission_id
|
||||
)
|
||||
|
||||
self.assertIsNone(result.errors)
|
||||
self.assertIsNotNone(
|
||||
result.data.get('updateSubmissionFeedback').get('updatedSubmissionFeedback').get('id'))
|
||||
|
||||
def test_student_cannot_create_feedback(self):
|
||||
result = self._create_submission_feedback(self.student1, False, 'Balalal', self.student_submission_id)
|
||||
self.assertIsNotNone(result.errors)
|
||||
self.assertEqual(len(result.errors), 1)
|
||||
self.assertEqual(result.errors[0].get('message'), 'Missing permissions')
|
||||
|
||||
def test_teacher_can_update_feedback(self):
|
||||
assignment = AssignmentFactory(
|
||||
owner=self.teacher
|
||||
result.data.get("updateSubmissionFeedback")
|
||||
.get("updatedSubmissionFeedback")
|
||||
.get("id")
|
||||
)
|
||||
|
||||
student_submission = StudentSubmissionFactory(assignment=assignment, student=self.student1, final=False)
|
||||
submission_feedback = SubmissionFeedbackFactory(teacher=self.teacher, final=False,
|
||||
student_submission=student_submission)
|
||||
submission_feedback_id = to_global_id('SubmissionFeedback', submission_feedback.pk)
|
||||
def test_student_cannot_create_feedback(self):
|
||||
result = self._create_submission_feedback(
|
||||
self.student1, False, "Balalal", self.student_submission_id
|
||||
)
|
||||
self.assertIsNotNone(result.errors)
|
||||
self.assertEqual(len(result.errors), 1)
|
||||
self.assertEqual(result.errors[0].get("message"), "Missing permissions")
|
||||
|
||||
result = self._create_submission_feedback(self.teacher, True, 'Some', submission_feedback_id)
|
||||
def test_teacher_can_update_feedback(self):
|
||||
assignment = AssignmentFactory(owner=self.teacher)
|
||||
|
||||
student_submission = StudentSubmissionFactory(
|
||||
assignment=assignment, student=self.student1, final=False
|
||||
)
|
||||
submission_feedback = SubmissionFeedbackFactory(
|
||||
teacher=self.teacher, final=False, student_submission=student_submission
|
||||
)
|
||||
submission_feedback_id = to_global_id(
|
||||
"SubmissionFeedback", submission_feedback.pk
|
||||
)
|
||||
|
||||
result = self._create_submission_feedback(
|
||||
self.teacher, True, "Some", submission_feedback_id
|
||||
)
|
||||
|
||||
self.assertIsNone(result.errors)
|
||||
|
||||
submission_feedback_response = result.data.get('updateSubmissionFeedback').get(
|
||||
'updatedSubmissionFeedback')
|
||||
|
||||
self.assertTrue(submission_feedback_response.get('final'))
|
||||
self.assertEqual(submission_feedback_response.get('text'), 'Some')
|
||||
|
||||
def test_external_teacher_cannot_update_feedback(self):
|
||||
assignment = AssignmentFactory(
|
||||
owner=self.teacher
|
||||
submission_feedback_response = result.data.get("updateSubmissionFeedback").get(
|
||||
"updatedSubmissionFeedback"
|
||||
)
|
||||
|
||||
student_submission = StudentSubmissionFactory(assignment=assignment, student=self.student1, final=False)
|
||||
submission_feedback = SubmissionFeedbackFactory(teacher=self.teacher, final=False,
|
||||
student_submission=student_submission)
|
||||
submission_feedback_id = to_global_id('SubmissionFeedback', submission_feedback.pk)
|
||||
self.assertTrue(submission_feedback_response.get("final"))
|
||||
self.assertEqual(submission_feedback_response.get("text"), "Some")
|
||||
|
||||
result = self._create_submission_feedback(self.teacher2, True, 'Some', submission_feedback_id)
|
||||
def test_external_teacher_cannot_update_feedback(self):
|
||||
assignment = AssignmentFactory(owner=self.teacher)
|
||||
|
||||
student_submission = StudentSubmissionFactory(
|
||||
assignment=assignment, student=self.student1, final=False
|
||||
)
|
||||
submission_feedback = SubmissionFeedbackFactory(
|
||||
teacher=self.teacher, final=False, student_submission=student_submission
|
||||
)
|
||||
submission_feedback_id = to_global_id(
|
||||
"SubmissionFeedback", submission_feedback.pk
|
||||
)
|
||||
|
||||
result = self._create_submission_feedback(
|
||||
self.teacher2, True, "Some", submission_feedback_id
|
||||
)
|
||||
|
||||
self.assertIsNotNone(result.errors)
|
||||
|
||||
def test_student_does_not_see_non_final_feedback(self):
|
||||
SubmissionFeedbackFactory(teacher=self.teacher, final=False, student_submission=self.student_submission)
|
||||
SubmissionFeedbackFactory(
|
||||
teacher=self.teacher,
|
||||
final=False,
|
||||
student_submission=self.student_submission,
|
||||
)
|
||||
result = self._fetch_assignment_student(self.student1)
|
||||
|
||||
self.assertIsNone(result.data.get('submissionFeedback'))
|
||||
self.assertIsNone(result.data.get("submissionFeedback"))
|
||||
|
||||
def test_student_does_see_final_feedback(self):
|
||||
submission_feedback = SubmissionFeedbackFactory(teacher=self.teacher, final=True,
|
||||
student_submission=self.student_submission)
|
||||
submission_feedback = SubmissionFeedbackFactory(
|
||||
teacher=self.teacher, final=True, student_submission=self.student_submission
|
||||
)
|
||||
result = self._fetch_assignment_student(self.student1)
|
||||
self.assertEqual(result.data.get('assignment').get('submission').get('submissionFeedback')
|
||||
.get('text'), submission_feedback.text)
|
||||
self.assertEqual(
|
||||
result.data.get("assignment")
|
||||
.get("submission")
|
||||
.get("submissionFeedback")
|
||||
.get("text"),
|
||||
submission_feedback.text,
|
||||
)
|
||||
|
||||
def test_teacher_can_see_feedback_for_submission(self):
|
||||
submission_feedback = SubmissionFeedbackFactory(teacher=self.teacher, final=False,
|
||||
student_submission=self.student_submission)
|
||||
submission_feedback = SubmissionFeedbackFactory(
|
||||
teacher=self.teacher,
|
||||
final=False,
|
||||
student_submission=self.student_submission,
|
||||
)
|
||||
self.student_submission.final = True
|
||||
self.student_submission.save()
|
||||
|
||||
result = self._fetch_assignment_teacher(self.teacher)
|
||||
self.assertEqual(result.data.get('assignment').get('submissions')[0].get('submissionFeedback')
|
||||
.get('text'), submission_feedback.text)
|
||||
self.assertEqual(
|
||||
result.data.get("assignment")
|
||||
.get("submissions")[0]
|
||||
.get("submissionFeedback")
|
||||
.get("text"),
|
||||
submission_feedback.text,
|
||||
)
|
||||
|
||||
def test_external_teacher_cannot_see_assignment_with_feedback(self):
|
||||
SubmissionFeedbackFactory(teacher=self.teacher, final=False,
|
||||
student_submission=self.student_submission)
|
||||
SubmissionFeedbackFactory(
|
||||
teacher=self.teacher,
|
||||
final=False,
|
||||
student_submission=self.student_submission,
|
||||
)
|
||||
self.student_submission.final = True
|
||||
self.student_submission.save()
|
||||
|
||||
result = self._fetch_assignment_teacher(self.teacher2)
|
||||
self.assertEqual(result.data.get('assignment').get('submissions'), [])
|
||||
self.assertEqual(result.data.get("assignment").get("submissions"), [])
|
||||
|
||||
def test_external_teacher_cannot_see_feedback(self):
|
||||
SubmissionFeedbackFactory(teacher=self.teacher, final=False,
|
||||
student_submission=self.student_submission)
|
||||
SubmissionFeedbackFactory(
|
||||
teacher=self.teacher,
|
||||
final=False,
|
||||
student_submission=self.student_submission,
|
||||
)
|
||||
self.student_submission.final = True
|
||||
self.student_submission.save()
|
||||
|
||||
result = self._fetch_submission_teacher(self.teacher2)
|
||||
self.assertIsNone(result.errors)
|
||||
self.assertIsNone(result.data.get('studentSubmission'))
|
||||
self.assertIsNone(result.data.get("studentSubmission"))
|
||||
|
|
|
|||
|
|
@ -1,35 +1,23 @@
|
|||
from django.conf import settings
|
||||
import json
|
||||
|
||||
from django.test import TestCase, RequestFactory
|
||||
from graphene.test import Client
|
||||
|
||||
from api import schema
|
||||
from api.schema import schema
|
||||
from api.test_utils import DefaultUserTestCase, create_client
|
||||
from assignments.factories import AssignmentFactory, StudentSubmissionFactory
|
||||
from assignments.models import Assignment
|
||||
from books.factories import ModuleFactory
|
||||
from books.models import ContentBlock, Chapter
|
||||
from core.factories import UserFactory
|
||||
from users.models import User
|
||||
from users.services import create_users
|
||||
|
||||
|
||||
class MyAssignmentsTest(DefaultUserTestCase):
|
||||
def setUp(self):
|
||||
super(MyAssignmentsTest, self).setUp()
|
||||
self.assignment = AssignmentFactory(
|
||||
owner=self.teacher
|
||||
)
|
||||
self.assignment = AssignmentFactory(owner=self.teacher)
|
||||
|
||||
self.submission1 = StudentSubmissionFactory(student=self.student1, assignment=self.assignment)
|
||||
self.submission2 = StudentSubmissionFactory(student=self.student2, assignment=self.assignment)
|
||||
self.submission1 = StudentSubmissionFactory(
|
||||
student=self.student1, assignment=self.assignment
|
||||
)
|
||||
self.submission2 = StudentSubmissionFactory(
|
||||
student=self.student2, assignment=self.assignment
|
||||
)
|
||||
|
||||
self.client = create_client(self.student1)
|
||||
|
||||
def query_my_assignments(self):
|
||||
query = '''
|
||||
query = """
|
||||
query MyActivityQuery {
|
||||
myActivity {
|
||||
edges {
|
||||
|
|
@ -138,20 +126,27 @@ class MyAssignmentsTest(DefaultUserTestCase):
|
|||
}
|
||||
}
|
||||
|
||||
'''
|
||||
"""
|
||||
|
||||
result = self.client.execute(query)
|
||||
|
||||
self.assertIsNone(result.get('errors'))
|
||||
self.assertIsNone(result.get("errors"))
|
||||
return result
|
||||
|
||||
@staticmethod
|
||||
def get_content(result):
|
||||
return result.get('data').get('myActivity').get('edges')
|
||||
return result.get("data").get("myActivity").get("edges")
|
||||
|
||||
def test_my_assignment_query(self):
|
||||
result = self.query_my_assignments()
|
||||
contents = self.get_content(result)
|
||||
self.assertEqual(len(contents), 1)
|
||||
self.assertEquals(contents[0].get('node').get('mySubmissions').get('edges')[0].get('node').get('text'), self.submission1.text)
|
||||
|
||||
self.assertEquals(
|
||||
contents[0]
|
||||
.get("node")
|
||||
.get("mySubmissions")
|
||||
.get("edges")[0]
|
||||
.get("node")
|
||||
.get("text"),
|
||||
self.submission1.text,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,9 +3,11 @@ from datetime import timedelta, date
|
|||
from graphql_relay import to_global_id
|
||||
|
||||
from assignments.factories import AssignmentFactory, StudentSubmissionFactory
|
||||
from assignments.tests.queries.mutations import UPDATE_ASSIGNMENT_MUTATION, UPDATE_SUBMISSION_FEEDBACK_MUTATION
|
||||
from assignments.tests.queries.mutations import (
|
||||
UPDATE_ASSIGNMENT_MUTATION,
|
||||
UPDATE_SUBMISSION_FEEDBACK_MUTATION,
|
||||
)
|
||||
from core.tests.base_test import SkillboxTestCase
|
||||
from users.models import User
|
||||
|
||||
|
||||
class AssignmentReadOnlyTestCase(SkillboxTestCase):
|
||||
|
|
@ -18,7 +20,7 @@ class AssignmentReadOnlyTestCase(SkillboxTestCase):
|
|||
self.teacher.license_expiry_date = yesterday
|
||||
self.teacher.save()
|
||||
self.assignment = AssignmentFactory()
|
||||
self.assignment_id = to_global_id('AssignmentNode', self.assignment.id)
|
||||
self.assignment_id = to_global_id("AssignmentNode", self.assignment.id)
|
||||
|
||||
def test_edit_assignment_fails(self):
|
||||
variables = {
|
||||
|
|
@ -27,11 +29,13 @@ class AssignmentReadOnlyTestCase(SkillboxTestCase):
|
|||
"answer": "bla",
|
||||
"document": "",
|
||||
"final": False,
|
||||
"id": self.assignment_id
|
||||
"id": self.assignment_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
result = self.get_client(self.student1).execute(UPDATE_ASSIGNMENT_MUTATION, variables=variables)
|
||||
result = self.get_client(self.student1).execute(
|
||||
UPDATE_ASSIGNMENT_MUTATION, variables=variables
|
||||
)
|
||||
self.assertIsNotNone(result.errors)
|
||||
|
||||
def test_share_assignment_fails(self):
|
||||
|
|
@ -41,42 +45,55 @@ class AssignmentReadOnlyTestCase(SkillboxTestCase):
|
|||
"answer": "bla",
|
||||
"document": "",
|
||||
"final": True,
|
||||
"id": self.assignment_id
|
||||
"id": self.assignment_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
result = self.get_client(self.student1).execute(UPDATE_ASSIGNMENT_MUTATION, variables=variables)
|
||||
result = self.get_client(self.student1).execute(
|
||||
UPDATE_ASSIGNMENT_MUTATION, variables=variables
|
||||
)
|
||||
self.assertIsNotNone(result.errors)
|
||||
|
||||
def test_edit_feedback_fails(self):
|
||||
student_submission = StudentSubmissionFactory(assignment=self.assignment, student=self.student1,
|
||||
final=True)
|
||||
student_submission_id = to_global_id('StudentSubmissionNode', student_submission.id)
|
||||
result = self.get_client(self.teacher).execute(UPDATE_SUBMISSION_FEEDBACK_MUTATION, variables={
|
||||
'input': {
|
||||
"submissionFeedback": {
|
||||
"studentSubmission": student_submission_id,
|
||||
"text": "Feedback",
|
||||
"final": False
|
||||
student_submission = StudentSubmissionFactory(
|
||||
assignment=self.assignment, student=self.student1, final=True
|
||||
)
|
||||
student_submission_id = to_global_id(
|
||||
"StudentSubmissionNode", student_submission.id
|
||||
)
|
||||
result = self.get_client(self.teacher).execute(
|
||||
UPDATE_SUBMISSION_FEEDBACK_MUTATION,
|
||||
variables={
|
||||
"input": {
|
||||
"submissionFeedback": {
|
||||
"studentSubmission": student_submission_id,
|
||||
"text": "Feedback",
|
||||
"final": False,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
self.assertIsNotNone(result.errors)
|
||||
|
||||
|
||||
def test_share_feedback_fails(self):
|
||||
student_submission = StudentSubmissionFactory(assignment=self.assignment, student=self.student1,
|
||||
final=True)
|
||||
student_submission_id = to_global_id('StudentSubmissionNode', student_submission.id)
|
||||
result = self.get_client(self.teacher).execute(UPDATE_SUBMISSION_FEEDBACK_MUTATION, variables={
|
||||
'input': {
|
||||
"submissionFeedback": {
|
||||
"studentSubmission": student_submission_id,
|
||||
"text": "Feedback",
|
||||
"final": True
|
||||
student_submission = StudentSubmissionFactory(
|
||||
assignment=self.assignment, student=self.student1, final=True
|
||||
)
|
||||
student_submission_id = to_global_id(
|
||||
"StudentSubmissionNode", student_submission.id
|
||||
)
|
||||
result = self.get_client(self.teacher).execute(
|
||||
UPDATE_SUBMISSION_FEEDBACK_MUTATION,
|
||||
variables={
|
||||
"input": {
|
||||
"submissionFeedback": {
|
||||
"studentSubmission": student_submission_id,
|
||||
"text": "Feedback",
|
||||
"final": True,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
self.assertIsNotNone(result.errors)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import logging
|
|||
|
||||
from django.db import models
|
||||
from wagtail.admin.panels import FieldPanel, TabbedInterface, ObjectList
|
||||
from books.models.contentblock import ContentBlock
|
||||
|
||||
from core.wagtail_utils import StrictHierarchyPage, get_default_settings
|
||||
from users.models import SchoolClass
|
||||
|
|
@ -39,9 +38,6 @@ class Chapter(StrictHierarchyPage, GraphqlNodeMixin):
|
|||
SchoolClass, related_name="hidden_chapter_descriptions"
|
||||
)
|
||||
|
||||
def get_content_blocks(self):
|
||||
return ContentBlock.objects.all().descendant_of(self)
|
||||
|
||||
def sync_title_visibility(self, school_class_template, school_class_to_sync):
|
||||
if (
|
||||
self.title_hidden_for.filter(id=school_class_template.id).exists()
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
from django.test import TestCase
|
||||
from assignments.factories import AssignmentFactory
|
||||
from assignments.models import Assignment
|
||||
|
||||
from books.factories import BookFactory, ContentBlockFactory
|
||||
from books.models.contentblock import ContentBlock
|
||||
from core.logger import get_logger
|
||||
from surveys.factories import SurveyFactory
|
||||
from surveys.models import Survey
|
||||
from users.services import create_users
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,11 @@
|
|||
import json
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
from wagtail.models import Page
|
||||
from wagtail.test.utils import WagtailTestUtils
|
||||
from wagtail.test.utils.form_data import rich_text
|
||||
from assignments.factories import AssignmentFactory
|
||||
from assignments.models import Assignment
|
||||
from books.blocks import AssignmentBlock, SurveyBlock
|
||||
from books.factories import BookFactory, ChapterFactory, ModuleFactory, TopicFactory
|
||||
from books.models.book import Book
|
||||
from books.models.chapter import Chapter
|
||||
from books.models.contentblock import ContentBlock
|
||||
from books.models.module import Module
|
||||
from books.models.topic import Topic
|
||||
|
|
|
|||
Loading…
Reference in New Issue