parent
693895a90a
commit
e97c343995
41 changed files with 100 additions and 972 deletions
@ -1,61 +0,0 @@ |
||||
# -*- 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 = [ |
||||
('access', '0001_initial'), |
||||
('auth', '0008_alter_user_username_max_length'), |
||||
('maps', '0001_initial'), |
||||
('courses', '0002_auto_20171128_1518'), |
||||
] |
||||
|
||||
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='maps.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='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,27 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by Django 1.11.6 on 2017-11-29 16:39 |
||||
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): |
||||
|
||||
dependencies = [ |
||||
('access', '0002_auto_20171128_1518'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AlterField( |
||||
model_name='progress', |
||||
name='course', |
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='Курс'), |
||||
), |
||||
migrations.AlterField( |
||||
model_name='progress', |
||||
name='user', |
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент'), |
||||
), |
||||
] |
||||
@ -1,46 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by Django 1.11.6 on 2017-12-11 14: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): |
||||
|
||||
dependencies = [ |
||||
('access', '0003_auto_20171129_1639'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.CreateModel( |
||||
name='Invite', |
||||
fields=[ |
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
('hash', models.CharField(max_length=15, unique=True, verbose_name='Уникальный код')), |
||||
('date', models.DateTimeField(blank=True, null=True, verbose_name='Дата сгорания приглошения')), |
||||
], |
||||
options={ |
||||
'verbose_name': 'Приглошение в систему', |
||||
'verbose_name_plural': 'Приглошения в систему', |
||||
}, |
||||
), |
||||
migrations.CreateModel( |
||||
name='ResetPassword', |
||||
fields=[ |
||||
('invite_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='access.Invite')), |
||||
('password', models.CharField(max_length=63, verbose_name='Новый пароль, если есть')), |
||||
], |
||||
options={ |
||||
'verbose_name': 'Запрос на сброс пароля', |
||||
'verbose_name_plural': 'Запросы на сброс пароля', |
||||
}, |
||||
bases=('access.invite',), |
||||
), |
||||
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='Кому приглошение'), |
||||
), |
||||
] |
||||
@ -1,56 +0,0 @@ |
||||
# -*- 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), |
||||
), |
||||
] |
||||
@ -1,24 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by Django 1.11.6 on 2017-12-05 18:21 |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('achievements', '0002_auto_20171128_1518'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.RemoveField( |
||||
model_name='achievements', |
||||
name='course', |
||||
), |
||||
migrations.AlterField( |
||||
model_name='achievements', |
||||
name='icon', |
||||
field=models.ImageField(blank=True, null=True, upload_to='achives', verbose_name='Отображение достижения'), |
||||
), |
||||
] |
||||
@ -1,26 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by Django 1.11.6 on 2017-12-05 18:23 |
||||
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), |
||||
('achievements', '0003_auto_20171205_1821'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.RemoveField( |
||||
model_name='achievements', |
||||
name='user', |
||||
), |
||||
migrations.AddField( |
||||
model_name='achievements', |
||||
name='user', |
||||
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL), |
||||
), |
||||
] |
||||
@ -1,25 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by Django 1.11.6 on 2017-12-05 18:33 |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import migrations |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('achievements', '0004_auto_20171205_1823'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.RenameField( |
||||
model_name='achievements', |
||||
old_name='icon', |
||||
new_name='img', |
||||
), |
||||
migrations.RenameField( |
||||
model_name='diploma', |
||||
old_name='icon', |
||||
new_name='img', |
||||
), |
||||
] |
||||
@ -1,20 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by Django 1.11.6 on 2017-12-05 18:36 |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import migrations |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('achievements', '0005_auto_20171205_1833'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.RenameField( |
||||
model_name='achievements', |
||||
old_name='user', |
||||
new_name='users', |
||||
), |
||||
] |
||||
@ -1,20 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by Django 1.11.6 on 2017-12-06 12:44 |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('achievements', '0006_auto_20171205_1836'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AddField( |
||||
model_name='achievements', |
||||
name='text', |
||||
field=models.CharField(default='', max_length=255, verbose_name='Текст достижения'), |
||||
), |
||||
] |
||||
@ -1,31 +0,0 @@ |
||||
# -*- 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 = [ |
||||
('courses', '0001_initial'), |
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), |
||||
('maps', '0001_initial'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AddField( |
||||
model_name='course', |
||||
name='route', |
||||
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='maps.CourseRoute', verbose_name='Порядок прохождения по умолчанию'), |
||||
), |
||||
migrations.AddField( |
||||
model_name='course', |
||||
name='teachers', |
||||
field=models.ManyToManyField(related_name='course_teachers', to=settings.AUTH_USER_MODEL, verbose_name='Преподаватели'), |
||||
), |
||||
] |
||||
@ -1,19 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by Django 1.11.6 on 2017-12-05 11:23 |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import migrations |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('courses', '0002_auto_20171128_1518'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.RemoveField( |
||||
model_name='course', |
||||
name='mentors', |
||||
), |
||||
] |
||||
@ -1 +0,0 @@ |
||||
default_app_config = "journals.apps.JournalsAppConfig" |
||||
@ -1,5 +0,0 @@ |
||||
from django.contrib import admin |
||||
from journals.models import Thread, Journal |
||||
|
||||
admin.site.register(Thread) |
||||
admin.site.register(Journal) |
||||
@ -1,7 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
from django.apps import AppConfig |
||||
|
||||
|
||||
class JournalsAppConfig(AppConfig): |
||||
name = "journals" |
||||
verbose_name = "Журналы" |
||||
@ -1,75 +0,0 @@ |
||||
import os, sys, django |
||||
|
||||
from django.contrib.auth import get_user_model |
||||
|
||||
sys.path.append("../") |
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings") |
||||
django.setup() |
||||
|
||||
|
||||
from journals.models import Thread |
||||
from django.contrib.auth.models import Group |
||||
from lms.global_decorators import transaction_decorator |
||||
|
||||
|
||||
@transaction_decorator |
||||
def main_threads(): |
||||
Thread.objects.all().delete() |
||||
|
||||
admin_thread = Thread.objects.create( |
||||
key='Admin', |
||||
text='Тред для админов, сюда падают все журналируемые сообщения в системе, кроме личных переписок', |
||||
is_staff=True, |
||||
x=500, |
||||
y=75, |
||||
) |
||||
|
||||
admin_thread.groups.add(Group.objects.get(name='admin')) |
||||
|
||||
management_thread = Thread.objects.create( |
||||
key='Project_management', |
||||
text='Тред для проджект-менеджеров, сюда падает статистика разного рода', |
||||
is_staff=True, |
||||
) |
||||
|
||||
management_thread.groups.add(Group.objects.get(name='project_managers')) |
||||
management_thread.parent.add(admin_thread) |
||||
|
||||
support_thread = Thread.objects.create( |
||||
key='Support', |
||||
text='Тред сапортов, занимаются поддержкой клиента', |
||||
is_staff=True, |
||||
y=500, |
||||
) |
||||
|
||||
support_thread.groups.add(Group.objects.get(name='supports')) |
||||
support_thread.parent.add(management_thread) |
||||
|
||||
lead_managers = Thread.objects.create( |
||||
key='Sale_lead', |
||||
text='Тред лидов, сейлзов', |
||||
is_staff=True, |
||||
x=700, |
||||
) |
||||
|
||||
lead_managers.groups.add(Group.objects.get(name='lead_managers')) |
||||
lead_managers.parent.add(admin_thread) |
||||
|
||||
managers = Thread.objects.create( |
||||
key='Sale', |
||||
text='Тред сейлзов', |
||||
is_staff=True, |
||||
is_recurse=True, |
||||
x=700, |
||||
y=500, |
||||
) |
||||
|
||||
managers.groups.add(Group.objects.get(name='managers')) |
||||
managers.parent.add(lead_managers) |
||||
|
||||
for user in get_user_model().objects.all(): |
||||
Thread.objects.get_or_create(key="""user_%s""" % user.id) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
main_threads() |
||||
@ -1,60 +0,0 @@ |
||||
# -*- 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 = [ |
||||
('storage', '0001_initial'), |
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), |
||||
('auth', '0008_alter_user_username_max_length'), |
||||
('contenttypes', '0002_remove_content_type_name'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.CreateModel( |
||||
name='Journal', |
||||
fields=[ |
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
('extra_data', models.TextField(blank=True, null=True)), |
||||
('object_id', models.PositiveIntegerField()), |
||||
('action_type', models.CharField(choices=[('try', 'попытался сдать'), ('yes', 'одобрил'), ('no', 'отклонил'), ('favorite', 'добавил в избранное'), ('watch', 'просмотрел'), ('like', 'лайкнул'), ('dislike', 'дизлайкнул'), ('comment', 'оставил комментарий'), ('start', 'начал прохождение'), ('end', 'закончил прохождение'), ('create', 'создал'), ('update', 'обновил'), ('delete', 'удалил')], max_length=31)), |
||||
('date', models.DateTimeField(auto_now_add=True)), |
||||
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), |
||||
('files', models.ManyToManyField(blank=True, to='storage.Storage')), |
||||
], |
||||
), |
||||
migrations.CreateModel( |
||||
name='Thread', |
||||
fields=[ |
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
||||
('key', models.CharField(editable=False, max_length=200, unique=True)), |
||||
('text', models.TextField(default='', verbose_name='Описание треда')), |
||||
('is_staff', models.BooleanField(default=False, verbose_name='Админская ли табличка')), |
||||
('is_recurse', models.BooleanField(default=False, verbose_name='Поле аптимизации поиска')), |
||||
('check_subscribe', models.BooleanField(default=True, verbose_name='Проверять ли подписки')), |
||||
('x', models.SmallIntegerField(default=300)), |
||||
('y', models.SmallIntegerField(default=300)), |
||||
('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Группы подписчиков')), |
||||
('parent', models.ManyToManyField(blank=True, to='journals.Thread')), |
||||
('subscribers', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Подписчики')), |
||||
], |
||||
), |
||||
migrations.AddField( |
||||
model_name='journal', |
||||
name='thread', |
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='journals.Thread', verbose_name='Тред'), |
||||
), |
||||
migrations.AddField( |
||||
model_name='journal', |
||||
name='user', |
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Инициатор действия или тот, на ком действие инициируется'), |
||||
), |
||||
] |
||||
@ -1,100 +0,0 @@ |
||||
# coding=utf-8 |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.conf import settings |
||||
from django.contrib.auth.models import Group |
||||
from django.contrib.contenttypes.fields import GenericForeignKey |
||||
from django.contrib.contenttypes.models import ContentType |
||||
from django.db import models |
||||
from django.db import connection |
||||
|
||||
from courses.models import Course |
||||
from finance.models import Bill |
||||
from storage.models import Storage |
||||
|
||||
ACTION_CHOICES = ( |
||||
('try', 'попытался сдать'), |
||||
('yes', 'одобрил'), |
||||
('no', 'отклонил'), |
||||
('favorite', 'добавил в избранное'), |
||||
('watch', 'просмотрел'), |
||||
('like', 'лайкнул'), |
||||
('dislike', 'дизлайкнул'), |
||||
('comment', 'оставил комментарий'), |
||||
('start', 'начал прохождение'), |
||||
('end', 'закончил прохождение'), |
||||
('create', 'создал'), |
||||
('update', 'обновил'), |
||||
('delete', 'удалил'), |
||||
) |
||||
|
||||
|
||||
class Journal(models.Model): |
||||
thread = models.ForeignKey(to='Thread', verbose_name='Тред') |
||||
user = models.ForeignKey( |
||||
to=settings.AUTH_USER_MODEL, verbose_name='Инициатор действия или тот, на ком действие инициируется' |
||||
) |
||||
content_type = models.ForeignKey(to=ContentType) |
||||
extra_data = models.TextField(null=True, blank=True) |
||||
object_id = models.PositiveIntegerField() |
||||
content_object = GenericForeignKey('content_type', 'object_id') |
||||
action_type = models.CharField(max_length=31, choices=ACTION_CHOICES) |
||||
date = models.DateTimeField(auto_now_add=True) |
||||
files = models.ManyToManyField(to=Storage, blank=True) |
||||
|
||||
def __str__(self): |
||||
return '%d Пользователь %s %s %s' % (self.id, self.user.email, self.get_action_type_display(), self.thread.key) |
||||
|
||||
|
||||
class Thread(models.Model): |
||||
key = models.CharField(max_length=200, unique=True, editable=False) |
||||
text = models.TextField(default='', verbose_name='Описание треда') |
||||
is_staff = models.BooleanField(default=False, verbose_name='Админская ли табличка') |
||||
is_recurse = models.BooleanField(default=False, verbose_name='Поле аптимизации поиска') |
||||
subscribers = models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name='Подписчики', blank=True) |
||||
groups = models.ManyToManyField(to=Group, verbose_name='Группы подписчиков', blank=True) |
||||
check_subscribe = models.BooleanField(default=True, verbose_name='Проверять ли подписки') |
||||
parent = models.ManyToManyField(to='self', blank=True, symmetrical=False) |
||||
x = models.SmallIntegerField(default=300) |
||||
y = models.SmallIntegerField(default=300) |
||||
|
||||
def check_status(self): |
||||
# Определяет статус треда если такой есть. |
||||
# Возможно, костыль. |
||||
res = None |
||||
for i in self.journal_set.all(): |
||||
if i.action_type in ['try', 'yes', 'no']: |
||||
res = i.action_type |
||||
return res |
||||
|
||||
def check_perm(self, user): |
||||
res = user in self.subscribers.all() |
||||
for i in self.groups.all(): |
||||
res = res or (i in user.groups.all()) |
||||
return res or sum([int(i.check_perm(user)) for i in self.parent.all()]) |
||||
|
||||
def child_thread_count(self): |
||||
# cursor = connection.cursor() |
||||
# if self.is_recurse: |
||||
# cursor.execute(""" |
||||
# WITH RECURSIVE temp1 (to_thread_id, from_thread_id) AS ( |
||||
# SELECT T1.to_thread_id, T1.from_thread_id |
||||
# FROM journals_thread_parent T1 |
||||
# WHERE to_thread_id = %s |
||||
# UNION |
||||
# SELECT T2.to_thread_id, T2.from_thread_id |
||||
# FROM journals_thread_parent T2 |
||||
# INNER JOIN temp1 ON(T2.from_thread_id = temp1.to_thread_id) |
||||
# ) |
||||
# SELECT COUNT(*) FROM temp1 |
||||
# """, [self.id]) |
||||
# count = cursor.fetchone() |
||||
# return int(count[0]) |
||||
|
||||
return self.thread_set.count() |
||||
|
||||
def journals_count(self): |
||||
return self.journal_set.count() |
||||
|
||||
def __str__(self): |
||||
return self.key |
||||
@ -1,68 +0,0 @@ |
||||
from rest_framework import serializers |
||||
|
||||
from journals.models import Thread, Journal |
||||
from storage.serializers import StorageSerializer |
||||
|
||||
|
||||
class JournalSerializer(serializers.ModelSerializer): |
||||
user = serializers.SerializerMethodField() |
||||
files = serializers.SerializerMethodField() |
||||
label = serializers.SerializerMethodField() |
||||
|
||||
class Meta: |
||||
model = Journal |
||||
fields = ('label', 'date', 'user', 'files', 'action_type', 'object_id', ) |
||||
|
||||
@staticmethod |
||||
def get_user(self): |
||||
return self.user.get_full_name() |
||||
|
||||
@staticmethod |
||||
def get_label(self): |
||||
return self.extra_data if self.extra_data else """%s %s"""\ |
||||
% (self.user.get_full_name(), self.get_action_type_display()) |
||||
|
||||
@staticmethod |
||||
def get_files(self): |
||||
return [StorageSerializer(i).data for i in self.files.all()] |
||||
|
||||
|
||||
class ThreadDetailSerializer(serializers.ModelSerializer): |
||||
journals = serializers.SerializerMethodField() |
||||
children = serializers.SerializerMethodField() |
||||
|
||||
class Meta: |
||||
model = Thread |
||||
fields = ('journals', 'id', 'text', 'children', 'key',) |
||||
|
||||
@staticmethod |
||||
def get_journals(self): |
||||
return [JournalSerializer(i).data for i in self.journal_set.all()] |
||||
|
||||
@staticmethod |
||||
def get_children(self): |
||||
return [ThreadDetailSerializer(i).data for i in self.thread_set.all()] |
||||
|
||||
|
||||
class ThreadAdminSerializer(serializers.ModelSerializer): |
||||
count_children = serializers.SerializerMethodField() |
||||
count_journals = serializers.SerializerMethodField() |
||||
|
||||
class Meta: |
||||
model = Thread |
||||
exclude = ('is_staff', ) |
||||
|
||||
@staticmethod |
||||
def get_count_children(self): |
||||
return self.child_thread_count() |
||||
|
||||
@staticmethod |
||||
def get_count_journals(self): |
||||
return self.journals_count() |
||||
|
||||
|
||||
class ThreadUserSerializer(serializers.ModelSerializer): |
||||
|
||||
class Meta: |
||||
model = Thread |
||||
fields = ('id', 'text') |
||||
@ -1,9 +0,0 @@ |
||||
from django.conf.urls import url |
||||
from journals import views as views |
||||
|
||||
urlpatterns = [ |
||||
url(r'thread/$', views.ThreadAdminListView.as_view()), |
||||
url(r'pay-stat/([0-9]{1,99})/$', views.get_pay_stat), |
||||
url(r'thread/(?P<key>[-\w]+)/$', views.ThreadDetailView.as_view()), |
||||
url(r'journal/$', views.JournalCreateView.as_view()), |
||||
] |
||||
@ -1,131 +0,0 @@ |
||||
from django.contrib.auth import get_user_model |
||||
from django.contrib.contenttypes.models import ContentType |
||||
from rest_framework.permissions import IsAuthenticated |
||||
from rest_framework.views import APIView |
||||
from rest_framework.renderers import JSONRenderer |
||||
from rest_framework.response import Response |
||||
import csv |
||||
from django.http import HttpResponse, HttpResponseForbidden |
||||
|
||||
from access.models.other import Progress |
||||
from journals.models import Thread, Journal |
||||
from journals.serilizers import ThreadDetailSerializer, ThreadAdminSerializer, JournalSerializer |
||||
from lms.global_decorators import transaction_decorator |
||||
from lms.tools import decode_base64 |
||||
from storage.models import Storage |
||||
|
||||
|
||||
class ThreadAdminListView(APIView): |
||||
renderer_classes = (JSONRenderer,) |
||||
status_code = 200 |
||||
|
||||
def get(self, request): |
||||
return Response( |
||||
[ThreadAdminSerializer(thread).data for thread in Thread.objects.filter(is_staff=True)], |
||||
self.status_code, |
||||
) |
||||
|
||||
|
||||
class ThreadDetailView(APIView): |
||||
renderer_classes = (JSONRenderer,) |
||||
permission_classes = () |
||||
status_code = 200 |
||||
|
||||
def post(self, request, key): |
||||
try: |
||||
thread = Thread.objects.get(key=key) |
||||
thread.text = request.JSON.get('text', thread.text) |
||||
thread.key = request.JSON.get('key', thread.key) |
||||
thread.x = request.JSON.get('x', thread.x) |
||||
thread.y = request.JSON.get('y', thread.y) |
||||
thread.save() |
||||
return Response(ThreadAdminSerializer(thread).data, self.status_code, ) |
||||
except Thread.DoesNotExist: |
||||
return Response("Thread doesn't exist.", self.status_code, ) |
||||
|
||||
@staticmethod |
||||
def get(request, key): |
||||
try: |
||||
thread = Thread.objects.get(key=key) |
||||
if thread.check_perm(request.user): |
||||
return Response(ThreadDetailSerializer(thread).data, status=200) |
||||
return Response("permission denied", status=403) |
||||
|
||||
except Thread.DoesNotExist: |
||||
return Response("Thread not found", status=404) |
||||
|
||||
|
||||
def get_pay_stat(request, pk): |
||||
if not request.user.is_authenticated and (request.user.groups.filter(name="supports") or request.user.is_superuser): |
||||
return HttpResponseForbidden() |
||||
|
||||
date_from = request.GET.get('from', None) |
||||
date_to = request.GET.get('to', None) |
||||
|
||||
file_name = "teacher_%s" % pk |
||||
file_name = file_name + "__from_%s" % date_from if date_from else file_name |
||||
file_name = file_name + "__to_%s" % date_to if date_to else file_name |
||||
|
||||
journals = Journal.objects.filter(user_id=pk, action_type="yes") |
||||
journals = journals.filter(date__lt=date_to) if date_to else journals |
||||
journals = journals.filter(date__gte=date_from) if date_from else journals |
||||
|
||||
response = HttpResponse(content_type='text/csv') |
||||
response['Content-Disposition'] = 'attachment; filename="%s"' % file_name |
||||
|
||||
writer = csv.writer(response) |
||||
writer.writerow(['student_email', 'full_name', 'course', 'theme', 'task_id', 'date']) |
||||
|
||||
for i in journals.order_by('-date'): |
||||
student = get_user_model().objects.get(id=i.thread.key.split('user_')[1].split('__vertex')[0]) |
||||
writer.writerow([ |
||||
student.email, |
||||
student.get_full_name(), |
||||
i.content_object.course.title, |
||||
i.content_object.vertex_set.all()[0].title, |
||||
i.content_object.id, |
||||
i.date, |
||||
]) |
||||
|
||||
return response |
||||
|
||||
|
||||
class JournalCreateView(APIView): |
||||
renderer_classes = (JSONRenderer,) |
||||
permission_classes = (IsAuthenticated,) |
||||
status_code = 200 |
||||
|
||||
@transaction_decorator |
||||
def post(self, request): |
||||
pk = request.JSON.get('thread_id', None) |
||||
try: |
||||
thread = Thread.objects.get(id=pk) |
||||
if request.user.is_authenticated and thread.check_perm(request.user): |
||||
action_type = request.JSON.get('action_type', None) |
||||
extra_data = request.JSON.get('extra_data', None) |
||||
object_id = request.JSON.get('object_id', None) |
||||
content_type__model = request.JSON.get('content_type__model', None) |
||||
content_type__app_label = request.JSON.get('content_type__app_label', None) |
||||
content_type = ContentType.objects.get(model=content_type__model, app_label=content_type__app_label) |
||||
|
||||
files = request.JSON.get('files', []) |
||||
files = [{'data': decode_base64(i['data']), 'name': i['name']} for i in files] |
||||
|
||||
journal = Journal.objects.create( |
||||
action_type=action_type, extra_data=extra_data, thread=thread, |
||||
content_type=content_type, object_id=object_id, |
||||
user=request.user |
||||
) |
||||
|
||||
for i in files: |
||||
s = Storage.objects.create(original=decode_base64(i['data']), name=i['name']) |
||||
journal.files.add(s) |
||||
|
||||
if action_type == 'yes': |
||||
p = Progress.objects.get(course=journal.content_object.course, user=journal.thread.subscribers.all()[0]) |
||||
p.add_vertex(journal.content_object) |
||||
|
||||
return Response(JournalSerializer(journal).data, status=200) |
||||
return Response("permission denied", status=403) |
||||
except Thread.DoesNotExist: |
||||
return Response("Thread doesn't exist.", self.status_code,) |
||||
@ -1,24 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by Django 1.11.6 on 2017-11-29 14:39 |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import migrations |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('courses', '0002_auto_20171128_1518'), |
||||
('maps', '0001_initial'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AlterUniqueTogether( |
||||
name='pivotcoursemap', |
||||
unique_together=set([('map_course', 'route'), ('sort', 'route')]), |
||||
), |
||||
migrations.AlterUniqueTogether( |
||||
name='pivotvertex', |
||||
unique_together=set([('sort', 'map_course'), ('map_course', 'vertex')]), |
||||
), |
||||
] |
||||
@ -1,25 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by Django 1.11.6 on 2017-11-29 14:41 |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('maps', '0002_auto_20171129_1439'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AlterField( |
||||
model_name='pivotcoursemap', |
||||
name='sort', |
||||
field=models.SmallIntegerField(verbose_name='Порядок сортировки'), |
||||
), |
||||
migrations.AlterField( |
||||
model_name='pivotvertex', |
||||
name='sort', |
||||
field=models.SmallIntegerField(verbose_name='Порядок сортировки'), |
||||
), |
||||
] |
||||
@ -1,19 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by Django 1.11.6 on 2017-11-29 14:47 |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import migrations |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('maps', '0003_auto_20171129_1441'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AlterModelOptions( |
||||
name='pivotcoursemap', |
||||
options={'ordering': ('sort',), 'verbose_name': 'Порядок сортировки маршрута', 'verbose_name_plural': 'Порядки сортировок маршрутов'}, |
||||
), |
||||
] |
||||
@ -1,20 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by Django 1.11.6 on 2017-12-01 20:12 |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('maps', '0004_auto_20171129_1447'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AddField( |
||||
model_name='coursemap', |
||||
name='name', |
||||
field=models.CharField(default='Линейное прохождение', max_length=255, verbose_name='Имя прохождения'), |
||||
), |
||||
] |
||||
@ -1,20 +0,0 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by Django 1.11.6 on 2017-12-06 12:58 |
||||
from __future__ import unicode_literals |
||||
|
||||
from django.db import migrations, models |
||||
|
||||
|
||||
class Migration(migrations.Migration): |
||||
|
||||
dependencies = [ |
||||
('maps', '0005_coursemap_name'), |
||||
] |
||||
|
||||
operations = [ |
||||
migrations.AlterField( |
||||
model_name='courseroute', |
||||
name='name', |
||||
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Имя шаблона'), |
||||
), |
||||
] |
||||
Loading…
Reference in new issue