access update

feature/fix_generate_pass
Andrey 8 years ago
parent 6e71fb8da3
commit 14bf4b5f76
  1. 11
      access/models.py
  2. 1
      access/urls.py
  3. 54
      access/views.py
  4. 19
      courses/models.py
  5. 10
      courses/serializers.py
  6. 2
      courses/urls.py
  7. 35
      courses/views.py
  8. 2
      csv/access/account.csv
  9. 13907
      csv/access/progress.csv
  10. 2
      csv/access/users.csv
  11. 1
      csv/load_perm.py
  12. 34
      journals/migrations/0006_auto_20171031_1405.py
  13. 37
      journals/models.py
  14. 2
      library/models.py
  15. 1
      lms/settings.py
  16. 1
      management/__init__.py
  17. 6
      management/admin.py
  18. 7
      management/apps.py
  19. 52
      management/migrations/0001_initial.py
  20. 0
      management/migrations/__init__.py
  21. 39
      management/models.py

@ -111,8 +111,9 @@ class CustomUserManager(BaseUserManager):
"subject": 'Спасибо за регистрацию', "subject": 'Спасибо за регистрацию',
"message": ''' "message": '''
Вы были успешны зарегистрированны на портале go.skillbox.ru Вы были успешны зарегистрированны на портале go.skillbox.ru
ваш пароль %s
для подтверждения регистрации перейдите по ссылке для подтверждения регистрации перейдите по ссылке
https://go.skillbox.ru/api/v1/users/registration/?hash=''' + invite.hash, https://go.skillbox.ru/api/v1/users/registration/?hash=%s''' %(user.password, invite.hash),
"from_email": 'robo@skillbox.ru', "from_email": 'robo@skillbox.ru',
"recipient_list": [user.email], "recipient_list": [user.email],
} }
@ -122,14 +123,14 @@ class CustomUserManager(BaseUserManager):
) )
return user return user
def create_user(self, email, password, **extra_fields): def create_user(self, email, **extra_fields):
return self._create_user(email=email, password=password, **extra_fields) return self._create_user(email=email, **extra_fields)
def create_superuser(self, email, password): def create_superuser(self, email, password):
return self._create_user(email=email, password=password, is_superuser=True, is_staff=True, is_active=True) return self._create_user(email=email, password=password, is_superuser=True, is_staff=True, is_active=True)
def create_student(self, email, password, **extra_fields): def create_student(self, email, **extra_fields):
return self.create_user(email=email, password=password, role_list=['students'], is_send=True, **extra_fields) return self.create_user(email=email, role_list=['students'], is_send=True, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin): class User(AbstractBaseUser, PermissionsMixin):

@ -11,4 +11,5 @@ urlpatterns = [
url(r'change_password/$', views.ChangePasswordView.as_view()), url(r'change_password/$', views.ChangePasswordView.as_view()),
url(r'login/$', views.LoginView.as_view()), url(r'login/$', views.LoginView.as_view()),
url(r'logout/$', views.LogoutView.as_view()), url(r'logout/$', views.LogoutView.as_view()),
url(r'progress/$', views.UpdateProgress.as_view()),
] ]

@ -6,8 +6,9 @@ from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response from rest_framework.response import Response
from django.db.models import Q from django.db.models import Q
from access.models import Invite from access.models import Invite, Progress, ExtraPrivilege
from access.serializers import UserInitSerializer, UserSearchSerializer from access.serializers import UserInitSerializer, UserSearchSerializer
from courses.models import Vertex
class TeacherListView(APIView): class TeacherListView(APIView):
@ -108,10 +109,17 @@ class RegistrationView(APIView):
get_user_model().objects.get(email=request.JSON['email'].lower()) get_user_model().objects.get(email=request.JSON['email'].lower())
return Response('user already exist', status=403) return Response('user already exist', status=403)
except get_user_model().DoesNotExist: except get_user_model().DoesNotExist:
user = get_user_model().objects.create_student( password = request.JSON.get('password')
email=request.JSON['email'].lower(), if password:
password=request.JSON['password'] user = get_user_model().objects.create_student(
) email=request.JSON['email'].lower(),
password=request.JSON['password']
)
else:
user = get_user_model().objects.create_student(
email=request.JSON['email'].lower(),
)
return Response(UserInitSerializer(user).data, status=200) return Response(UserInitSerializer(user).data, status=200)
@ -149,3 +157,39 @@ class LogoutView(APIView):
if request.user.is_authenticated(): if request.user.is_authenticated():
auth.logout(request) auth.logout(request)
return Response(status=204) return Response(status=204)
class UpdateProgress(APIView):
"""
Переводит ученика на следующую стадию прохождения курса
Запрос идёт синхронно возвращает id нового объекта прогресса
"""
renderer_classes = (JSONRenderer,)
@staticmethod
def post(request):
pk = int(request.JSON.get('id'))
try:
vertex = Vertex.objects.get(id=pk)
except Vertex.DoesNotExist:
return Response("Объект не найден", status=404)
next_vertex = vertex.get_next(['task', 'tutorial'])
try:
progress = Progress.objects.get(user=request.user, course=vertex.course)
if progress.active_obj == vertex:
if next_vertex.is_more(progress.active_obj):
progress.active_obj = next_vertex
progress.save()
return Response({'id': progress.active_obj.id, 'type': progress.active_obj.content_type.model}, status=200)
except Progress.DoesNotExist:
pass
try:
privilege = ExtraPrivilege.objects.get(user=request.user, subject=vertex)
privilege.is_done = True
privilege.save()
return Response({'id': next_vertex.id, 'type': next_vertex.content_type.model}, status=200)
except ExtraPrivilege.DoesNotExist:
return Response('У вас нет прав', status=403)

@ -3,11 +3,11 @@ from django.conf import settings
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db import models from django.db import models
from django.core.exceptions import ObjectDoesNotExist
import json import json
from lms.global_decorators import transaction_decorator from lms.global_decorators import transaction_decorator
from library.models import Tags from library.models import Tags
from management.models import Comment
from storage.models import Storage from storage.models import Storage
@ -263,6 +263,23 @@ class Vertex(models.Model):
course_map = CourseMap.objects.get(course=self.course) course_map = CourseMap.objects.get(course=self.course)
return course_map.map_to_list().index(self.id) > course_map.map_to_list().index(vertex.id) return course_map.map_to_list().index(self.id) > course_map.map_to_list().index(vertex.id)
def check_vertex(self, user) -> bool:
if self.free:
return True
if not user.is_authenticated:
return False
if self.extraprivilege_set.filter(user=user).exists():
return True
try:
progress = self.course.progress_set.get(user=user)
except ObjectDoesNotExist:
return False
return progress.is_access(self)
# Модели нового API со временем всё, что выше будет выпилено # Модели нового API со временем всё, что выше будет выпилено
class Tutorial(models.Model): class Tutorial(models.Model):

@ -4,10 +4,16 @@ from courses.models import Course, Vertex, Tutorial, Topic, Task
class TutorialSerializer(serializers.ModelSerializer): class TutorialSerializer(serializers.ModelSerializer):
materials = serializers.SerializerMethodField()
class Meta: class Meta:
model = Tutorial model = Tutorial
exclude = ['id'] exclude = ['id']
@staticmethod
def get_materials(self):
return [i.original.url for i in self.materials.all()]
class TaskSerializer(serializers.ModelSerializer): class TaskSerializer(serializers.ModelSerializer):
class Meta: class Meta:
@ -82,7 +88,7 @@ class CourseTreeSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Course model = Course
fields = ['id', 'children'] fields = ['id', 'children', 'title']
@staticmethod @staticmethod
def get_children(self): def get_children(self):
@ -104,7 +110,7 @@ class CourseDetailSerializer(serializers.ModelSerializer):
@staticmethod @staticmethod
def get_direction(self): def get_direction(self):
return self.direction.title return self.get_direction_display()
@staticmethod @staticmethod
def get_teachers(self): def get_teachers(self):

@ -4,6 +4,6 @@ from 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()),
url(r'vertex/([0-9]{1,99})/$', views.VertexDetail.as_view()), url(r'vertex/([0-9]{1,99})/$', views.VertexDetail.as_view()),
url(r'tree/(?P<slug>[-\w]+)/$', views.TreeView.as_view()), url(r'tree/(?P<slug>.+)/$', views.TreeView.as_view()),
url(r'^$', views.CourseListView.as_view()), url(r'^$', views.CourseListView.as_view()),
] ]

@ -18,6 +18,7 @@ class TreeView(APIView):
return Response(status=204) return Response(status=204)
def get(self, request, slug): def get(self, request, slug):
try: try:
course = Course.objects.get(slug=slug) course = Course.objects.get(slug=slug)
except Course.DoesNotExist: except Course.DoesNotExist:
@ -63,17 +64,16 @@ class CourseListView(APIView):
status_code = 200 status_code = 200
def get(self, request): def get(self, request):
if not request.user.is_authenticated() or (not request.user.is_staff or request.GET.get('staff') == 'true'): if request.user.is_authenticated() and request.user.is_staff:
return Response([CourseListSerializer(i).data for i in Course.objects.all()], self.status_code) return Response([CourseListSerializer(i).data for i in Course.objects.all()], self.status_code)
res = [] res = []
for course in Course.objects.filter(public=True): for course in Course.objects.filter(public=True):
if course.public: course_serialize = CourseListSerializer(course).data
course_serialize = CourseListSerializer(course).data course_serialize['is_mine'] = False
course_serialize['is_mine'] = False if request.user.is_authenticated() and Progress.objects.filter(course=course, user=request.user).exists():
if request.user.is_authenticated() and Progress.objects.filter(course=course, user=request.user).exists(): course_serialize['is_mine'] = True
course_serialize['is_mine'] = True res.append(course_serialize)
res.append(course_serialize)
return Response(res, self.status_code) return Response(res, self.status_code)
@ -90,22 +90,9 @@ class VertexDetail(APIView):
except Vertex.DoesNotExist: except Vertex.DoesNotExist:
return Response("Vertex doesn't exist", status=404) return Response("Vertex doesn't exist", status=404)
res_a = Response(VertexSerializer(vertex).data, status=200) if status == 200 else Response(status=204) if not vertex.check_vertex(request.user):
if vertex.free:
return res_a
if not request.user.is_authenticated:
return Response("Access to detail of vertex, exist only for authenticated users", status=403)
if ExtraPrivilege.objects.filter(user=request.user, subject=vertex).exists():
return res_a
try:
if not Progress.objects.get(course=vertex.course, user=request.user).is_access(vertex):
return Response("permission denied", status=403)
except Progress.DoesNotExist:
return Response("permission denied", status=403) return Response("permission denied", status=403)
return res_a res = VertexSerializer(vertex).data
return Response(res, status=200) if status == 200 else Response(status=204)

@ -15665,11 +15665,11 @@ d_day,city,gender,owner,photo,phone
1985-12-17,Санкт-Петербург,0,9363,in_ava/ava_UbZDddi,+79219121509 1985-12-17,Санкт-Петербург,0,9363,in_ava/ava_UbZDddi,+79219121509
1992-02-09,Москва,0,10667,2017_2_6_14_45_851,+79168608063 1992-02-09,Москва,0,10667,2017_2_6_14_45_851,+79168608063
1991-07-30,минск,0,10724,2017_2_1_13_33_858,+375297977417 1991-07-30,минск,0,10724,2017_2_1_13_33_858,+375297977417
,Москва,0,15809,in_ava/ava_10k7npC,+7-916-192-73-11
,,0,1515,in_ava/ava_ke4HHv1, ,,0,1515,in_ava/ava_ke4HHv1,
,,0,35,in_ava/ava_KjWSNfF, ,,0,35,in_ava/ava_KjWSNfF,
,,0,5261,in_ava/ava_l3k526i,+79788042038 ,,0,5261,in_ava/ava_l3k526i,+79788042038
,,0,63,in_ava/ava_oIVmeYH,89061185850 ,,0,63,in_ava/ava_oIVmeYH,89061185850
,Москва,0,15809,in_ava/ava_10k7npC,+7-916-192-73-11
,,0,48,in_ava/ava_Uxv3fQS, ,,0,48,in_ava/ava_Uxv3fQS,
1990-06-21,Йошкар-Ола,0,93,in_ava/ava_bqpnnXv,Игоревич 1990-06-21,Йошкар-Ола,0,93,in_ava/ava_bqpnnXv,Игоревич
,,0,691,in_ava/ava_mXsosby, ,,0,691,in_ava/ava_mXsosby,

Can't render this file because it is too large.

File diff suppressed because it is too large Load Diff

@ -15666,11 +15666,11 @@ id,email,first_name,last_name,last_login,role_list,is_superuser,date_joined,is_s
9363,4pavlov@list.ru,Никита,Павлов,2017-05-01 14:51:36.878400,['students'],False,2017-01-27 13:06:01.032972,False,True,False,pbkdf2_sha256$24000$Ebgngk1B60cL$AgAcrl2hVliVLlVA01SLgYtRmwRpL56kOhjiAvUjutU= 9363,4pavlov@list.ru,Никита,Павлов,2017-05-01 14:51:36.878400,['students'],False,2017-01-27 13:06:01.032972,False,True,False,pbkdf2_sha256$24000$Ebgngk1B60cL$AgAcrl2hVliVLlVA01SLgYtRmwRpL56kOhjiAvUjutU=
10667,mad-hatter613@yandex.ru,Татьяна ,Тихонова ,2017-08-02 17:23:59.817791,['students'],False,2017-03-03 11:53:39.739851,False,True,False,pbkdf2_sha256$24000$Jc4doAyshxRk$VBqyvAy5PgrXY6Cey+/OGvPIEYLrygvck426snYGPZ8= 10667,mad-hatter613@yandex.ru,Татьяна ,Тихонова ,2017-08-02 17:23:59.817791,['students'],False,2017-03-03 11:53:39.739851,False,True,False,pbkdf2_sha256$24000$Jc4doAyshxRk$VBqyvAy5PgrXY6Cey+/OGvPIEYLrygvck426snYGPZ8=
10724,7977417@gmail.com,яна,сыревич,2017-07-27 13:55:21.776902,['students'],False,2017-03-06 13:09:37.538459,False,True,False,pbkdf2_sha256$24000$8eI8cRQw0bhE$XzePRiOYa2cHDoYN9p2TkmjmmHkOs6/607UMoOP3jyo= 10724,7977417@gmail.com,яна,сыревич,2017-07-27 13:55:21.776902,['students'],False,2017-03-06 13:09:37.538459,False,True,False,pbkdf2_sha256$24000$8eI8cRQw0bhE$XzePRiOYa2cHDoYN9p2TkmjmmHkOs6/607UMoOP3jyo=
15809,andrey.korolev@skillbox.ru,Андрей,Королёв,2017-10-06 11:09:50.887731,[],True,2017-08-24 18:26:40,True,True,False,pbkdf2_sha256$24000$nVAKvm1WWWXa$mj0hx2m4G6yNtcZnkbdcBDgF+r/ZfbXnbEQYScTGK5A=
1515,heiaheia25+5@gmail.com,,,2016-04-23 21:13:57.791906,['students'],False,2016-04-23 21:13:57.791913,False,False,False,pbkdf2_sha256$24000$KeysH3LMA3ze$EHrAmAfGynjMZ6zh7nul7Q2ownc2D6+W/DWy6od/tn0= 1515,heiaheia25+5@gmail.com,,,2016-04-23 21:13:57.791906,['students'],False,2016-04-23 21:13:57.791913,False,False,False,pbkdf2_sha256$24000$KeysH3LMA3ze$EHrAmAfGynjMZ6zh7nul7Q2ownc2D6+W/DWy6od/tn0=
35,trubnikovvadim@gmail.com,,,2016-04-21 21:35:25.055910,['students'],False,2015-11-11 14:56:04.465000,False,False,False,pbkdf2_sha256$20000$3g1fr3aPCQXp$xV8WSPM1SGhfpvtf4eEAOwS6LvEnozZJ6K4kvC49has= 35,trubnikovvadim@gmail.com,,,2016-04-21 21:35:25.055910,['students'],False,2015-11-11 14:56:04.465000,False,False,False,pbkdf2_sha256$20000$3g1fr3aPCQXp$xV8WSPM1SGhfpvtf4eEAOwS6LvEnozZJ6K4kvC49has=
5261,formik52@gmail.com,,,2016-10-04 10:02:19.163373,['students'],False,2016-10-04 10:02:19.163378,False,False,False,!gftsRlQ3rA9ukdS6Ky7QDY9HR2M3YnIhrOvOozIz 5261,formik52@gmail.com,,,2016-10-04 10:02:19.163373,['students'],False,2016-10-04 10:02:19.163378,False,False,False,!gftsRlQ3rA9ukdS6Ky7QDY9HR2M3YnIhrOvOozIz
63,eduard.s.1984@gmail.com,Эдуард,Самигуллин,2016-04-21 21:35:25.055910,['students'],False,2015-11-28 12:07:44.699000,False,True,False,pbkdf2_sha256$20000$VsDI2yXXtna2$eb43XhgxRjQ0V+Vt6AYeBuDpeKkiAOVCuWNX2GU5+Ek= 63,eduard.s.1984@gmail.com,Эдуард,Самигуллин,2016-04-21 21:35:25.055910,['students'],False,2015-11-28 12:07:44.699000,False,True,False,pbkdf2_sha256$20000$VsDI2yXXtna2$eb43XhgxRjQ0V+Vt6AYeBuDpeKkiAOVCuWNX2GU5+Ek=
15809,andrey.korolev@skillbox.ru,Андрей,Королёв,2017-10-27 12:17:02.920485,[],True,2017-08-24 18:26:40,True,True,False,pbkdf2_sha256$24000$nVAKvm1WWWXa$mj0hx2m4G6yNtcZnkbdcBDgF+r/ZfbXnbEQYScTGK5A=
48,pro100lehsa@yandex.ru,,,2016-04-21 21:35:25.055910,['students'],False,2015-11-19 19:23:23.427000,False,False,False,pbkdf2_sha256$20000$XWrcnijH1x8N$d8zfkqiR/+UtnyKsf2VLp+Vt8RsULw9eEy64cydHGTM= 48,pro100lehsa@yandex.ru,,,2016-04-21 21:35:25.055910,['students'],False,2015-11-19 19:23:23.427000,False,False,False,pbkdf2_sha256$20000$XWrcnijH1x8N$d8zfkqiR/+UtnyKsf2VLp+Vt8RsULw9eEy64cydHGTM=
93,boltyn4ik@gmail.com,Павел,Фейгин,2016-04-21 21:35:25.055910,['students'],False,2015-12-11 11:23:35.830000,False,True,False,pbkdf2_sha256$20000$tzxhKyjW1x1E$/tuSjAaiE49PqMVHR64wiLQA2iP/CiGUrF1HPY4bH/8= 93,boltyn4ik@gmail.com,Павел,Фейгин,2016-04-21 21:35:25.055910,['students'],False,2015-12-11 11:23:35.830000,False,True,False,pbkdf2_sha256$20000$tzxhKyjW1x1E$/tuSjAaiE49PqMVHR64wiLQA2iP/CiGUrF1HPY4bH/8=
691,belocerkovecden@mail.ru,,,2016-04-21 21:35:25.055910,['students'],False,2016-03-24 15:02:20.761634,False,False,False,!UeR9h1bWgWi3Wr0RJXNfiTACMF7Xkff6T4aSNey6 691,belocerkovecden@mail.ru,,,2016-04-21 21:35:25.055910,['students'],False,2016-03-24 15:02:20.761634,False,False,False,!UeR9h1bWgWi3Wr0RJXNfiTACMF7Xkff6T4aSNey6

Can't render this file because it is too large.

@ -9,6 +9,7 @@ from access.models import Progress
from courses.models import Vertex, Course from courses.models import Vertex, Course
if __name__ == '__main__': if __name__ == '__main__':
Progress.objects.all().delete()
with open('./access/progress.csv') as progress_csv: with open('./access/progress.csv') as progress_csv:
progress_reader = csv.DictReader(progress_csv) progress_reader = csv.DictReader(progress_csv)
for row in progress_reader: for row in progress_reader:

@ -0,0 +1,34 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-31 14:05
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('journals', '0005_auto_20171024_1352'),
]
operations = [
migrations.RemoveField(
model_name='thread',
name='recurse_step',
),
migrations.AddField(
model_name='journal',
name='children',
field=models.ManyToManyField(blank=True, to='journals.Journal'),
),
migrations.AddField(
model_name='thread',
name='is_recurse',
field=models.BooleanField(default=False, verbose_name='Поле аптимизации поиска'),
),
migrations.AlterField(
model_name='journal',
name='action_type',
field=models.SmallIntegerField(choices=[(0, 'try'), (1, 'yes'), (2, 'no'), (3, 'favorite'), (4, 'watch'), (5, 'like'), (6, 'dislike'), (7, 'comment'), (8, 'start'), (9, 'end'), (10, 'create'), (11, 'update'), (12, 'delete')]),
),
]

@ -8,7 +8,6 @@ from django.contrib.contenttypes.models import ContentType
from django.db import models from django.db import models
from courses.models import Achievements, Course, CourseMap, Diploma from courses.models import Achievements, Course, CourseMap, Diploma
from management.models import Comment
from finance.models import Bill from finance.models import Bill
ACTION_CHOICES = ( ACTION_CHOICES = (
@ -17,11 +16,14 @@ ACTION_CHOICES = (
(2, 'no'), (2, 'no'),
(3, 'favorite'), (3, 'favorite'),
(4, 'watch'), (4, 'watch'),
(5, 'start'), (5, 'like'),
(6, 'end'), (6, 'dislike'),
(7, 'create'), (7, 'comment'),
(8, 'update'), (8, 'start'),
(9, 'delete'), (9, 'end'),
(10, 'create'),
(11, 'update'),
(12, 'delete'),
) )
@ -37,6 +39,7 @@ class Journal(models.Model):
content_object = GenericForeignKey('content_type', 'object_id') content_object = GenericForeignKey('content_type', 'object_id')
action_type = models.SmallIntegerField(choices=ACTION_CHOICES) action_type = models.SmallIntegerField(choices=ACTION_CHOICES)
date = models.DateTimeField(auto_now=True) date = models.DateTimeField(auto_now=True)
children = models.ManyToManyField(to='self', blank=True, symmetrical=False)
def __str__(self): def __str__(self):
return '%d Пользователь %s %s %s' % (self.id, self.user.email, self.get_action_type_display(), self.thread.key) return '%d Пользователь %s %s %s' % (self.id, self.user.email, self.get_action_type_display(), self.thread.key)
@ -45,8 +48,8 @@ class Journal(models.Model):
class Thread(models.Model): class Thread(models.Model):
key = models.CharField(max_length=200) key = models.CharField(max_length=200)
text = models.TextField(default='', verbose_name=u'Описание треда') text = models.TextField(default='', verbose_name=u'Описание треда')
is_staff = models.BooleanField(default=False, verbose_name=u'Админская ли табличка') is_staff = models.BooleanField(default=False, verbose_name='Админская ли табличка')
recurse_step = models.SmallIntegerField(default=0, verbose_name=u'Поле аптимизации поиска') is_recurse = models.BooleanField(default=False, verbose_name='Поле аптимизации поиска')
subscribers = models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name='Подписчики', blank=True) subscribers = models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name='Подписчики', blank=True)
groups = models.ManyToManyField(to=Group, verbose_name='Группы подписчиков', blank=True) groups = models.ManyToManyField(to=Group, verbose_name='Группы подписчиков', blank=True)
check_subscribe = models.BooleanField(default=True, verbose_name='Проверять ли подписки') check_subscribe = models.BooleanField(default=True, verbose_name='Проверять ли подписки')
@ -61,31 +64,29 @@ class Thread(models.Model):
def check_perm(self, user): def check_perm(self, user):
return (user in self.subscribers.all()) or bool(sum([int(i.check_perm(user)) for i in self.parent.all()])) return (user in self.subscribers.all()) or bool(sum([int(i.check_perm(user)) for i in self.parent.all()]))
def child_thread_count(self, step=None): def child_thread_count(self):
step = self.recurse_step if step is None else step
if step == 0: if self.is_recurse:
return self.thread_set.count() return self.thread_set.count()
return sum([i.child_thread_count(step-1) for i in self.thread_set.all()]) return sum([i.child_thread_count() for i in self.thread_set.all()])
def journals_count(self, step=None): def journals_count(self):
step = self.recurse_step if step is None else step children = list(self.get_children())
children = list(self.get_children(step))
children.append(self) children.append(self)
return Journal.objects.filter(thread__in=children).count() return Journal.objects.filter(thread__in=children).count()
def get_children(self, step): def get_children(self):
children = self.thread_set.filter(is_staff=False) children = self.thread_set.filter(is_staff=False)
if step == 0: if self.is_recurse:
list(children).append(self) list(children).append(self)
return children return children
res = [self] res = [self]
for child in children: for child in children:
res += child.get_children(step=step-1) res += child.get_children()
return res return res

@ -2,8 +2,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import datetime import datetime
from django.db import models from django.db import models
from management.models import Comment
class ArticleSection(models.Model): class ArticleSection(models.Model):
name = models.CharField(verbose_name=u'Раздел', max_length=255) name = models.CharField(verbose_name=u'Раздел', max_length=255)

@ -91,7 +91,6 @@ INSTALLED_APPS = [
'access', 'access',
'courses', 'courses',
'storage', 'storage',
'management',
'finance', 'finance',
'journals', 'journals',
'library', 'library',

@ -1 +0,0 @@
default_app_config = "management.apps.ManagementAppConfig"

@ -1,6 +0,0 @@
from django.contrib import admin
from management.models import Comment, Like
admin.site.register(Comment)
admin.site.register(Like)

@ -1,7 +0,0 @@
# -*- coding: utf-8 -*-
from django.apps import AppConfig
class ManagementAppConfig(AppConfig):
name = "management"
verbose_name = "Менеджмент"

@ -1,52 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-18 14:37
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 = [
('contenttypes', '0002_remove_content_type_name'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('storage', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Comment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('closed', models.BooleanField(default=False, editable=False, verbose_name='Закрыт')),
('text', models.TextField(default='', verbose_name='Текст')),
('object_id', models.PositiveIntegerField()),
('children', models.ManyToManyField(blank=True, to='management.Comment')),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
('files', models.ManyToManyField(blank=True, editable=False, to='storage.Storage', verbose_name='Прикрепленые файлы')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Автор')),
],
options={
'verbose_name': 'Комментарий',
'verbose_name_plural': 'Комментарии',
},
),
migrations.CreateModel(
name='Like',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_positive', models.BooleanField(default=True)),
('object_id', models.PositiveIntegerField()),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Автор')),
],
options={
'verbose_name': 'Лайк-дизлайк',
'verbose_name_plural': 'Лайки-дизлайки',
},
),
]

@ -1,39 +0,0 @@
# coding=utf-8
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.conf import settings
from storage.models import Storage
class Comment(models.Model):
closed = models.BooleanField(verbose_name='Закрыт', default=False, editable=False)
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name=u'Автор')
text = models.TextField(verbose_name='Текст', default='')
files = models.ManyToManyField(Storage, verbose_name='Прикрепленые файлы', blank=True, editable=False)
children = models.ManyToManyField(to='self', blank=True, symmetrical=False)
content_type = models.ForeignKey(to=ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
def __str__(self):
return str(self.id)
class Meta:
verbose_name = 'Комментарий'
verbose_name_plural = 'Комментарии'
class Like(models.Model):
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name=u'Автор')
is_positive = models.BooleanField(default=True)
content_type = models.ForeignKey(to=ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
def __str__(self):
return str(self.id) + ': ' + 'Лайк' if self.is_positive else 'Дизлайк'
class Meta:
verbose_name = 'Лайк-дизлайк'
verbose_name_plural = 'Лайки-дизлайки'
Loading…
Cancel
Save