Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions application/courses_app/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Section, ClassmatesCheckedTask, TaskOption, StudentResult, Check, TaskWithTick, \
TaskWithTickStudentResult, TaskWithTeacherCheckCheck, TaskWithTeacherCheck, \
TaskWithKeyword, TaskWithTeacherCheckOption, TaskWithKeywordOption, \
TaskWithTeacherCheckResult, TaskWithKeywordResult, TaskWithTickInStream, StudentInCourse, CourseNews, Badge, BadgeForUser, CourseFAQ
TaskWithTeacherCheckResult, TaskWithKeywordResult, TaskWithTickInStream, StudentInCourse, CourseNews, Badge, BadgeForUser, CourseFAQ, TaskWithTeacherCheckInStream


admin.site.register(StudentGroup)
Expand Down Expand Up @@ -36,7 +36,7 @@
admin.site.register(Badge)
admin.site.register(BadgeForUser)
admin.site.register(CourseFAQ)

admin.site.register(TaskWithTeacherCheckInStream)

UserAdmin.fieldsets += ('Custom fields set', {'fields': ('role', 'group')}),
admin.site.register(User, UserAdmin)
Expand Down
2 changes: 1 addition & 1 deletion application/courses_app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ class TaskWithTeacherCheckResult(models.Model):
option = models.ForeignKey(TaskWithTeacherCheckOption, on_delete=models.CASCADE, related_name = 'task_with_teacher_results')
description = models.CharField(max_length=1024, blank = True, null=True)
perform = models.BooleanField(default=False)
on_check = models.BooleanField(default=True)
on_check = models.BooleanField(default=False) # был true
file = models.FileField(upload_to='task_with_teacher_result_files/', null=True, blank=True)


Expand Down
1 change: 1 addition & 0 deletions application/courses_app/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class SectionInCourseSerializer(serializers.ModelSerializer):
task_with_tick_in_section = TaskWithTickInSectionSerializer(many = True)
task_with_teacher_check_in_section = TaskWithTeacherCheckInSectionSerializer(many = True)
task_with_keyword_in_section = TaskWithKeywordCheckInSectionSerializer(many = True)
fixed_tests_for_section = FixedTestSerializer(many = True)
class Meta:
model = Section
fields = '__all__'
Expand Down
38 changes: 35 additions & 3 deletions application/courses_app/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
from stats.models import StudentFixedTest



User = get_user_model()


Expand Down Expand Up @@ -155,6 +156,17 @@ class GroupInStreamNewDetailView(generics.RetrieveAPIView):
serializer_class = StudentStreamListSerializer
permission_classes = [permissions.AllowAny]

def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
newdata = dict(serializer.data)
course = Course.objects.filter(streams_on_a_course__id=self.kwargs['pk'])
isJoined = StudentInCourse.objects.filter(user=self.request.user, course_id=course[0].id)
if isJoined:
newdata.update({"status": "2"})
else:
newdata.update({"status": "1"})
return Response(newdata)

class GroupInStreamNewDeleteUpdateView(generics.RetrieveUpdateDestroyAPIView):
queryset = StudentStream.objects.all()
Expand Down Expand Up @@ -403,6 +415,13 @@ def list(self, request, **kwargs):
if TaskWithKeywordResult.objects.filter(user = self.request.user, option__task_id = task["id"], perform = True):
student_tasks +=1

for task in section["task_with_teacher_check_in_section"]:
all_tasks +=1
# if TaskWithTeacherCheckResult.objects.filter(user = self.request.user, option__task_id = task["id"], perform = True):
# student_tasks +=1

for task in section["fixed_tests_for_section"]:
all_tasks +=1

try:
newdata.update({"status": StudentInCourse.objects.get(course = newdata["id"], user = self.request.user).status, "all_tasks": all_tasks, "student_tasks": student_tasks})
Expand Down Expand Up @@ -440,7 +459,7 @@ def retrieve(self, request, *args, **kwargs):
try:
instance = self.get_object()
except (Course.DoesNotExist, KeyError):
return Response({"error": "Requested Movie does not exist"}, status=status.HTTP_404_NOT_FOUND)
return Response({"error": "Requested Course does not exist"}, status=status.HTTP_404_NOT_FOUND)
serializer = self.get_serializer(instance)
print ('her')
newdata = dict(serializer.data)
Expand Down Expand Up @@ -509,8 +528,12 @@ def retrieve(self, request, *args, **kwargs):

for task in section["fixed_tests_for_section"]:
try:
if StudentFixedTest.objects.filter(test = task["id"], student = self.request.user, is_success = True):
task.update({"status": "1"})
results = StudentFixedTest.objects.filter(test = task["id"], student = self.request.user, is_success = True).values('correct_answers_percent')
if results:
resultsArr = []
for item in results:
resultsArr.append(item['correct_answers_percent'])
task.update({"status": "1", "results": resultsArr })
else:
task.update({"status": "0"})
except:
Expand Down Expand Up @@ -1016,6 +1039,15 @@ class TaskWithTickStudentResultCreateView(generics.CreateAPIView):
serializer_class = CreateTaskWithTickStudentResultSerializer
permission_classes = [permissions.AllowAny]

# def create(self, request, *args, **kwargs):
# request.data.update({"user": request.user.id})
# serializer = self.get_serializer(data=request.data)
# serializer.is_valid(raise_exception=True)
# self.perform_create(serializer)
# headers = self.get_success_headers(serializer.data)

# return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)


class TaskWithTickStudentResultRetrieveView(generics.RetrieveAPIView):
queryset = TaskWithTickStudentResult.objects.all()
Expand Down
27 changes: 21 additions & 6 deletions application/online_notebook_project/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
"""

import os
from os.path import join, dirname
from dotenv import load_dotenv

dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
Expand Down Expand Up @@ -204,15 +209,25 @@
# ]


# EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
# EMAIL_HOST = 'smtp.gmail.com'
# EMAIL_USE_TLS = True
# EMAIL_PORT = 587
# EMAIL_HOST_USER = '[email protected]'
# EMAIL_HOST_PASSWORD = '*'

# for dev yande email test
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = '*'
EMAIL_HOST = 'smtp.yandex.ru'
EMAIL_USE_TLS = False
EMAIL_USE_SSL = True
EMAIL_PORT = 465
EMAIL_HOST_USER = os.getenv('EMAIL_LOGIN')
EMAIL_HOST_PASSWORD = os.getenv('EMAIL_PASSWORD')
DEFAULT_FROM_EMAIL = os.getenv('EMAIL_ADDRESS')

DJOSER = {
'PASSWORD_RESET_CONFIRM_URL': 'password/reset/confirm/{uid}/{token}',
'PASSWORD_RESET_CONFIRM_URL': 'restore-confirm/{uid}/{token}',
'USERNAME_RESET_CONFIRM_URL': '#/username/reset/confirm/{uid}/{token}',
'ACTIVATION_URL': '#/activate/{uid}/{token}',
'SEND_ACTIVATION_EMAIL': False,
Expand Down
2 changes: 1 addition & 1 deletion application/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ pillow==7.0.0
PyMySQL[rsa]
cryptography
drf-yasg

python-dotenv
4 changes: 2 additions & 2 deletions application/stats/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def finish_test(self):


class StudentFixedTest(StudentTest):
test = models.ForeignKey(FixedTest, on_delete=models.PROTECT)
test = models.ForeignKey(FixedTest, on_delete=models.CASCADE)

class Meta:
unique_together = ('test', 'student', 'number_of_try')
Expand Down Expand Up @@ -85,7 +85,7 @@ class Meta:


class StudentFixedTestQuestion(StudentTestQuestion):
student_test = models.ForeignKey(StudentFixedTest, on_delete=models.PROTECT)
student_test = models.ForeignKey(StudentFixedTest, on_delete=models.CASCADE)

class Meta:
unique_together = ('student_test', 'question')
5 changes: 5 additions & 0 deletions application/stats/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from rest_framework import generics, views, exceptions, viewsets, filters, mixins
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import permissions

from tests_builder import models as tests_models
from tests_builder import serializers as tests_serializers
Expand Down Expand Up @@ -76,6 +77,9 @@ class StudentRandomTestQuestionSet(StudentTestQuestionSet):


class StudentFixedTestQuestionSet(StudentTestQuestionSet):
# TODO: пермишн нужен на студента
# здесь студент отв на по вопросы (POST)
permission_classes = [permissions.AllowAny]
queryset = stats_models.StudentFixedTestQuestion.objects.all()
serializer_class = serializers.StudentFixedTestQuestionSerializer
filter_backends = (django_filters.DjangoFilterBackend, filters.OrderingFilter)
Expand Down Expand Up @@ -115,6 +119,7 @@ def get_students_stats(self, request):


class StudentFixedTestSet(StudentTestSet):
permission_classes = [permissions.AllowAny]
queryset = stats_models.StudentFixedTest.objects.all()
serializer_class = serializers.StudentFixedTestSerializer
filter_backends = (django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
Expand Down
8 changes: 4 additions & 4 deletions application/tests_builder/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def get_questions_by_tags(cls, tags: List, count: Optional[int] = None):

class Answer(models.Model):
question = models.ForeignKey(Question, related_name='answers', on_delete=models.CASCADE)
text_answer = models.CharField(max_length=255)
text_answer = models.CharField(max_length=255, blank=True)
is_correct = models.BooleanField()

def __str__(self):
Expand Down Expand Up @@ -78,14 +78,14 @@ def __str__(self):

class FixedTestQuestion(models.Model):
test = models.ForeignKey('FixedTest', on_delete=models.CASCADE, related_name='test_to_question')
question = models.ForeignKey('Question', on_delete=models.CASCADE, related_name='question_to_test')
question = models.ForeignKey('Question', null=True, on_delete=models.CASCADE, related_name='question_to_test')
position = models.PositiveSmallIntegerField()

class Meta:
unique_together = (('test', 'question'), ('test', 'position'))

def __str__(self):
return f'{self.question.text_question}'
# def __str__(self):
# return f'{self.question.text_question}'


class FixedTest(Test):
Expand Down
43 changes: 41 additions & 2 deletions application/tests_builder/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def update(self, instance, validated_data):


class FixedTestQuestionSerializer(serializers.ModelSerializer):
question = QuestionSerializer()
# question = QuestionSerializer()

class Meta:
model = models.FixedTestQuestion
Expand All @@ -77,7 +77,7 @@ class Meta:
class CreateFixedTestQuestionSerializer(serializers.ModelSerializer):
class Meta:
model = models.FixedTestQuestion
fields = ('position', 'question')
fields = ('id', 'position', 'question')


class FixedTestSerializer(serializers.ModelSerializer):
Expand All @@ -89,6 +89,11 @@ class Meta:
fields = '__all__'
read_only_fields = ('created',)

def to_representation(self, instance):
response = super().to_representation(instance)
response["questions"] = sorted(response["questions"], key=lambda x: x["position"])
return response

@transaction.atomic
def create(self, validated_data):
questions_data = validated_data.pop('test_to_question')
Expand Down Expand Up @@ -139,3 +144,37 @@ def create(self, validated_data):
random_test.tags.add(tag_data)

return random_test





class StudentAnswerSerializer(serializers.ModelSerializer):
class Meta:
model = models.Answer
fields = ('id', 'text_answer')

class StudentQuestionSerializer(serializers.ModelSerializer):
answers = StudentAnswerSerializer(many=True)
class Meta:
model = models.Question
fields = ('id', 'text_question', 'answers')

class StudentTestQuestionSerializer(serializers.ModelSerializer):
question = StudentQuestionSerializer()
class Meta:
model = models.FixedTestQuestion
fields = ('id', 'position', 'question')

class StudentTestSerializer1(serializers.ModelSerializer):
questions = StudentTestQuestionSerializer(source='test_to_question', many=True)
created_by = serializers.HiddenField(default=serializers.CurrentUserDefault())

class Meta:
model = models.FixedTest
fields = '__all__'

def to_representation(self, instance):
response = super().to_representation(instance)
response["questions"] = sorted(response["questions"], key=lambda x: x["position"])
return response
1 change: 1 addition & 0 deletions application/tests_builder/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
urlpatterns = [
path('answers/', views.AnswerCreate.as_view()),
path('answers/<int:pk>/', views.AnswerDetail.as_view()),
path('student_fixed_test/detail/<int:pk>', views.StudentFixedTestSet.as_view({'get':'retrieve'})),
url(r'', include(router.urls)),
]
27 changes: 25 additions & 2 deletions application/tests_builder/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
from django_filters import rest_framework as django_filters
from rest_framework import viewsets, generics, filters
from django.shortcuts import get_object_or_404
from django.http import Http404
from rest_framework import permissions
from rest_framework import viewsets, generics, filters, status
from rest_framework.decorators import action
from rest_framework.response import Response

from tests_builder import models
from tests_builder import serializers
Expand All @@ -9,17 +14,35 @@ class FixedTestSet(viewsets.ModelViewSet):
queryset = models.FixedTest.objects.all()
serializer_class = serializers.FixedTestSerializer
filter_backends = (django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
# ordering_fields = ['questions__position']
# filterset_fields = ('name', 'section')
# search_fields = ('name', 'section__name', 'created_by__username')

class StudentFixedTestSet(viewsets.ReadOnlyModelViewSet):
"""Получение теста с вопросами(с текстом вопроса) и ответами (без is_correct)"""
# TODO: возможно сделать другой пермишн
permission_classes = [permissions.AllowAny]
queryset = models.FixedTest.objects.all()
serializer_class = serializers.StudentTestSerializer1

class FixedTestQuestionSet(viewsets.ModelViewSet):
queryset = models.FixedTestQuestion.objects.all()
serializer_class = serializers.FixedTestQuestionSerializer
filter_backends = (django_filters.DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
# filterset_fields = ('test',)
# search_fields = ('test__name', 'question__text_question')

def destroy(self, request, *args, **kwargs):
question = self.get_object()
test = question.test
posStart = question.position + 1
question.delete()
questionsByTest = models.FixedTestQuestion.objects.filter(test=test)
for question in questionsByTest:
if question.position >= posStart:
question.position -= 1
question.save()

return Response(status=status.HTTP_204_NO_CONTENT)

class RandomTestSet(viewsets.ModelViewSet):
queryset = models.RandomTest.objects.all()
Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ services:
- REACT_APP_API_SCHEMA=http
- REACT_APP_API_PORT=8005
- PORT=3000
# depends_on:
# - backend
depends_on:
- backend

volumes:
node-modules: