В процессе

feature/fix_generate_pass
Andrey 8 years ago
parent af4261f409
commit b42a589c28
  1. 11
      README.md
  2. 4
      access/migrations/0091_privilege.py
  3. 4
      access/migrations/0092_auto_20170925_1829.py
  4. 3
      access/new_view.py
  5. 9
      access/serializers.py
  6. 1
      api_v1/urls.py
  7. 54
      courses/course_update.py
  8. 80
      courses/migrations/0046_auto_20170925_1829.py
  9. 29
      courses/migrations/0047_auto_20170921_1746.py
  10. 45
      courses/models.py
  11. 3
      courses/new_urls.py
  12. 49
      courses/new_view.py
  13. 140
      courses/serializers.py
  14. 6
      courses/signals.py
  15. 22
      courses/update_db.py
  16. 58
      journals/migrations/0074_auto_20170925_1829.py
  17. 13
      journals/migrations/0075_auto_20170926_1238.py
  18. 25
      journals/migrations/0076_auto_20170922_1116.py
  19. 20
      journals/migrations/0077_auto_20170922_1117.py
  20. 20
      journals/migrations/0078_auto_20170922_1118.py
  21. 2
      journals/models.py
  22. 7
      journals/new_urls.py
  23. 34
      journals/new_view.py
  24. 10
      journals/serilizers.py

@ -1,11 +1,4 @@
#**SkillBox LMS**
Нужно выполнить миграции и запустить скрипт update_db.py без параметров в модуле courses (скрипт на всякий случай пока не удалять)
Фактически в структуре данных изменилось только то, что появилась новая табличка NormalMap. Скрипт собирает все treeview курсов и кладёт в эту табличку
Появилась новая зависимость django_rest_framework.
Изменения никак не трогают старый функционал.
Имеет смысл пробежаться по middl
DROP TABLE courses_normalmap;
снести табличку вручную

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.3 on 2017-09-21 17:07
# Generated by Django 1.9.3 on 2017-09-25 18:29
from __future__ import unicode_literals
from django.db import migrations, models
@ -16,7 +16,7 @@ class Migration(migrations.Migration):
name='Privilege',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('value', models.CharField(choices=[('r', 'Отображение'), ('u', 'Использование'), ('w', 'Изменение')], default='r', max_length=1, verbose_name='Права')),
('value', models.CharField(choices=[('r', 'Доступно для выполнению'), ('w', 'Ждёт ответа'), ('d', 'Выполнено')], default='r', max_length=1, verbose_name='Права')),
],
),
]

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.3 on 2017-09-21 17:07
# Generated by Django 1.9.3 on 2017-09-25 18:29
from __future__ import unicode_literals
from django.conf import settings
@ -10,8 +10,8 @@ import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('courses', '0046_auto_20170925_1829'),
('access', '0091_privilege'),
('courses', '0046_auto_20170921_1707'),
]
operations = [

@ -32,7 +32,8 @@ class CheckUserView(APIView):
status_code = 200
def get(self, request):
if request.user.is_authenticated() and (request.user.in_role in ['M', 'S', 'S2', 'A'] or request.user.is_admin):
if request.user.is_authenticated() and\
(request.user.in_role in ['M', 'S', 'S2', 'A', 'T'] or request.user.is_admin):
return Response(True, status=self.status_code)
return Response(False, status=self.status_code)

@ -3,8 +3,13 @@ from rest_framework import serializers
class UserInitSerializer(serializers.ModelSerializer):
in_role = serializers.SerializerMethodField()
class Meta:
model = get_user_model()
fields = ['id', 'email', 'phone', 'name',
'fname', 'oname', 'city', 'b_day']
fields = ['id', 'email', 'phone', 'name', 'in_avatar',
'fname', 'oname', 'city', 'b_day', 'in_role',]
@staticmethod
def get_in_role(self):
return self.get_in_role_display()

@ -3,4 +3,5 @@ from django.conf.urls import url, include
urlpatterns = [
url(r'courses/', include('courses.new_urls')),
url(r'users/', include('access.new_urls')),
url(r'journals/', include('journals.new_urls')),
]

@ -6,13 +6,11 @@ os.environ['PG_PORT_5432_TCP_ADDR'] = '127.0.0.1'
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings")
django.setup()
from django.contrib.contenttypes.models import ContentType
from courses.models import Course, NormalMap, CourseTheme, Lesson, Homework, Exam, \
Tutorial, Task, Topic, Vertex
from courses.models import Course, NormalMap, CourseTheme, Lesson, Homework, Exam, Vertex
if __name__ == '__main__':
for course in Course.objects.all():
tree = []
course_list = []
for theme in CourseTheme.objects.filter(course=course).order_by('sort'):
topic_vertex = Vertex.manager.create_with_dependencies(
@ -22,54 +20,50 @@ if __name__ == '__main__':
model='topic',
icon=theme.icon,
)
course_list.append(topic_vertex.id)
topic_list = []
tree.append(topic_vertex.id)
children = []
for i in Lesson.objects.filter(theme=theme).order_by('sort'):
on_comment = i.on_comment == 'N' or i.on_comment == 'T' and i.theme.on_comment
tutor = Tutorial.objects.create(video=i.video, on_comment=on_comment)
[tutor.materials.add(j) for j in i.materials.all()]
lesson_type = ContentType.objects.get(app_label="courses", model="tutorial")
vertex = Vertex.objects.create(
vertex = Vertex.manager.create_with_dependencies(
course=course,
title=i.title,
description=i.description,
content_type=lesson_type,
object_id=tutor.id,
model='tutorial',
on_comment=on_comment,
video=i.video,
materials=i.materials.all(),
)
topic_vertex.children.add(vertex)
children.append(vertex.id)
topic_list.append(vertex.id)
for i in Homework.objects.filter(theme=theme).order_by('sort'):
task = Task.objects.create(is_exam=False,)
[task.materials.add(j) for j in i.materials.all()]
task_type = ContentType.objects.get(app_label="courses", model="task")
vertex = Vertex.objects.create(
vertex = Vertex.manager.create_with_dependencies(
course=course,
title='Домашняя работа',
description=i.description,
content_type=task_type,
object_id=task.id,
model='task',
is_exam=False,
materials=i.materials.all(),
)
topic_vertex.children.add(vertex)
children.append(vertex.id)
topic_list.append(vertex.id)
for i in Exam.objects.filter(theme=theme).order_by('sort'):
task=Task.objects.create(is_exam=True,)
[task.materials.add(j) for j in i.materials.all()]
task_type = ContentType.objects.get(app_label="courses", model="task")
vertex = Vertex.objects.create(
vertex = Vertex.manager.create_with_dependencies(
course=course,
title='Экзамен',
description=i.description,
content_type=task_type,
object_id=task.id,
model='task',
is_exam=True,
materials=i.materials.all(),
)
topic_vertex.children.add(vertex)
children.append(vertex.id)
topic_list.append(vertex.id)
tree.append(children)
course_list.append(topic_list)
course_map, _is_create = NormalMap.objects.get_or_create(course=course)
course_map.json_tree=json.dumps(tree)
course_map.save()
course_map.dependent_elements = json.dumps(course_list)
course_map.save()

@ -0,0 +1,80 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.3 on 2017-09-25 18:29
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import django.db.models.manager
class Migration(migrations.Migration):
dependencies = [
('storage', '0002_auto_20160831_1638'),
('contenttypes', '0002_remove_content_type_name'),
('courses', '0045_auto_20170918_0811'),
]
operations = [
migrations.CreateModel(
name='NormalMap',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('dependent_elements', models.TextField(default='[]')),
('independent_elements', models.TextField(default='[]')),
],
),
migrations.CreateModel(
name='Task',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_exam', models.BooleanField(default=False, verbose_name='Экзамен или домашка')),
('materials', models.ManyToManyField(blank=True, to='storage.Storage', verbose_name='Материалы для домашней работы')),
],
),
migrations.CreateModel(
name='Topic',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('icon', models.ImageField(blank=True, null=True, upload_to='CourseTheme', verbose_name='Иконка темы')),
],
),
migrations.CreateModel(
name='Tutorial',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('on_comment', models.BooleanField(default=True, verbose_name='Комментарии')),
('video', models.TextField(blank=True, default='', verbose_name='Код видео')),
('materials', models.ManyToManyField(blank=True, to='storage.Storage', verbose_name='Материалы урока')),
],
),
migrations.CreateModel(
name='Vertex',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=255, verbose_name='Название')),
('description', models.TextField(blank=True, default='', null=True, verbose_name='Описание')),
('object_id', models.PositiveIntegerField()),
('children', models.ManyToManyField(blank=True, to='courses.Vertex')),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
],
managers=[
('manager', django.db.models.manager.Manager()),
],
),
migrations.AlterField(
model_name='course',
name='level',
field=models.CharField(choices=[('B', 'Базовый'), ('A', 'Продвинутый'), ('E', 'Экспертный'), ('B+A', 'Базовый + Продвинутый')], default='B', max_length=3, verbose_name='Уровень'),
),
migrations.AddField(
model_name='vertex',
name='course',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course'),
),
migrations.AddField(
model_name='normalmap',
name='course',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='courses.Course'),
),
]

@ -1,29 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.3 on 2017-09-21 17:46
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('courses', '0046_auto_20170921_1707'),
]
operations = [
migrations.CreateModel(
name='NormalMap',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('json_tree', models.TextField(default='')),
('independent_elements', models.TextField(default='')),
],
),
migrations.AddField(
model_name='normalmap',
name='course',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='courses.Course'),
),
]

@ -980,26 +980,52 @@ class CourseBuilder:
# Модели нового API со временем всё, что выше будет выпилено
class Tutorial(models.Model):
"""
Модель урока.
Урок может быть открыт для комментирования и закрыт, по дефолту открыт,
вероятно закрывать нужно будет крайне редко.
Видео к уроку фрейм который лежит прямо в базе, конечно же костыль и со временем
мы уйдём от этого, все видео хостятся на двух онлайн сервисах на клиент нужно передовать
id и сервис на котором, это дело хостится, а правило отображения оставить клиенту.
Материалы для урока по сути FileField, нужна только для создания лишней связи в таблице
и дублирования метазаголовков файла
"""
on_comment = models.BooleanField(verbose_name=u'Комментарии', default=True)
video = models.TextField(verbose_name=u'Код видео', default='', blank=True)
materials = models.ManyToManyField(Storage, verbose_name=u'Материалы урока', blank=True)
class Task(models.Model):
"""
Модель таска.
Исторически сложилось, что на сервере хостятся два типа тасков отличающихся лишь наименованием
домашние работы и экзамены, не нужно быть гением, чтобы понять для чего нужно булево значение
is_exam
Материалы для урока по сути FileField, нужна только для создания лишней связи в таблице
и дублирования метазаголовков файла
"""
materials = models.ManyToManyField(Storage, verbose_name=u'Материалы для домашней работы', blank=True)
is_exam = models.BooleanField(default=False, verbose_name=u'Экзамен или домашка')
class Topic(models.Model):
"""
Модель темы, нужно просто для объединения тасков и уроков.
У некоторых тем есть иконка.
Возможно поле icon перекачует в Vertex, а данная модель отвалится за ненадобностью
"""
icon = models.ImageField(verbose_name=u'Иконка темы', upload_to='CourseTheme', null=True, blank=True)
class VertexManager(models.Manager):
# Менеджер вершин графа. На самом деле
# Менеджер вершин графа.
def create_with_dependencies(self, model, course, title, description, **kwargs):
def create_with_dependencies(self, model, course, title, description,
materials=None, **kwargs):
content_type = ContentType.objects.get(app_label='courses', model=model)
obj = content_type.model_class().objects.create(**kwargs)
[obj.materials.add(i) for i in materials] if materials else None
return self.create(
content_type=content_type,
object_id=obj.id,
@ -1010,6 +1036,13 @@ class VertexManager(models.Manager):
class Vertex(models.Model):
"""
Основная структурная единица узел графа курса.
Может быть привязана к теме уроку или заданию.
Модель создана для минимизации трёх выше указанных.
Позволяет работать со структурой курса на более высоком уровне абстракции.
"""
course = models.ForeignKey(to=Course)
title = models.CharField(verbose_name=u'Название', max_length=255)
description = models.TextField(
@ -1029,6 +1062,10 @@ class Vertex(models.Model):
class NormalMap(models.Model):
"""
Так как курс евляется связным графом мы можем отобразить его бесконечным количеством способов,
а нам нужен один самый красивый, мы должный в явном виде указать способ отображения.
"""
course = models.OneToOneField(to=Course)
json_tree = models.TextField(default='')
independent_elements = models.TextField(default='')
dependent_elements = models.TextField(default='[]')
independent_elements = models.TextField(default='[]')

@ -2,9 +2,8 @@ from django.conf.urls import url
from courses import new_view as views
urlpatterns = [
url(r'theme/detail/([0-9]{1,99})/$', views.ThemeDetailView.as_view()),
url(r'lesson/detail/([0-9]{1,99})/$', views.LessonDetailView.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'tree/([0-9]{1,99})/$', views.TreeView.as_view()),
url(r'directions/$', views.DirectionListView.as_view()),
url(r'^$', views.CourseListView.as_view()),

@ -1,9 +1,8 @@
from rest_framework.views import APIView
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from courses.models import Course, MaterialDirection, CourseTheme, Lesson
from courses.serializers import CourseTreeSerializer, CourseDetailSerializer, CourseListSerializer,\
ThemeSerializer, LessonSerializer
from courses.models import Course, MaterialDirection, Vertex
from courses.serializers import CourseDetailSerializer, CourseListSerializer, VertexSerializer, CourseTreeSerializer
from finance.models import Bill
@ -24,32 +23,22 @@ class TreeView(APIView):
print(request)
return Response(status=204)
def get(self, request, id):
return Response(CourseTreeSerializer(Course.objects.get(id=id)).data, self.status_code)
class ThemeDetailView(APIView):
renderer_classes = (JSONRenderer,)
status_code = 200
def get(self, request, id):
return Response(ThemeSerializer(CourseTheme.objects.get(id=id)).data, self.status_code)
class LessonDetailView(APIView):
renderer_classes = (JSONRenderer,)
status_code = 200
def get(self, request, id):
return Response(LessonSerializer(Lesson.objects.get(id=id)).data, self.status_code)
def get(self, request, pk):
try:
return Response(CourseTreeSerializer(Course.objects.get(id=pk)).data, self.status_code)
except Course.DoesNotExist:
return Response("Course doesn't exist", status=404)
class CourseDetailView(APIView):
renderer_classes = (JSONRenderer,)
status_code = 200
def get(self, request, id):
return Response(CourseDetailSerializer(Course.objects.get(id=id)).data, self.status_code)
def get(self, request, pk):
try:
return Response(CourseDetailSerializer(Course.objects.get(id=pk)).data, self.status_code)
except Course.DoesNotExist:
return Response("Course doesn't exist", status=404)
class CourseListView(APIView):
@ -69,4 +58,16 @@ class CourseListView(APIView):
course_serialize['is_mine'] = True
res.append(course_serialize)
return Response(res, self.status_code)
return Response(res, self.status_code)
class VertexDetail(APIView):
renderer_classes = (JSONRenderer,)
def get(self, request, pk):
if not request.user.is_authenticated:
return Response("Access to detail of vertex, exist only for authenticated users", status=404)
try:
return Response(VertexSerializer(Vertex.manager.get(id=pk)).data, status=200)
except Vertex.DoesNotExist:
return Response("Vertex doesn't exist", status=404)

@ -3,29 +3,65 @@ import json
# from django.contrib.auth import get_user_model
# from django.core.exceptions import ObjectDoesNotExist
from courses.models import Course, CourseTheme, Lesson, Homework, Exam
from courses.models import Course, Vertex, Tutorial, Topic, Task
class LessonSerializer(serializers.ModelSerializer):
on_comment = serializers.SerializerMethodField()
class TutorialSerializer(serializers.ModelSerializer):
class Meta:
model = Tutorial
exclude = ['id']
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Lesson
fields = (
'id', 'title', 'on_comment', 'materials',
'free', 'video', 'video_id',
)
model = Task
exclude = ['id']
class TopicSerializer(serializers.ModelSerializer):
class Meta:
model = Topic
exclude = ['id']
class MiniVertexSerializer(serializers.ModelSerializer):
object = serializers.SerializerMethodField()
type = serializers.SerializerMethodField()
children = serializers.SerializerMethodField()
class Meta:
model = Vertex
fields = ('id', 'title', 'type', 'object', 'children')
@staticmethod
def get_on_comment(self):
return self.on_comment == 'N' or self.on_comment == 'T' and self.theme.on_comment
def get_object(self):
if self.content_type.model == 'tutorial':
return TutorialSerializer(self.content_object).data
elif self.content_type.model == 'topic':
return TopicSerializer(self.content_object).data
class ThemeSerializer(serializers.ModelSerializer):
elif self.content_type.model == 'task':
return TaskSerializer(self.content_object).data
@staticmethod
def get_type(self):
return self.content_type.model
@staticmethod
def get_children(self):
return json.loads(self.sort_map.dependent_elements)
class VertexSerializer(MiniVertexSerializer):
class Meta:
model = CourseTheme
exclude = ('price_type', '_type', 'sort', 'on_comment')
model = Vertex
fields = ('id', 'title', 'type', 'object', 'children', 'description')
@staticmethod
def get_children(self):
return [VertexSerializer(Vertex.manager.get(id=i)).data
for i in json.loads(self.sort_map.dependent_elements)]
class CourseListSerializer(serializers.ModelSerializer):
@ -36,16 +72,11 @@ class CourseListSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = ['id', 'title', 'length',
'level', 'direction', 'image',]
'level', 'direction', 'image', ]
@staticmethod
def get_length(self):
summary = 0
for theme_slim in json.loads(self.normalmap.json_tree):
for simple_object in theme_slim['body']:
if simple_object.split('_')[1] == 'L':
summary += 1
return summary
return 15
@staticmethod
def get_level(self):
@ -61,46 +92,12 @@ class CourseTreeSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = ['id', 'title', 'children']
fields = ['id', 'children']
@staticmethod
def get_children(self):
theme_list = json.loads(self.normalmap.json_tree)
map = []
for theme_slim in theme_list:
theme = CourseTheme.objects.get(id=theme_slim['id'])
theme_obj = {
'id': theme.id,
'title': theme.title,
'lessons': [],
'tasks': [],
}
for simple_object in theme_slim['body']:
val = simple_object.split('_')[0]
if simple_object.split('_')[1] == 'L':
lesson = Lesson.objects.get(id=val)
lesson_obj = {'id': lesson.id, 'title': lesson.title}
theme_obj['lessons'].append(lesson_obj)
if simple_object.split('_')[1] == 'H':
task = Homework.objects.get(id=val)
task_obj = {
'id': task.id,
'is_exam': False,
}
theme_obj['tasks'].append(task_obj)
if simple_object.split('_')[1] == 'E':
task = Exam.objects.get(id=val)
task_obj = {
'id': task.id,
'is_exam': True,
}
theme_obj['tasks'].append(task_obj)
map.append(theme_obj)
return map
return [MiniVertexSerializer(Vertex.manager.get(id=i)).data
for i in json.loads(self.sort_map.dependent_elements)]
class CourseDetailSerializer(serializers.ModelSerializer):
@ -128,32 +125,3 @@ class CourseDetailSerializer(serializers.ModelSerializer):
@staticmethod
def get_teachers(self):
return [teacher.full_name() for teacher in self.teachers.all()]
# class UserSerializer(serializers.ModelSerializer):
# statistics = serializers.SerializerMethodField('get_statistic')
# games = serializers.SerializerMethodField('get_my_games')
# is_anonymous = serializers.BooleanField()
#
# @staticmethod
# def get_my_games(self):
# res = {}
# try:
# res['active'] = GameSerializer(self.game_set.get(state__lte=1)).data
# except ObjectDoesNotExist:
# res['active'] = {}
#
# res['archive'] = [GameSerializer(i).data for i in self.game_set.all().filter(state=2)]
# return res
#
# @staticmethod
# def get_statistic(self):
# try:
# statistics = StatisticSerializer(Statistic.objects.get(user=self)).data
# except ObjectDoesNotExist:
# statistics = {}
# return statistics
#
# class Meta:
# model = get_user_model()
# fields = ['id', 'username', 'email', 'is_active', 'statistics', 'games', 'is_anonymous']

@ -6,4 +6,8 @@ from courses.models import Vertex
@receiver(pre_delete, sender=Vertex)
def delete_dependencies(instance, **kwargs):
instance.content_object.delete()
"""Удаляем зависимости вместе с узлом"""
if instance.content_object:
instance.content_object.delete()
if instance.sort_map:
instance.sort_map.delete()

@ -1,22 +0,0 @@
import os, sys
import django, json
sys.path.append("../")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings")
django.setup()
from courses.models import Course, NormalMap, CourseTheme, Lesson, Homework, Exam
if __name__ == '__main__':
for course in Course.objects.all():
tree = []
for theme in CourseTheme.objects.filter(course=course).order_by('sort'):
tree.append({'id': theme.id, 'body':
[str(i.id) + "_L" for i in Lesson.objects.filter(theme=theme).order_by('sort')] +
[str(i.id) + "_H" for i in Homework.objects.filter(theme=theme).order_by('sort')] +
[str(i.id) + "_E" for i in Exam.objects.filter(theme=theme).order_by('sort')]
})
obj, _is_create = NormalMap.objects.get_or_create(course=course)
obj.json_tree = json.dumps(tree)
obj.save()

@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.3 on 2017-09-25 18:29
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 = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contenttypes', '0002_remove_content_type_name'),
('journals', '0073_auto_20170918_0811'),
]
operations = [
migrations.CreateModel(
name='Action',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Наименование действия (на английском)')),
('text', models.TextField(verbose_name='Описание действия')),
],
),
migrations.CreateModel(
name='Journal',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('object_id', models.PositiveIntegerField()),
('date', models.DateTimeField(auto_now=True)),
('action_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='journals.Action')),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
],
),
migrations.CreateModel(
name='Thread',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('key', models.CharField(max_length=200)),
('text', models.TextField(default='', verbose_name='Описание треда')),
('is_staff', models.BooleanField(default=False, verbose_name='Админская ли табличка')),
('parent', models.ManyToManyField(blank=True, related_name='_thread_parent_+', to='journals.Thread')),
('subscribers', models.ManyToManyField(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,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.3 on 2017-09-22 11:23
# Generated by Django 1.9.3 on 2017-09-26 12:38
from __future__ import unicode_literals
from django.db import migrations, models
@ -8,17 +8,18 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('journals', '0078_auto_20170922_1118'),
('journals', '0074_auto_20170925_1829'),
]
operations = [
migrations.RemoveField(
migrations.AddField(
model_name='thread',
name='children',
name='x',
field=models.SmallIntegerField(default=0),
),
migrations.AddField(
model_name='thread',
name='parent',
field=models.ManyToManyField(blank=True, related_name='_thread_parent_+', to='journals.Thread'),
name='y',
field=models.SmallIntegerField(default=0),
),
]

@ -1,25 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.3 on 2017-09-22 11:16
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('journals', '0075_remove_journal_body'),
]
operations = [
migrations.AddField(
model_name='thread',
name='is_staff',
field=models.BooleanField(default=True, verbose_name='Видно ли в админке'),
),
migrations.AlterField(
model_name='thread',
name='text',
field=models.TextField(default='', verbose_name='Описание треда'),
),
]

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.3 on 2017-09-22 11:17
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('journals', '0076_auto_20170922_1116'),
]
operations = [
migrations.AlterField(
model_name='thread',
name='is_staff',
field=models.BooleanField(default=False, verbose_name='Видно ли в админке'),
),
]

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.3 on 2017-09-22 11:18
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('journals', '0077_auto_20170922_1117'),
]
operations = [
migrations.AlterField(
model_name='thread',
name='is_staff',
field=models.BooleanField(default=False, verbose_name='Админская ли табличка'),
),
]

@ -1688,6 +1688,8 @@ class Thread(models.Model):
is_staff = models.BooleanField(default=False, verbose_name=u'Админская ли табличка')
subscribers = models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name=u'Подписчики')
parent = models.ManyToManyField(to='self', blank=True)
x = models.SmallIntegerField(default=300)
y = models.SmallIntegerField(default=300)
def get_journals(self, **filter_extra):
threads = [i for i in self.thread_set.all()].append(self)

@ -0,0 +1,7 @@
from django.conf.urls import url
from journals import new_view as views
urlpatterns = [
url(r'thread/$', views.ThreadListView.as_view()),
url(r'thread/([0-9]{1,99})/$', views.ThreadDetailView.as_view()),
]

@ -0,0 +1,34 @@
from rest_framework.views import APIView
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from journals.models import Thread
from journals.serilizers import ThreadSerializer
class ThreadListView(APIView):
renderer_classes = (JSONRenderer,)
status_code = 200
def get(self, request):
return Response(
[ThreadSerializer(thread).data for thread in Thread.objects.filter(is_staff=True)],
self.status_code,
)
class ThreadDetailView(APIView):
renderer_classes = (JSONRenderer,)
status_code = 200
def post(self, request, pk):
try:
thread = Thread.objects.get(id=pk)
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(ThreadSerializer(thread).data, self.status_code,)
except Thread.DoesNotExist:
return Response("Thread doesn't exist.", self.status_code,)

@ -0,0 +1,10 @@
from rest_framework import serializers
from journals.models import Thread
class ThreadSerializer(serializers.ModelSerializer):
class Meta:
model = Thread
exclude = ['is_staff']
Loading…
Cancel
Save