diff --git a/access/migrations/0001_initial.py b/access/migrations/0001_initial.py index 40712e7..c70af12 100644 --- a/access/migrations/0001_initial.py +++ b/access/migrations/0001_initial.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-13 23:00 +# Generated by Django 1.11.6 on 2017-12-17 18:03 from __future__ import unicode_literals import access.models.user @@ -7,6 +7,7 @@ from django.conf import settings import django.contrib.postgres.fields from django.db import migrations, models import django.db.models.deletion +import phonenumber_field.modelfields class Migration(migrations.Migration): @@ -51,8 +52,8 @@ class Migration(migrations.Migration): ('b_day', models.DateField(blank=True, null=True)), ('city', models.CharField(blank=True, max_length=63, null=True)), ('gender', models.SmallIntegerField(choices=[(0, 'undefined'), (1, 'male'), (2, 'female')], default=0)), - ('photo', models.ImageField(blank=True, default='/static/default/access/default.png', null=True, upload_to='user/photo/')), - ('phone', models.CharField(blank=True, max_length=15, null=True)), + ('photo', models.ImageField(default='/static/default/access/default.png', upload_to='user/photo/')), + ('phone', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128)), ('owner', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ @@ -76,7 +77,7 @@ class Migration(migrations.Migration): name='PivotProgressVertex', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('vertex', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=15, unique=True, verbose_name='Ссылки на узлы'), size=None)), + ('vertex', models.CharField(blank=True, max_length=15, unique=True, verbose_name='Ссылки на узлы')), ('status', models.SmallIntegerField(choices=[(2, 'Выполненно'), (1, 'Ожидание'), (0, 'Не выполненно')], default=0)), ('comment', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=15, unique=True, verbose_name='Ссылки на комменты'), size=None)), ], @@ -85,9 +86,9 @@ class Migration(migrations.Migration): name='Progress', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('template', models.CharField(max_length=15, verbose_name='Токен прохождения')), + ('route', models.CharField(max_length=15, verbose_name='Токен прохождения')), ('teacher', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teacher_progress', to=settings.AUTH_USER_MODEL, verbose_name='Преподователь по умолчанию')), - ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент')), ], options={ 'verbose_name': 'Прогресс пользователя', @@ -114,7 +115,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='pivotprogressvertex', name='teacher', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Преподователь по умолчанию'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Преподователь'), ), migrations.AddField( model_name='invite', @@ -123,6 +124,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name='progress', - unique_together=set([('user', 'template')]), + unique_together=set([('user', 'route')]), ), ] diff --git a/access/migrations/0002_auto_20171214_2034.py b/access/migrations/0002_auto_20171214_2034.py deleted file mode 100644 index 386156a..0000000 --- a/access/migrations/0002_auto_20171214_2034.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-14 20:34 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('access', '0001_initial'), - ] - - operations = [ - migrations.RenameField( - model_name='progress', - old_name='template', - new_name='route', - ), - migrations.AlterUniqueTogether( - name='progress', - unique_together=set([('user', 'route')]), - ), - ] diff --git a/access/migrations/0002_auto_20171217_1808.py b/access/migrations/0002_auto_20171217_1808.py new file mode 100644 index 0000000..8c0c049 --- /dev/null +++ b/access/migrations/0002_auto_20171217_1808.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.6 on 2017-12-17 18:08 +from __future__ import unicode_literals + +from django.db import migrations +import phonenumber_field.modelfields + + +class Migration(migrations.Migration): + + dependencies = [ + ('access', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='account', + name='phone', + field=phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, null=True), + ), + ] diff --git a/access/migrations/0003_auto_20171214_2049.py b/access/migrations/0003_auto_20171214_2049.py deleted file mode 100644 index b9dc237..0000000 --- a/access/migrations/0003_auto_20171214_2049.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-14 20:49 -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_20171214_2034'), - ] - - operations = [ - migrations.AlterField( - model_name='progress', - name='teacher', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='teacher_progress', to=settings.AUTH_USER_MODEL, verbose_name='Преподователь по умолчанию'), - ), - migrations.AlterField( - model_name='progress', - name='user', - field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент'), - preserve_default=False, - ), - ] diff --git a/access/migrations/0004_auto_20171215_1735.py b/access/migrations/0004_auto_20171215_1735.py deleted file mode 100644 index 720ef9e..0000000 --- a/access/migrations/0004_auto_20171215_1735.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-15 17:35 -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_20171214_2049'), - ] - - operations = [ - migrations.AlterField( - model_name='pivotprogressvertex', - name='teacher', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Преподователь'), - ), - ] diff --git a/access/models/other.py b/access/models/other.py index fcdd84c..6c803ab 100644 --- a/access/models/other.py +++ b/access/models/other.py @@ -1,11 +1,7 @@ from django.conf import settings from django.contrib.postgres.fields import ArrayField from django.db import models -from django.db.models import Q - -from course_service.courses.models import Course, Vertex -from course_service.maps.models import CourseRoute -from lms.global_decorators import transaction_decorator +from phonenumber_field.modelfields import PhoneNumberField class Invite(models.Model): @@ -36,8 +32,8 @@ class Account(models.Model): city = models.CharField(max_length=63, null=True, blank=True) gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0) owner = models.OneToOneField(to=settings.AUTH_USER_MODEL, null=True) - photo = models.ImageField(null=True, blank=True, default='/static/default/access/default.png', upload_to='user/photo/') - phone = models.CharField(max_length=15, null=True, blank=True) + photo = models.ImageField(default='/static/default/access/default.png', upload_to='user/photo/') + phone = PhoneNumberField(blank=True, null=True) def __str__(self): return self.owner.email @@ -49,7 +45,7 @@ class Account(models.Model): class Progress(models.Model): teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь по умолчанию", - related_name='teacher_progress', null=True, blank=True) + related_name='teacher_progress') user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Студент') route = models.CharField(max_length=15, verbose_name='Токен прохождения') @@ -68,9 +64,8 @@ class PivotProgressVertex(models.Model): (1, 'Ожидание'), (0, 'Не выполненно'), ) - teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь", - blank=True, null=True) + teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь",) progress = models.ForeignKey(to=Progress) - vertex = ArrayField(models.CharField(max_length=15, blank=True, verbose_name='Ссылки на узлы', unique=True),) + vertex = models.CharField(max_length=15, blank=True, verbose_name='Ссылки на узлы', unique=True) status = models.SmallIntegerField(choices=VERTEX_STATUS, default=0) comment = ArrayField(models.CharField(max_length=15, blank=True, verbose_name='Ссылки на комменты', unique=True),) \ No newline at end of file diff --git a/achievements/migrations/0001_initial.py b/achievements/migrations/0001_initial.py index d644437..a7f8722 100644 --- a/achievements/migrations/0001_initial.py +++ b/achievements/migrations/0001_initial.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-13 23:00 +# Generated by Django 1.11.6 on 2017-12-17 18:03 from __future__ import unicode_literals from django.db import migrations, models @@ -17,8 +17,8 @@ class Migration(migrations.Migration): name='Achievements', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('img', models.ImageField(blank=True, null=True, upload_to='achives', verbose_name='Отображение достижения')), - ('text', models.CharField(default='', max_length=255, verbose_name='Текст достижения')), + ('img', models.ImageField(upload_to='achives', verbose_name='Отображение достижения')), + ('text', models.CharField(max_length=255, verbose_name='Текст достижения')), ], options={ 'verbose_name': 'Достижение', @@ -63,7 +63,7 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('title', models.CharField(max_length=255, verbose_name='Наименование')), ('color', models.CharField(max_length=255, verbose_name='Цвет')), - ('icon', models.ImageField(help_text='65x65', null=True, upload_to='skills', verbose_name='Большая картинка')), + ('icon', models.ImageField(help_text='65x65', upload_to='skills', verbose_name='Картинка')), ('description', models.TextField(blank=True, verbose_name='Описание')), ], options={ diff --git a/achievements/migrations/0002_auto_20171213_2300.py b/achievements/migrations/0002_auto_20171213_2300.py deleted file mode 100644 index 01a6a58..0000000 --- a/achievements/migrations/0002_auto_20171213_2300.py +++ /dev/null @@ -1,51 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-13 23:00 -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 = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('courses', '0001_initial'), - ('achievements', '0001_initial'), - ] - - 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), - ), - ] diff --git a/achievements/models.py b/achievements/models.py index 5308e25..2625bfb 100644 --- a/achievements/models.py +++ b/achievements/models.py @@ -5,8 +5,8 @@ from course_service.courses.models import Course, Vertex class Achievements(models.Model): - img = models.ImageField(verbose_name='Отображение достижения', upload_to='achives', blank=True, null=True) - text = models.CharField(max_length=255, verbose_name="Текст достижения", default="") + img = models.ImageField(verbose_name='Отображение достижения', upload_to='achives') + text = models.CharField(max_length=255, verbose_name="Текст достижения") users = models.ManyToManyField(to=settings.AUTH_USER_MODEL) class Meta: @@ -17,7 +17,7 @@ class Achievements(models.Model): class Skills(models.Model): title = models.CharField(verbose_name='Наименование', max_length=255) color = models.CharField(verbose_name='Цвет', max_length=255) - icon = models.ImageField(verbose_name='Большая картинка', upload_to='skills', null=True, help_text='65x65') + icon = models.ImageField(verbose_name='Картинка', upload_to='skills', help_text='65x65') description = models.TextField(verbose_name='Описание', blank=True) def __str__(self): return '%s' % self.title diff --git a/course_service/courses/migrations/0001_initial.py b/course_service/courses/migrations/0001_initial.py index c3a461e..c9eaa46 100644 --- a/course_service/courses/migrations/0001_initial.py +++ b/course_service/courses/migrations/0001_initial.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-13 23:00 +# Generated by Django 1.11.6 on 2017-12-17 18:03 from __future__ import unicode_literals import django.contrib.postgres.fields @@ -21,14 +21,14 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('hidden', models.BooleanField(default=False, verbose_name='Видно только оплатившим')), ('level', models.CharField(choices=[('B', 'Базовый'), ('A', 'Продвинутый'), ('E', 'Экспертный'), ('B+A', 'Базовый + Продвинутый')], default='B', max_length=3, verbose_name='Уровень')), - ('slug', models.SlugField(blank=True, default='', editable=False, max_length=255, unique=True)), - ('direction', models.SmallIntegerField(choices=[(3, 'Бизнес'), (2, 'Веб-дизайн'), (1, 'Разработка'), (4, 'Рисование')], null=True, verbose_name='Направление')), + ('slug', models.SlugField(editable=False, unique=True)), + ('direction', models.SmallIntegerField(choices=[(3, 'Бизнес'), (2, 'Веб-дизайн'), (1, 'Разработка'), (4, 'Рисование')], verbose_name='Направление')), ('public', models.BooleanField(default=False, verbose_name='Опубликовать')), - ('title', models.CharField(max_length=255, verbose_name='Заголовок')), + ('title', models.CharField(max_length=255, unique=True, verbose_name='Заголовок')), ('description', models.TextField(blank=True, verbose_name='Описание')), ('image', models.URLField(blank=True, max_length=255, verbose_name='Изображение')), ('big_image', models.URLField(blank=True, max_length=255, verbose_name='Большое изображение')), - ('big_mobile_image', models.URLField(blank=True, help_text='Большая картинка для мобильной версии', max_length=255, null=True, verbose_name='Под мобилку')), + ('big_mobile_image', models.URLField(blank=True, help_text='Большая картинка для мобильной версии', max_length=255, verbose_name='Под мобилку')), ('teachers', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=15, verbose_name='Ссылки на преподов'), default=[], size=None)), ], options={ @@ -42,6 +42,7 @@ class Migration(migrations.Migration): ('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='Иконка темы')), + ('description', models.TextField(blank=True, null=True, verbose_name='Описание')), ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='курс')), ], options={ @@ -54,12 +55,12 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('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='Описание')), - ('video', models.TextField(blank=True, default='', null=True, verbose_name='Код видео')), + ('free', models.BooleanField(default=False, verbose_name='Привилегии для узла не будут проверяться')), + ('description', models.TextField(blank=True, null=True, verbose_name='Описание')), + ('video', models.TextField(blank=True, null=True, verbose_name='Код видео')), ('materials', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=15, verbose_name='Материалы урока'), size=None)), ('valid_type', models.SmallIntegerField(choices=[(3, 'Автаматическая валидация'), (2, 'Полуавтаматическая валидация'), (1, 'Ручная валидация'), (0, 'Без валидации')], default=0)), - ('token', models.CharField(max_length=15, unique=True, verbose_name='Ключ доступа к узлу')), + ('token', models.CharField(editable=False, max_length=15, unique=True, verbose_name='Ключ доступа к узлу')), ('topic', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Topic', verbose_name='Тема')), ], options={ diff --git a/course_service/courses/migrations/0002_course_route.py b/course_service/courses/migrations/0002_course_route.py index dcaee66..2509ad3 100644 --- a/course_service/courses/migrations/0002_course_route.py +++ b/course_service/courses/migrations/0002_course_route.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-13 23:00 +# Generated by Django 1.11.6 on 2017-12-17 18:03 from __future__ import unicode_literals from django.db import migrations, models diff --git a/course_service/courses/migrations/0003_auto_20171214_1513.py b/course_service/courses/migrations/0003_auto_20171214_1513.py deleted file mode 100644 index 63a8c03..0000000 --- a/course_service/courses/migrations/0003_auto_20171214_1513.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-14 15:13 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('courses', '0002_course_route'), - ] - - operations = [ - migrations.AddField( - model_name='topic', - name='description', - field=models.TextField(blank=True, null=True, verbose_name='Описание'), - ), - migrations.AlterField( - model_name='vertex', - name='description', - field=models.TextField(blank=True, null=True, verbose_name='Описание'), - ), - ] diff --git a/course_service/courses/migrations/0003_auto_20171217_1821.py b/course_service/courses/migrations/0003_auto_20171217_1821.py new file mode 100644 index 0000000..0ecde21 --- /dev/null +++ b/course_service/courses/migrations/0003_auto_20171217_1821.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.6 on 2017-12-17 18:21 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('courses', '0002_course_route'), + ] + + operations = [ + migrations.AlterField( + model_name='course', + name='slug', + field=models.SlugField(editable=False, max_length=127, unique=True), + ), + ] diff --git a/course_service/courses/models.py b/course_service/courses/models.py index 66413f0..81c544f 100755 --- a/course_service/courses/models.py +++ b/course_service/courses/models.py @@ -74,14 +74,14 @@ class CourseManager(models.Manager): class Course(models.Model): hidden = models.BooleanField(verbose_name='Видно только оплатившим', default=False) level = models.CharField(verbose_name='Уровень', choices=COURSE_LEVEL, default='B', max_length=3) - slug = models.SlugField(max_length=255, blank=True, default='', unique=True, editable=False) - direction = models.SmallIntegerField(choices=COURSE_DIRECTION, verbose_name='Направление', null=True) + slug = models.SlugField(unique=True, editable=False, max_length=127) + direction = models.SmallIntegerField(choices=COURSE_DIRECTION, verbose_name='Направление') public = models.BooleanField(verbose_name='Опубликовать', default=False) - title = models.CharField(verbose_name="Заголовок", max_length=255) + title = models.CharField(verbose_name="Заголовок", max_length=255, unique=True) description = models.TextField(verbose_name='Описание', blank=True) image = models.URLField(verbose_name='Изображение', blank=True, max_length=255) big_image = models.URLField(verbose_name='Большое изображение', blank=True, max_length=255) - big_mobile_image = models.URLField(verbose_name='Под мобилку', blank=True, null=True, + big_mobile_image = models.URLField(verbose_name='Под мобилку', blank=True, help_text='Большая картинка для мобильной версии', max_length=255) teachers = ArrayField( models.CharField(max_length=15, blank=True, verbose_name='Ссылки на преподов'), default=[]) @@ -117,12 +117,12 @@ class Vertex(models.Model): ) topic = models.ForeignKey(to=Topic, verbose_name='Тема') title = models.CharField(verbose_name='Название', max_length=255) - free = models.BooleanField(default=True, verbose_name='Привилегии для узла не будут проверяться') + free = models.BooleanField(default=False, verbose_name='Привилегии для узла не будут проверяться') description = models.TextField(verbose_name='Описание', blank=True, null=True) - video = models.TextField(verbose_name='Код видео', default='', blank=True, null=True) + video = models.TextField(verbose_name='Код видео', blank=True, null=True) materials = ArrayField(models.CharField(max_length=15, blank=True, verbose_name='Материалы урока')) valid_type = models.SmallIntegerField(choices=VALID_TYPE, default=0) - token = models.CharField(max_length=15, verbose_name="Ключ доступа к узлу", unique=True) + token = models.CharField(max_length=15, verbose_name="Ключ доступа к узлу", unique=True, editable=False) def __str__(self): return self.title diff --git a/course_service/maps/migrations/0001_initial.py b/course_service/maps/migrations/0001_initial.py index 72aca92..2a4cd45 100644 --- a/course_service/maps/migrations/0001_initial.py +++ b/course_service/maps/migrations/0001_initial.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-13 23:00 +# Generated by Django 1.11.6 on 2017-12-17 18:03 from __future__ import unicode_literals from django.db import migrations, models @@ -19,7 +19,7 @@ class Migration(migrations.Migration): name='CourseMap', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(default='Линейное прохождение', max_length=255, verbose_name='Имя прохождения')), + ('name', models.CharField(max_length=255, verbose_name='Имя прохождения')), ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='К какому курсу привязан')), ], options={ @@ -32,7 +32,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('out_key', models.CharField(editable=False, max_length=15, unique=True, verbose_name='Ключ для внешних сервисов')), - ('name', models.CharField(blank=True, max_length=255, null=True, verbose_name='Имя шаблона')), + ('name', models.CharField(max_length=255, verbose_name='Имя шаблона')), ('is_template', models.BooleanField(default=True, verbose_name='Может ли быть использован как шаблон')), ], options={ @@ -45,7 +45,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('sort', models.SmallIntegerField(verbose_name='Порядок сортировки')), - ('map_course', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='maps.CourseMap', verbose_name='К какой сортеровке имеетотношение')), + ('map_course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='maps.CourseMap', verbose_name='К какой сортировке имеетотношение')), ('route', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='maps.CourseRoute', verbose_name='К какому узлу')), ], options={ @@ -59,7 +59,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('sort', models.SmallIntegerField(verbose_name='Порядок сортировки')), - ('map_course', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='maps.CourseMap', verbose_name='К какой сортеровке имеетотношение')), + ('map_course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='maps.CourseMap', verbose_name='К какой сортировке имеетотношение')), ('vertex', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Vertex', verbose_name='К какому узлу')), ], options={ @@ -74,6 +74,10 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name='pivotcoursemap', - unique_together=set([('map_course', 'route'), ('sort', 'route')]), + unique_together=set([('sort', 'route'), ('map_course', 'route')]), + ), + migrations.AlterUniqueTogether( + name='coursemap', + unique_together=set([('course', 'name')]), ), ] diff --git a/course_service/maps/migrations/0002_auto_20171215_1329.py b/course_service/maps/migrations/0002_auto_20171215_1329.py deleted file mode 100644 index f77c101..0000000 --- a/course_service/maps/migrations/0002_auto_20171215_1329.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-15 13:29 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('courses', '0003_auto_20171214_1513'), - ('maps', '0001_initial'), - ] - - operations = [ - migrations.AlterUniqueTogether( - name='coursemap', - unique_together=set([('course', 'name')]), - ), - ] diff --git a/course_service/maps/models.py b/course_service/maps/models.py index 851a33b..3eaddce 100644 --- a/course_service/maps/models.py +++ b/course_service/maps/models.py @@ -10,7 +10,7 @@ class CourseRoute(models.Model): определяет способ прохождения по курсу. """ out_key = models.CharField(max_length=15, unique=True, verbose_name="Ключ для внешних сервисов", editable=False) - name = models.CharField(max_length=255, verbose_name='Имя шаблона', blank=True, null=True) + name = models.CharField(max_length=255, verbose_name='Имя шаблона') is_template = models.BooleanField(default=True, verbose_name='Может ли быть использован как шаблон') def __str__(self): @@ -26,7 +26,7 @@ class CourseMap(models.Model): Способы отображения курса. Упорядочены в порядке возрастания приоретета. """ course = models.ForeignKey(to='courses.Course', verbose_name='К какому курсу привязан') - name = models.CharField(max_length=255, verbose_name="Имя прохождения", default="Линейное прохождение") + name = models.CharField(max_length=255, verbose_name="Имя прохождения") def __str__(self): return '''Линейное прохождение по курсу "%s"''' % self.course.title @@ -40,8 +40,7 @@ class CourseMap(models.Model): class PivotCourseMap(models.Model): route = models.ForeignKey(to=CourseRoute, verbose_name="К какому узлу") sort = models.SmallIntegerField(verbose_name='Порядок сортировки') - map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортеровке имеетотношение', blank=True, - null=True) + map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортировке имеетотношение') def __str__(self): return '''Карта с №%s по маршруту ID%s''' % (self.sort, self.route_id) @@ -56,8 +55,7 @@ class PivotCourseMap(models.Model): class PivotVertex(models.Model): vertex = models.ForeignKey(to='courses.Vertex', verbose_name="К какому узлу") sort = models.SmallIntegerField(verbose_name='Порядок сортировки') - map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортеровке имеетотношение', blank=True, - null=True) + map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортировке имеетотношение') def __str__(self): return '''Карта с №%s по линейному прохождению ID%s''' % (self.sort, self.map_course_id) diff --git a/csv/load_comments.py b/csv/load_comments.py index 219facf..dc026bd 100644 --- a/csv/load_comments.py +++ b/csv/load_comments.py @@ -7,6 +7,7 @@ import os import sys from django.contrib.auth import get_user_model +from django.db import IntegrityError sys.path.append("../") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings") @@ -14,21 +15,23 @@ django.setup() from course_service.courses.models import Vertex from storage.models import Comment, File -from access.models.other import PivotProgressVertex +from access.models.other import PivotProgressVertex, Progress if __name__ == '__main__': - Comment.objects.all().delete() csv.field_size_limit(500 * 1024 * 1024) with open('./management/comment.csv') as comment_csv: comment_reader = csv.DictReader(comment_csv) for row in comment_reader: if row['type'] == 'task' or row['type'] == 'exam': - c = Comment.objects.create( - id=row['id'], - email=row['owner__email'], - text=row['text'], - key=''.join(random.choice(string.ascii_letters) for x in range(15)), - ) + try: + c = Comment.objects.create( + id=row['id'], + email=row['owner__email'], + text=row['text'], + key=''.join(random.choice(string.ascii_letters) for x in range(15)), + ) + except IntegrityError: + c = Comment.objects.get(id=row['id']) for file_id in row['files'].split("[")[1].split("]")[0].split(", "): if file_id: @@ -37,16 +40,22 @@ if __name__ == '__main__': c.date = row['date'] c.save() - parent_id = row['parent_id'] + parent_id = int(row['parent_id']) if row['type'] == 'task': parent_id += 50 vertex = Vertex.objects.get(id=parent_id) vertex_key = vertex.token comment_key = c.key + progress = Progress( + route=vertex.topic.course.route.out_key, + user=get_user_model().objects.get(email=row['student'])) - PivotProgressVertex.objects.get_or_create( - comment=comment_key, + pv, _is_create = PivotProgressVertex.objects.get_or_create( vertex=vertex_key, - progress=vertex.topic.course.route.out_key + progress=progress, + teacher=get_user_model().objects.get(email=row['teacher']), ) + + pv.status = 0 if row['status'] == 'Отклонено' else 2 if row['status'] == 'Отклонено' else 1 + pv.save() diff --git a/finance/migrations/0001_initial.py b/finance/migrations/0001_initial.py index 4234496..a868bf8 100644 --- a/finance/migrations/0001_initial.py +++ b/finance/migrations/0001_initial.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-13 23:00 +# Generated by Django 1.11.6 on 2017-12-17 18:03 from __future__ import unicode_literals from django.conf import settings @@ -21,9 +21,9 @@ class Migration(migrations.Migration): name='Bill', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('course', models.CharField(max_length=255, verbose_name='Токен роута')), + ('route', models.CharField(max_length=15, verbose_name='Токен роута')), ('comment', models.TextField(blank=True, editable=False, help_text='Будет показано пользователю', verbose_name='Комментарий продавца')), - ('description', models.TextField(default='', verbose_name='Внутренняя заметка')), + ('description', models.TextField(blank=True, verbose_name='Внутренняя заметка')), ('opener', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Ответственный сотрудник')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bill_user', to=settings.AUTH_USER_MODEL, verbose_name='Плательщик')), ], @@ -37,10 +37,10 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('status', models.CharField(choices=[('W', 'Ожидание согласия'), ('P', 'На оплате'), ('F', 'Оплачен'), ('C', 'Отклонен')], default='W', max_length=1, verbose_name='Статус')), - ('price', models.IntegerField(blank=True, null=True, verbose_name='Сумма')), - ('real_price', models.IntegerField(blank=True, help_text='Сумма, минус комиссия', null=True, verbose_name='Полученная сумма')), + ('price', models.IntegerField(editable=False, verbose_name='Сумма')), + ('real_price', models.IntegerField(blank=True, editable=False, help_text='Сумма, минус комиссия', null=True, verbose_name='Полученная сумма')), ('method', models.CharField(choices=[('C', 'Наличные'), ('H', 'JustClick'), ('A', 'Альфа-Банк'), ('S', 'SimplePay'), ('Y', 'YandexKassa')], default='Y', max_length=2, verbose_name='Способ оплаты')), - ('key', models.CharField(blank=True, max_length=255, null=True, verbose_name='Ключ платежа')), + ('key', models.CharField(blank=True, editable=False, max_length=255, unique=True, verbose_name='Ключ платежа')), ('comment', models.TextField(blank=True, editable=False, help_text='Будет показано пользователю', verbose_name='Комментарий продавца')), ('is_open', models.BooleanField(default=True, verbose_name='Открывает ли платёж курс')), ('date', models.DateTimeField(auto_now_add=True)), @@ -54,6 +54,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name='bill', - unique_together=set([('course', 'opener', 'user')]), + unique_together=set([('route', 'user')]), ), ] diff --git a/finance/migrations/0002_auto_20171214_1405.py b/finance/migrations/0002_auto_20171214_1405.py deleted file mode 100644 index 67892e9..0000000 --- a/finance/migrations/0002_auto_20171214_1405.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-14 14:05 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('finance', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='bill', - name='route', - field=models.CharField(default='', max_length=15, unique=True, verbose_name='Токен роута'), - preserve_default=False, - ), - migrations.AlterUniqueTogether( - name='bill', - unique_together=set([]), - ), - migrations.RemoveField( - model_name='bill', - name='course', - ), - ] diff --git a/finance/migrations/0003_auto_20171214_1406.py b/finance/migrations/0003_auto_20171214_1406.py deleted file mode 100644 index 7f87f0f..0000000 --- a/finance/migrations/0003_auto_20171214_1406.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-14 14:06 -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), - ('finance', '0002_auto_20171214_1405'), - ] - - operations = [ - migrations.AlterField( - model_name='bill', - name='route', - field=models.CharField(max_length=15, verbose_name='Токен роута'), - ), - migrations.AlterUniqueTogether( - name='bill', - unique_together=set([('route', 'opener', 'user')]), - ), - ] diff --git a/finance/models.py b/finance/models.py index df0177f..6ecb33b 100755 --- a/finance/models.py +++ b/finance/models.py @@ -12,7 +12,7 @@ class Bill(models.Model): opener = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='Ответственный сотрудник', null=True) comment = models.TextField(verbose_name='Комментарий продавца', help_text='Будет показано пользователю', blank=True, editable=False) - description = models.TextField(verbose_name='Внутренняя заметка', default='') + description = models.TextField(verbose_name='Внутренняя заметка', blank=True) def __str__(self): return '%s: %s' % (self.id, self.user) @@ -24,7 +24,7 @@ class Bill(models.Model): verbose_name = 'Счет' verbose_name_plural = 'Счета' unique_together = ( - ('route', 'opener', 'user',), + ('route', 'user',), ) @@ -43,11 +43,11 @@ class Invoice(models.Model): ('C', 'Отклонен'), ) status = models.CharField(verbose_name='Статус', max_length=1, default='W', choices=BILL_STATUSES) - price = models.IntegerField(verbose_name='Сумма', null=True, blank=True) + price = models.IntegerField(verbose_name='Сумма', editable=False) real_price = models.IntegerField(verbose_name='Полученная сумма', null=True, blank=True, - help_text='Сумма, минус комиссия') + help_text='Сумма, минус комиссия', editable=False) method = models.CharField(verbose_name='Способ оплаты', max_length=2, default='Y', choices=BILL_METHOD) - key = models.CharField(verbose_name='Ключ платежа', blank=True, max_length=255, null=True) + key = models.CharField(verbose_name='Ключ платежа', max_length=255, unique=True, editable=False, blank=True) yandex_pay = models.OneToOneField(to=Payment, blank=True, null=True) comment = models.TextField(verbose_name='Комментарий продавца', help_text='Будет показано пользователю', blank=True, editable=False) diff --git a/library/migrations/0001_initial.py b/library/migrations/0001_initial.py index e60a4d3..adf39bd 100644 --- a/library/migrations/0001_initial.py +++ b/library/migrations/0001_initial.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-13 23:00 +# Generated by Django 1.11.6 on 2017-12-17 18:03 from __future__ import unicode_literals import datetime @@ -19,14 +19,14 @@ class Migration(migrations.Migration): name='Article', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('public', models.BooleanField(default=True, verbose_name='Опубликовать')), - ('slug', models.SlugField(blank=True, default='', editable=False, max_length=255, unique=True)), + ('public', models.BooleanField(default=False, verbose_name='Опубликовать')), + ('slug', models.SlugField(editable=False, max_length=255, unique=True)), ('description', models.CharField(blank=True, max_length=255, null=True, verbose_name='Описание в заголовке для соц сетей')), ('head_image', models.ImageField(blank=True, null=True, upload_to='library', verbose_name='Картинка для соц сетей')), - ('title', models.CharField(max_length=255, verbose_name='Заголовок')), + ('title', models.CharField(max_length=255, unique=True, verbose_name='Заголовок')), ('image', models.ImageField(blank=True, null=True, upload_to='library', verbose_name='Превьюшка заливки')), ('date', models.DateTimeField(default=datetime.datetime.now, editable=False, verbose_name='Дата публикации')), - ('url', models.URLField(verbose_name='url страницы')), + ('url', models.URLField(unique=True, verbose_name='url страницы')), ], options={ 'verbose_name': 'Статья', @@ -38,7 +38,7 @@ class Migration(migrations.Migration): name='ArticleSection', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255, verbose_name='Раздел')), + ('name', models.CharField(max_length=255, unique=True, verbose_name='Раздел')), ], options={ 'verbose_name': 'Раздел статьи', @@ -49,7 +49,7 @@ class Migration(migrations.Migration): name='Tags', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255, verbose_name='Теги')), + ('name', models.CharField(max_length=255, unique=True, verbose_name='Теги')), ], options={ 'verbose_name': 'Тег', @@ -59,7 +59,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='article', name='section', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='library.ArticleSection', verbose_name='Раздел'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='library.ArticleSection', verbose_name='Раздел'), ), migrations.AddField( model_name='article', diff --git a/library/models.py b/library/models.py index 99c69f4..f902565 100755 --- a/library/models.py +++ b/library/models.py @@ -3,8 +3,9 @@ from __future__ import unicode_literals import datetime from django.db import models + class ArticleSection(models.Model): - name = models.CharField(verbose_name=u'Раздел', max_length=255) + name = models.CharField(verbose_name='Раздел', max_length=255, unique=True) def __str__(self): return '%s' % self.name @@ -16,16 +17,17 @@ class ArticleSection(models.Model): class Article(models.Model): - public = models.BooleanField(verbose_name='Опубликовать', default=True) - slug = models.SlugField(max_length=255, editable=False, blank=True, default='', unique=True) - description = models.CharField(verbose_name='Описание в заголовке для соц сетей', max_length=255, blank=True, null=True) + public = models.BooleanField(verbose_name='Опубликовать', default=False) + slug = models.SlugField(max_length=255, editable=False, unique=True) + description = models.CharField( + verbose_name='Описание в заголовке для соц сетей', max_length=255, blank=True, null=True) head_image = models.ImageField(verbose_name='Картинка для соц сетей', upload_to='library', blank=True, null=True) - title = models.CharField(verbose_name='Заголовок', max_length=255) - section = models.ForeignKey(to=ArticleSection, verbose_name='Раздел', null=True) + title = models.CharField(verbose_name='Заголовок', max_length=255, unique=True) + section = models.ForeignKey(to=ArticleSection, verbose_name='Раздел') image = models.ImageField(verbose_name='Превьюшка заливки', upload_to='library', blank=True, null=True) date = models.DateTimeField(verbose_name='Дата публикации', default=datetime.datetime.now, editable=False) tags = models.ManyToManyField(to='Tags', verbose_name='Теги', blank=True) - url = models.URLField(verbose_name='url страницы') + url = models.URLField(verbose_name='url страницы', unique=True) def __str__(self): return '%s' % self.title @@ -37,7 +39,7 @@ class Article(models.Model): class Tags(models.Model): - name = models.CharField(verbose_name=u'Теги', max_length=255) + name = models.CharField(verbose_name='Теги', max_length=255, unique=True) def __str__(self): return '%s' % self.name diff --git a/lms/settings.py b/lms/settings.py index b1858ba..5d5e3e2 100644 --- a/lms/settings.py +++ b/lms/settings.py @@ -101,6 +101,7 @@ libs = ( 'django_celery_beat', "djcelery_email", 'yandex_money', + 'phonenumber_field', 'raven.contrib.django.raven_compat', ) diff --git a/storage/migrations/0001_initial.py b/storage/migrations/0001_initial.py index 482c3a3..9b6bd6b 100644 --- a/storage/migrations/0001_initial.py +++ b/storage/migrations/0001_initial.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-13 23:00 +# Generated by Django 1.11.6 on 2017-12-17 18:03 from __future__ import unicode_literals from django.db import migrations, models @@ -19,7 +19,8 @@ class Migration(migrations.Migration): ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('email', models.CharField(max_length=63, verbose_name='email автора')), ('text', models.TextField(default='', verbose_name='Текст комментария')), - ('key', models.SlugField(unique=True, verbose_name='Получения комментария по ключу')), + ('key', models.SlugField(editable=False, unique=True, verbose_name='Получения комментария по ключу')), + ('date', models.DateTimeField(auto_now_add=True, verbose_name='Дата коментария')), ], options={ 'verbose_name': 'Коммент', @@ -30,8 +31,8 @@ class Migration(migrations.Migration): name='File', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('key', models.CharField(max_length=15, unique=True, verbose_name='Внешний ключ')), - ('original', models.FileField(max_length=255, upload_to='files', verbose_name='Файл')), + ('key', models.CharField(editable=False, max_length=15, unique=True, verbose_name='Внешний ключ')), + ('original', models.FileField(max_length=255, unique=True, upload_to='files', verbose_name='Файл')), ('name', models.CharField(blank=True, max_length=255, null=True, verbose_name='Видимое имя файла')), ], options={ diff --git a/storage/migrations/0002_auto_20171214_1908.py b/storage/migrations/0002_auto_20171214_1908.py deleted file mode 100644 index 2725f1d..0000000 --- a/storage/migrations/0002_auto_20171214_1908.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-14 19:08 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('storage', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='file', - name='key', - field=models.CharField(editable=False, max_length=15, unique=True, verbose_name='Внешний ключ'), - ), - ] diff --git a/storage/migrations/0003_comment_date.py b/storage/migrations/0003_comment_date.py deleted file mode 100644 index dea589c..0000000 --- a/storage/migrations/0003_comment_date.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-15 15:32 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.utils.timezone - - -class Migration(migrations.Migration): - - dependencies = [ - ('storage', '0002_auto_20171214_1908'), - ] - - operations = [ - migrations.AddField( - model_name='comment', - name='date', - field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now, verbose_name='Дата коментария'), - preserve_default=False, - ), - ] diff --git a/storage/migrations/0004_auto_20171215_1704.py b/storage/migrations/0004_auto_20171215_1704.py deleted file mode 100644 index 240b817..0000000 --- a/storage/migrations/0004_auto_20171215_1704.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.6 on 2017-12-15 17:04 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('storage', '0003_comment_date'), - ] - - operations = [ - migrations.AlterField( - model_name='file', - name='original', - field=models.FileField(max_length=255, unique=True, upload_to='files', verbose_name='Файл'), - ), - ] diff --git a/storage/models.py b/storage/models.py index a750d13..69a0173 100755 --- a/storage/models.py +++ b/storage/models.py @@ -38,7 +38,7 @@ class Comment(models.Model): 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="Получения комментария по ключу") + key = models.SlugField(unique=True, verbose_name="Получения комментария по ключу", editable=False) date = models.DateTimeField(auto_now_add=True, verbose_name="Дата коментария") def __str__(self):