feature/fix_generate_pass
Andrey 8 years ago
parent e97c343995
commit f41af94e52
  1. 6
      access/migrations/0001_initial.py
  2. 76
      access/migrations/0002_auto_20171212_2307.py
  3. 14
      access/models/other.py
  4. 2
      achievements/migrations/0001_initial.py
  5. 51
      achievements/migrations/0002_auto_20171212_2307.py
  6. 4
      courses/admin.py
  7. 38
      courses/migrations/0001_initial.py
  8. 31
      courses/migrations/0002_auto_20171212_2307.py
  9. 105
      courses/models.py
  10. 30
      courses/serializers.py
  11. 4
      csv/load_courses.py
  12. 4
      csv/load_student_teachers_threads.py
  13. 6
      finance/migrations/0001_initial.py
  14. 2
      library/migrations/0001_initial.py
  15. 4
      maps/migrations/0001_initial.py
  16. 5
      storage/admin.py
  17. 14
      storage/migrations/0001_initial.py
  18. 15
      storage/models.py
  19. 4
      storage/serializers.py
  20. 28
      storage/tests.py
  21. 47
      storage/views.py

@ -1,8 +1,9 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-12 16:07
# Generated by Django 1.11.6 on 2017-12-12 23:07
from __future__ import unicode_literals
import access.models.user
import django.contrib.postgres.fields
from django.db import migrations, models
import django.db.models.deletion
@ -69,7 +70,8 @@ class Migration(migrations.Migration):
name='PivotProgressVertex',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('status', models.SmallIntegerField(choices=[(0, 'Выполненно'), (1, 'Ожидание'), (2, 'Не выполненно')], default=0)),
('status', models.SmallIntegerField(choices=[(2, 'Выполненно'), (1, 'Ожидание'), (0, 'Не выполненно')], default=0)),
('comment', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=15, verbose_name='Ссылки на комменты'), size=None)),
],
),
migrations.CreateModel(

@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-12 23:07
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', '0002_auto_20171212_2307'),
('auth', '0008_alter_user_username_max_length'),
('maps', '0001_initial'),
('access', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='progress',
name='course',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='Курс'),
),
migrations.AddField(
model_name='progress',
name='teacher',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teacher_progress', to=settings.AUTH_USER_MODEL, 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.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент'),
),
migrations.AddField(
model_name='pivotprogressvertex',
name='progress',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='access.Progress'),
),
migrations.AddField(
model_name='pivotprogressvertex',
name='vertex',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Vertex'),
),
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='Кому приглошение'),
),
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,4 +1,5 @@
from django.conf import settings
from django.contrib.postgres.fields import ArrayField
from django.db import models
from courses.models import Course, Vertex
@ -65,6 +66,11 @@ class Progress(models.Model):
@transaction_decorator
def add_vertex(self, vertex):
PivotProgressVertex.objects.create(
progress=self,
vertex=vertex,
)
self.progress_list.add(vertex)
parent = vertex.vertex_set.first() if vertex.vertex_set.all().exists() else None
if parent:
@ -93,11 +99,13 @@ class Progress(models.Model):
class PivotProgressVertex(models.Model):
VERTEX_STATUS = (
(0, 'Выполненно'),
(2, 'Выполненно'),
(1, 'Ожидание'),
(2, 'Не выполненно'),
(0, 'Не выполненно'),
)
progress = models.ForeignKey(to=Progress)
vertex = models.ForeignKey(to=Vertex)
status = models.SmallIntegerField(choices=VERTEX_STATUS, default=0)
comment = models.ManyToManyField(to=Comment)
comment = ArrayField(
models.CharField(max_length=15, blank=True, verbose_name='Ссылки на комменты'),
)

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-12 16:07
# Generated by Django 1.11.6 on 2017-12-12 23:07
from __future__ import unicode_literals
from django.db import migrations, models

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-12 23:07
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'),
('achievements', '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='users',
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL),
),
]

@ -1,9 +1,7 @@
from django.contrib import admin
from courses.models import Course, Tutorial, Topic, Task, Vertex
from courses.models import Course, Topic, Vertex
admin.site.register(Topic)
admin.site.register(Task)
admin.site.register(Vertex)
admin.site.register(Tutorial)
admin.site.register(Course)

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-12 16:07
# Generated by Django 1.11.6 on 2017-12-12 23:07
from __future__ import unicode_literals
from django.db import migrations, models
@ -11,7 +11,6 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('storage', '0001_initial'),
]
@ -37,29 +36,18 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'Курсы',
},
),
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')),
('title', models.CharField(max_length=255, verbose_name='Название')),
('icon', models.ImageField(blank=True, null=True, upload_to='', verbose_name='Иконка темы')),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course')),
],
),
migrations.CreateModel(
name='Tutorial',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('on_comment', models.BooleanField(default=False, verbose_name='Комментарии')),
('video', models.TextField(blank=True, default='', verbose_name='Код видео')),
('materials', models.ManyToManyField(blank=True, to='storage.Storage', verbose_name='Материалы урока')),
],
options={
'verbose_name': 'Тема',
'verbose_name_plural': 'Темы',
},
),
migrations.CreateModel(
name='Vertex',
@ -68,10 +56,14 @@ class Migration(migrations.Migration):
('title', models.CharField(max_length=255, verbose_name='Название')),
('free', models.BooleanField(default=True, 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')),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course')),
('video', models.TextField(blank=True, default='', null=True, verbose_name='Код видео')),
('valid_type', models.SmallIntegerField(choices=[(3, 'Автаматическая валидация'), (2, 'Полуавтаматическая валидация'), (1, 'Ручная валидация'), (0, 'Без валидации')], default=0)),
('materials', models.ManyToManyField(blank=True, to='storage.File', verbose_name='Материалы урока')),
('topic', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Topic')),
],
options={
'verbose_name': 'Урок',
'verbose_name_plural': 'Уроки',
},
),
]

@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-12 23:07
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'),
('maps', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
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='Преподаватели'),
),
]

@ -13,7 +13,7 @@ from maps.models import CourseRoute, CourseMap
from lms.tools import decode_base64, get_real_name
from lms.global_decorators import transaction_decorator
from library.models import Tags
from storage.models import Storage
from storage.models import File
import random
COURSE_LEVEL = (
@ -163,58 +163,33 @@ class Course(models.Model):
verbose_name_plural = "Курсы"
class VertexManager(models.Manager):
# Менеджер вершин графа.
@transaction_decorator
def create_with_dependencies(self, model, course, title, description, extra_data=None,
free=True, materials=None, parents=None, children=None):
extra_data = json.loads(extra_data)
content_type = ContentType.objects.get(app_label='courses', model=model)
obj = content_type.model_class().objects.create(**extra_data)
[obj.materials.add(i) for i in materials] if materials else None
res = self.create(
content_type=content_type,
object_id=obj.id,
course=course,
title=title,
description=description,
free=free,
)
if children:
for child in children:
res.children.add(child)
if parents:
for parent in parents:
parent.children.add(res)
class Topic(models.Model):
title = models.CharField(verbose_name='Название', max_length=255)
icon = models.ImageField(verbose_name='Иконка темы', null=True, blank=True)
course = models.ForeignKey(to=Course)
return res
class Meta:
verbose_name = "Тема"
verbose_name_plural = "Темы"
class Vertex(models.Model):
"""
Основная структурная единица узел графа курса.
Позволяет работать со структурой курса на более высоком уровне абстракции.
"""
course = models.ForeignKey(to=Course)
VALID_TYPE = (
(3, 'Автаматическая валидация'),
(2, 'Полуавтаматическая валидация'),
(1, 'Ручная валидация'),
(0, 'Без валидации'),
)
topic = models.ForeignKey(to=Topic)
title = models.CharField(verbose_name='Название', max_length=255)
free = models.BooleanField(default=True, verbose_name='Привилегии для узла не будут проверяться')
description = models.TextField(verbose_name='Описание', default='', blank=True, null=True)
children = models.ManyToManyField(to='Vertex', blank=True)
content_type = models.ForeignKey(to=ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
objects = VertexManager()
video = models.TextField(verbose_name='Код видео', default='', blank=True, null=True)
materials = models.ManyToManyField(File, verbose_name='Материалы урока', blank=True)
valid_type = models.SmallIntegerField(choices=VALID_TYPE, default=0)
def __str__(self):
return self.title + ': ' + str(self.content_type.model)
return self.title
def get_next(self, route):
return route.get_first().get_next(self)
@ -271,42 +246,6 @@ class Vertex(models.Model):
res = None
return res
# Модели нового API со временем всё, что выше будет выпилено
class Tutorial(models.Model):
"""
Модель урока.
Урок может быть открыт для комментирования и закрыт, по дефолту открыт,
вероятно закрывать нужно будет крайне редко.
Видео к уроку фрейм который лежит прямо в базе, конечно же костыль и со временем
мы уйдём от этого, все видео хостятся на двух онлайн сервисах на клиент нужно передовать
id и сервис на котором, это дело хостится, а правило отображения оставить клиенту.
Материалы для урока по сути FileField, нужна только для создания лишней связи в таблице
и дублирования метазаголовков файла
"""
on_comment = models.BooleanField(verbose_name=u'Комментарии', default=False)
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='Материалы для домашней работы', blank=True)
is_exam = models.BooleanField(default=False, verbose_name='Экзамен или домашка')
class Topic(models.Model):
"""
Модель темы, нужно просто для объединения тасков и уроков.
У некоторых тем есть иконка.
Возможно поле icon перекачует в Vertex, а данная модель отвалится за ненадобностью
"""
icon = models.ImageField(verbose_name='Иконка темы', null=True, blank=True)
class Meta:
verbose_name = "Урок"
verbose_name_plural = "Уроки"

@ -1,24 +1,6 @@
from rest_framework import serializers
from courses.models import Course, Vertex, Tutorial, Topic, Task
class TutorialSerializer(serializers.ModelSerializer):
materials = serializers.SerializerMethodField()
class Meta:
model = Tutorial
exclude = ['id']
@staticmethod
def get_materials(self):
return [i.original.url for i in self.materials.all()]
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
exclude = ['id']
from courses.models import Course, Vertex, Topic
class TopicSerializer(serializers.ModelSerializer):
@ -49,15 +31,7 @@ class MiniVertexSerializer(serializers.ModelSerializer):
class VertexSerializer(MiniVertexSerializer):
class Meta:
model = Vertex
fields = ('id', 'title', 'type', 'object', "description")
@staticmethod
def get_object(self):
if self.content_type.model == 'tutorial':
return TutorialSerializer(self.content_object).data
if self.content_type.model == 'task':
return TaskSerializer(self.content_object).data
return False
fields = '__all__'
class CourseInitSerializer(serializers.ModelSerializer):

@ -8,7 +8,7 @@ django.setup()
from courses.models import Course, Vertex
from maps.models import CourseRoute, CourseMap, PivotVertex, PivotCourseMap
from storage.models import Storage
from storage.models import File
if __name__ == '__main__':
CourseMap.objects.all().delete()
@ -37,7 +37,7 @@ if __name__ == '__main__':
storage_reader = csv.DictReader(storage_csv)
for row in storage_reader:
if row['original']:
Storage.objects.get_or_create(**row)
File.objects.get_or_create(**row)
with open('./course/vertex.csv') as vertex_csv:
vertex_reader = csv.DictReader(vertex_csv)

@ -9,7 +9,7 @@ django.setup()
from courses.models import Vertex
from django.contrib.contenttypes.models import ContentType
from journals.models import Thread, Journal
from storage.models import Storage
from storage.models import File
if __name__ == '__main__':
csv.field_size_limit(500 * 1024 * 1024)
@ -53,5 +53,5 @@ if __name__ == '__main__':
for file_id in row['files'].split("[")[1].split("]")[0].split(", "):
if file_id:
journal.files.add(Storage.objects.get(id=file_id))
journal.files.add(File.objects.get(id=file_id))

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-12 16:07
# Generated by Django 1.11.6 on 2017-12-12 23:07
from __future__ import unicode_literals
from django.conf import settings
@ -12,9 +12,9 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('yandex_money', '0002_auto_20171128_1150'),
('courses', '0002_auto_20171212_2307'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('courses', '0002_auto_20171212_1607'),
('yandex_money', '0002_auto_20171128_1150'),
]
operations = [

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-12 16:07
# Generated by Django 1.11.6 on 2017-12-12 23:07
from __future__ import unicode_literals
import datetime

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-12 16:07
# Generated by Django 1.11.6 on 2017-12-12 23:07
from __future__ import unicode_literals
from django.db import migrations, models
@ -73,6 +73,6 @@ class Migration(migrations.Migration):
),
migrations.AlterUniqueTogether(
name='pivotcoursemap',
unique_together=set([('sort', 'route'), ('map_course', 'route')]),
unique_together=set([('map_course', 'route'), ('sort', 'route')]),
),
]

@ -1,4 +1,5 @@
from django.contrib import admin
from storage.models import Storage
from storage.models import File, Comment
admin.site.register(Storage)
admin.site.register(File)
admin.site.register(Comment)

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-12 16:07
# Generated by Django 1.11.6 on 2017-12-12 23:07
from __future__ import unicode_literals
from django.db import migrations, models
@ -17,11 +17,17 @@ class Migration(migrations.Migration):
name='Comment',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('text', models.TextField(default='')),
('email', models.CharField(max_length=63, verbose_name='email автора')),
('text', models.TextField(default='', verbose_name='Текст комментария')),
('key', models.SlugField(unique=True, verbose_name='Получения комментария по ключу')),
],
options={
'verbose_name': 'Коммент',
'verbose_name_plural': 'Комменты',
},
),
migrations.CreateModel(
name='Storage',
name='File',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('original', models.FileField(max_length=255, upload_to='files', verbose_name='Файл')),
@ -35,6 +41,6 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='comment',
name='files',
field=models.ManyToManyField(blank=True, to='storage.Storage'),
field=models.ManyToManyField(blank=True, to='storage.File', verbose_name='Файлы'),
),
]

@ -2,7 +2,7 @@
from django.db import models
class Storage(models.Model):
class File(models.Model):
original = models.FileField(max_length=255, verbose_name='Файл', upload_to="files")
name = models.CharField(max_length=255, null=True, blank=True, verbose_name='Видимое имя файла')
@ -15,5 +15,14 @@ class Storage(models.Model):
class Comment(models.Model):
text = models.TextField(default="")
files = models.ManyToManyField(to=Storage, blank=True)
email = models.CharField(verbose_name="email автора", max_length=63)
text = models.TextField(default="", verbose_name="Текст комментария")
files = models.ManyToManyField(to=File, blank=True, verbose_name='Файлы')
key = models.SlugField(unique=True, verbose_name="Получения комментария по ключу")
def __str__(self):
return '%s' % self.key
class Meta:
verbose_name = 'Коммент'
verbose_name_plural = 'Комменты'

@ -1,10 +1,10 @@
from rest_framework import serializers
from storage.models import Storage
from storage.models import File
class StorageSerializer(serializers.ModelSerializer):
class Meta:
model = Storage
model = File
exclude = ('id',)

@ -0,0 +1,28 @@
from django.test import TestCase
from storage.views import add_comment, delete_comment, update_comment, get_comment
from django.core.files.uploadedfile import SimpleUploadedFile
class CommentTestCase(TestCase):
def setUp(self):
self.first_comment = add_comment("first comment", "vasia@rambler.ru")
self.second_comment = add_comment(text="Привет, отличная работа", email="artem4000@gmail.com")
def test_comment_get(self):
self.assertEqual(self.first_comment, get_comment(self.first_comment.key))
def test_comment_update(self):
new_text = "Новый текст для коммента"
update_comment(key=self.first_comment.key, text=new_text)
self.assertEqual(get_comment(self.first_comment.key).text, new_text)
def test_comment_create(self):
token = 'fskjfskj'
comment1 = add_comment(text=token, email="artem4000@gmail.com")
self.assertEqual(comment1.text, token)
file_for_upload = SimpleUploadedFile('1.txt', 'Я файл!'.encode('utf-8'))
file_name = 'Клёвый файл'
object_for_upload = {'original': file_for_upload, 'name': file_name}
comment2 = add_comment(text=token, email="artem4000@gmail.com", files=[object_for_upload])
self.assertEqual(comment2.files.count(), 1)
self.assertEqual(comment2.files.all()[0].name, file_name)

@ -0,0 +1,47 @@
import random
import string
from storage.models import Comment, File
def add_comment(text: str, email: str, files=None) -> Comment:
"""
:param text: sting
:param email: string
:param files: {name?: string, file?: File, base64?: string}[] одно из двух последних свойств должно быть указано
:return: Comment
"""
key = ''.join(random.choice(string.ascii_letters) for _x in range(15))
comment = Comment.objects.create(
text=text,
email=email,
key=key,
)
if files:
for file in files:
new_file = File.objects.create(original=file['original'])
if 'name' in file.keys():
new_file.name = file['name']
new_file.save()
comment.files.add(new_file)
return comment
def get_comment(key):
comment = Comment.objects.get(key=key)
return comment
def update_comment(key, **kwargs):
comment = Comment.objects.get(key=key)
comment.__dict__.update(kwargs)
comment.save()
return comment
def delete_comment(key):
comment = Comment.objects.get(key=key).delete()
return comment
Loading…
Cancel
Save