diff --git a/.gitignore b/.gitignore index abcf00e..5706bc7 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ ITRadio/ITRadioBackend/db.sqlite3 *.py[cod] node_modules/ dist/ +conf.dev/ /conf var server/proj/media @@ -17,4 +18,4 @@ server/proj/conf/settings/__init__.py __pycache__ media/ env/ -db.sqlite3 \ No newline at end of file +db.sqlite3 diff --git a/server/proj/account/schemas.py b/server/proj/account/schemas.py new file mode 100644 index 0000000..f5631ae --- /dev/null +++ b/server/proj/account/schemas.py @@ -0,0 +1,27 @@ +from rest_framework.schemas import AutoSchema +import coreapi +import coreschema + + +class UpdateUserSchema(AutoSchema): + def get_serializer_fields(self, path, method): + return [ + coreapi.Field( + name='email', + location='form', + required=False, + schema=coreschema.String(description='Email пользователя') + ), + coreapi.Field( + name='old_password', + location='form', + required=False, + schema=coreschema.String(description='Старый пароль') + ), + coreapi.Field( + name='password', + location='form', + required=False, + schema=coreschema.String(description='Новый пароль') + ), + ] \ No newline at end of file diff --git a/server/proj/account/serializers.py b/server/proj/account/serializers.py index 0951e4e..d977e33 100644 --- a/server/proj/account/serializers.py +++ b/server/proj/account/serializers.py @@ -11,11 +11,7 @@ class MyUserSerializer(ModelSerializer): class Meta: model = MyUser - fields = ('id', 'email', 'password', - 'first_name', 'last_name', - 'phone', 'date_joined', - 'number', - ) + fields = ('id', 'email', 'password', 'date_joined') extra_kwargs = { 'password': {'write_only': True}, } diff --git a/server/proj/account/views.py b/server/proj/account/views.py index 2f20787..ec5b6ea 100644 --- a/server/proj/account/views.py +++ b/server/proj/account/views.py @@ -5,12 +5,21 @@ from rest_framework_simplejwt.views import TokenObtainPairView from rest_framework.decorators import action from rest_framework import status from django.core.mail import send_mail -from django.contrib.auth.hashers import make_password +from django.contrib.auth.hashers import make_password, check_password from conf import settings from account.serializers import MyUserSerializer, MyTokenObtainPairSerializer from account.models import MyUser +from .schemas import UpdateUserSchema +from conf.settings.base import MIN_LEN_PASSWORD +from django.core.exceptions import ValidationError +from django.core.validators import validate_email + PermissionClass = IsAuthenticated if not settings.DEBUG else AllowAny + + + + class MyTokenObtainPairView(TokenObtainPairView): permission_classes = [AllowAny] serializer_class = MyTokenObtainPairSerializer @@ -53,17 +62,45 @@ class MyUserViewSet(ViewSet): token_serializer.is_valid(raise_exception=True) return Response(token_serializer.validated_data, status=status.HTTP_201_CREATED) - @action(detail=False, methods=['post']) + @action(detail=False, methods=['post'], schema=UpdateUserSchema()) def update_user(self, request): - if 'email' in request.data: - del request.data['email'] - if 'password' in request.data: - request.data['password'] = make_password(request.data['password']) - serializer = MyUserSerializer(request.user, data=request.data, partial=True) - serializer.is_valid(raise_exception=True) - serializer.save() + password = request.user.password - return Response(serializer.data) + if check_password(request.data['old_password'], password): + try: + validate_email(request.data['password']) + except ValidationError as e: + pass + else: + return Response( + {'detail': 'Почта не может являться паролем', 'error': {'email': 'Почта не может являться паролем'}}, + status=status.HTTP_400_BAD_REQUEST) + + + if len(request.data['password']) < MIN_LEN_PASSWORD: + return Response( + {'detail': 'Минимальная длина - 8 символов', 'error': {'email': 'Минимальная длина - 8 символов'}}, + status=status.HTTP_400_BAD_REQUEST) + + + if check_password(request.data['password'], password): + return Response( + {'detail': 'Пароли одинаковые', 'error': {'email': 'Пароли одинаковые'}}, + status=status.HTTP_400_BAD_REQUEST) + + if 'email' in request.data: + del request.data['email'] + if 'password' in request.data: + request.data['password'] = make_password(request.data['password']) + serializer = MyUserSerializer(request.user, data=request.data, partial=True) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data) + else: + return Response( + {'detail': 'Неверный старый пароль', 'error': {'email': 'Неверный старый пароль'}}, + status=status.HTTP_400_BAD_REQUEST) + @action(detail=False, methods=['post']) def password_reset_user(self, request): diff --git a/server/proj/api/migrations/0001_initial.py b/server/proj/api/migrations/0001_initial.py deleted file mode 100644 index 352843c..0000000 --- a/server/proj/api/migrations/0001_initial.py +++ /dev/null @@ -1,26 +0,0 @@ -# Generated by Django 5.0.4 on 2024-04-21 17:43 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='NowPlayingSong', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=255)), - ('artist', models.CharField(max_length=255)), - ('album', models.CharField(blank=True, max_length=255, null=True)), - ('genre', models.CharField(blank=True, max_length=100, null=True)), - ('art_url', models.URLField(blank=True, null=True)), - ('duration', models.IntegerField()), - ], - ), - ] diff --git a/server/proj/api/migrations/0002_remove_nowplayingsong_duration.py b/server/proj/api/migrations/0002_remove_nowplayingsong_duration.py deleted file mode 100644 index 4c45f25..0000000 --- a/server/proj/api/migrations/0002_remove_nowplayingsong_duration.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 5.0.4 on 2024-04-21 18:13 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0001_initial'), - ] - - operations = [ - migrations.RemoveField( - model_name='nowplayingsong', - name='duration', - ), - ] diff --git a/server/proj/api/migrations/0003_rename_art_url_nowplayingsong_art.py b/server/proj/api/migrations/0003_rename_art_url_nowplayingsong_art.py deleted file mode 100644 index 9482299..0000000 --- a/server/proj/api/migrations/0003_rename_art_url_nowplayingsong_art.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.0.4 on 2024-04-21 18:51 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0002_remove_nowplayingsong_duration'), - ] - - operations = [ - migrations.RenameField( - model_name='nowplayingsong', - old_name='art_url', - new_name='art', - ), - ] diff --git a/server/proj/api/migrations/0004_delete_nowplayingsong.py b/server/proj/api/migrations/0004_delete_nowplayingsong.py deleted file mode 100644 index 9a81636..0000000 --- a/server/proj/api/migrations/0004_delete_nowplayingsong.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 5.0.4 on 2024-04-24 14:17 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('api', '0003_rename_art_url_nowplayingsong_art'), - ] - - operations = [ - migrations.DeleteModel( - name='NowPlayingSong', - ), - ] diff --git a/server/proj/audio/admin.py b/server/proj/audio/admin.py index 6d86d8b..3f670a5 100644 --- a/server/proj/audio/admin.py +++ b/server/proj/audio/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from .models import Song, FavoriteSong +from .models import Song, FavoriteSong, PlayList @admin.register(Song) class SongAdmin(admin.ModelAdmin): @@ -9,3 +9,7 @@ class SongAdmin(admin.ModelAdmin): @admin.register(FavoriteSong) class FavoriteSongAdmin(admin.ModelAdmin): list_display = ('id', 'song', 'user') + +@admin.register(PlayList) +class PlayListAdmin(admin.ModelAdmin): + list_display = ('id', 'name', 'user', 'art') diff --git a/server/proj/audio/models.py b/server/proj/audio/models.py index 46cada6..b7ca203 100644 --- a/server/proj/audio/models.py +++ b/server/proj/audio/models.py @@ -23,6 +23,7 @@ class Song(models.Model): class Meta: verbose_name = 'Треки' + unique_together = ('azura_id', ) verbose_name_plural = 'Треки' @@ -36,3 +37,15 @@ class FavoriteSong(models.Model): verbose_name = 'Избранные Треки' unique_together = ('song', 'user') verbose_name_plural = 'Избранные Треки' + + +class PlayList(models.Model): + name = models.CharField('Название плейлиста', max_length=50, blank=True, null=True) + song = models.ManyToManyField(Song, blank=True, null=True) + user = models.ForeignKey(MyUser, verbose_name='Пользователь', on_delete=models.CASCADE) + art = models.ImageField('Изображение плейлиста', blank=True, null=True, upload_to="playlist_images/") + + + class Meta: + verbose_name = 'Плейлисты' + verbose_name_plural = 'Плейлисты' \ No newline at end of file diff --git a/server/proj/audio/schemas.py b/server/proj/audio/schemas.py index eea2ba5..607ef1e 100644 --- a/server/proj/audio/schemas.py +++ b/server/proj/audio/schemas.py @@ -52,4 +52,27 @@ class DeleteSongSchema(AutoSchema): required=False, schema=coreschema.String(description='ID трека с Азуры') ), + ] + +class PlayListSchema(AutoSchema): + def get_serializer_fields(self, path, method): + return [ + coreapi.Field( + name='name', + location='form', + required=False, + schema=coreschema.String(description='Название плейлиста') + ), + coreapi.Field( + name='playlist_id', + location='form', + required=False, + schema=coreschema.Integer(description='ID плейлиста') + ), + coreapi.Field( + name='azura_id', + location='form', + required=False, + schema=coreschema.String(description='ID трека с азуры') + ), ] \ No newline at end of file diff --git a/server/proj/audio/serializers.py b/server/proj/audio/serializers.py index 751389f..317777c 100644 --- a/server/proj/audio/serializers.py +++ b/server/proj/audio/serializers.py @@ -1,11 +1,24 @@ from rest_framework import serializers -from .models import Song, FavoriteSong +from .models import Song, FavoriteSong, PlayList class SongSerializer(serializers.ModelSerializer): class Meta: model = Song fields = ('id', 'unique_id', 'azura_id', 'title', 'artist', 'album', 'genre', 'art') +class PlayListSerializer(serializers.ModelSerializer): + class Meta: + model = PlayList + fields = ('id', 'name', 'song', 'user') + + def to_representation(self, instance): + rep = super().to_representation(instance) + rep["song"] = SongSerializer( + instance.song.all(), many=True).data + return rep + + + class FavoriteSongSerializer(serializers.ModelSerializer): class Meta: diff --git a/server/proj/audio/views.py b/server/proj/audio/views.py index 4767e1b..c17aaa5 100644 --- a/server/proj/audio/views.py +++ b/server/proj/audio/views.py @@ -5,14 +5,98 @@ from rest_framework.decorators import action from rest_framework import status from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from django.shortcuts import get_object_or_404, get_list_or_404 -from rest_framework.permissions import IsAuthenticated +from rest_framework.permissions import IsAuthenticated, AllowAny import requests from django.http import HttpResponse -from .schemas import SongSchema, DeleteSongSchema -from .models import Song, FavoriteSong -from .serializers import SongSerializer, FavoriteSongSerializer +from .schemas import SongSchema, DeleteSongSchema, PlayListSchema +from .models import Song, FavoriteSong, PlayList +from .serializers import SongSerializer, FavoriteSongSerializer, PlayListSerializer +class PlayListViewSet(GenericViewSet): + queryset = PlayList + serializer_class = PlayListSerializer + permission_classes = (IsAuthenticated,) + def list(self, request): + queryset = self.get_queryset().objects.filter(user=request.user) + serializer = self.get_serializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def retrieve(self, request, pk): + try: + queryset = self.get_queryset().objects.get(pk=pk, user=request.user) + serializer = self.get_serializer(queryset) + return Response(serializer.data, status=status.HTTP_200_OK) + except ObjectDoesNotExist: + return Response( + {'detail': 'Объекта не существует', 'error': {'PlayList': 'Объекта не существует'}}, + status=status.HTTP_404_NOT_FOUND) + + @action(detail=False, methods=['post'], schema=PlayListSchema()) + def create_playlist(self, request): + + if request.data.get('name', False): + try: + instance = PlayList.objects.get(pk=request.data['playlist_id'], user=request.user.pk) + data = request.data + data.update(user=request.user.pk) + serializer = self.get_serializer(data=request.data, instance=instance) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data) + except ObjectDoesNotExist: + return Response( + {'detail': 'Объекта не существует', 'error': {'PlayList': 'Объекта не существует'}}, + status=status.HTTP_404_NOT_FOUND) + else: + playlist_pk = self.get_queryset().objects.filter(user=request.user.pk) + number_playlist = len(playlist_pk) + 1 + name = f"Плейлист № {number_playlist}" + data = request.data + data.update(user=request.user.pk, name=name) + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data) + + @action(detail=False, methods=['post'], schema=PlayListSchema()) + def delete_playlist(self, request): + try: + item = PlayList.objects.get(user=request.user, pk=request.data.get('playlist_id')) + item.delete() + return Response(status=status.HTTP_202_ACCEPTED) + except ObjectDoesNotExist: + return Response( + {'detail': 'Объекта не существует', 'error': {'PlayList': 'Объекта не существует'}}, + status=status.HTTP_404_NOT_FOUND) + + @action(detail=False, methods=['post'], schema=PlayListSchema()) + def add_to_playlist(self, request): + try: + song = list(Song.objects.filter(azura_id=request.data.get('azura_id')).values_list('pk', flat=True)) + except ObjectDoesNotExist: + return Response( + {'detail': 'Песни не существует', 'error': {'Song': 'Песни не существует'}}, + status=status.HTTP_404_NOT_FOUND) + + try: + instance = PlayList.objects.get(pk=request.data.get('playlist_id')) + except ObjectDoesNotExist: + return Response( + {'detail': 'Плейлиста не существует', 'error': {'PlayList': 'Плейлиста не существует'}}, + status=status.HTTP_404_NOT_FOUND) + + songs = list(instance.song.all().values_list('pk', flat=True))+song + data = { + 'playlist_id': request.data.get('playlist_id'), + 'song': songs + } + serializer = PlayListSerializer(data=data, partial=True, instance=instance) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data) + + class SongViewSet(GenericViewSet): queryset = Song.objects.all() serializer_class = SongSerializer @@ -108,6 +192,24 @@ class SongViewSet(GenericViewSet): except ObjectDoesNotExist: return Response({"error": 'Объекта не существует'}, status=status.HTTP_404_NOT_FOUND) + @action(detail=False, methods=['get']) + def get_all_song(self, request): + file_url = "http://82.97.242.49:10084/api/station/1/files" + API_KEY = "49226d3488aac3f5:18d88659c6c1c5e131a0ce0a94d55235" + headers = { + "Authorization": f"Bearer {API_KEY}" + } + response = requests.get(file_url, headers=headers) + data = [] + for i in response.json(): + i['azura_id'] = i.pop('song_id') + data.append(i) + + + + return Response(data, status=status.HTTP_200_OK) + + \ No newline at end of file diff --git a/server/proj/conf/__pycache__/urls.cpython-310.pyc b/server/proj/conf/__pycache__/urls.cpython-310.pyc index ff18f9c..7d8c935 100644 Binary files a/server/proj/conf/__pycache__/urls.cpython-310.pyc and b/server/proj/conf/__pycache__/urls.cpython-310.pyc differ diff --git a/server/proj/conf/settings/__init__.local.py b/server/proj/conf/settings/__init__.local.py new file mode 100644 index 0000000..8f607e4 --- /dev/null +++ b/server/proj/conf/settings/__init__.local.py @@ -0,0 +1 @@ +from .local import * diff --git a/server/proj/conf/settings/__init__.py b/server/proj/conf/settings/__init__.py index e0a19b2..ac5e714 100644 --- a/server/proj/conf/settings/__init__.py +++ b/server/proj/conf/settings/__init__.py @@ -1,5 +1,4 @@ - -from .development import * +from .local import * diff --git a/server/proj/conf/settings/__pycache__/__init__.cpython-310.pyc b/server/proj/conf/settings/__pycache__/__init__.cpython-310.pyc index 158dd64..10a15ec 100644 Binary files a/server/proj/conf/settings/__pycache__/__init__.cpython-310.pyc and b/server/proj/conf/settings/__pycache__/__init__.cpython-310.pyc differ diff --git a/server/proj/conf/settings/__pycache__/base.cpython-310.pyc b/server/proj/conf/settings/__pycache__/base.cpython-310.pyc index b012966..7434b68 100644 Binary files a/server/proj/conf/settings/__pycache__/base.cpython-310.pyc and b/server/proj/conf/settings/__pycache__/base.cpython-310.pyc differ diff --git a/server/proj/conf/settings/__pycache__/development.cpython-310.pyc b/server/proj/conf/settings/__pycache__/development.cpython-310.pyc index a7b4e8e..9786e1e 100644 Binary files a/server/proj/conf/settings/__pycache__/development.cpython-310.pyc and b/server/proj/conf/settings/__pycache__/development.cpython-310.pyc differ diff --git a/server/proj/conf/settings/base.py b/server/proj/conf/settings/base.py index e8e6cfe..4b7f9be 100644 --- a/server/proj/conf/settings/base.py +++ b/server/proj/conf/settings/base.py @@ -33,12 +33,12 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - + 'rest_framework', 'corsheaders', 'rest_framework_simplejwt', 'rest_framework.authtoken', - + 'news', 'rubricks', 'loginApi', @@ -47,7 +47,7 @@ INSTALLED_APPS = [ 'api', 'account', 'config_site' - + ] MIDDLEWARE = [ @@ -132,38 +132,7 @@ LOGGING = { 'style': '{', }, }, - 'handlers': { - 'update_history': { - 'level': 'DEBUG', - 'class': 'logging.handlers.RotatingFileHandler', - 'filename': LOG_ROOT / 'update_history.log', - 'formatter': 'extended', - 'maxBytes': ROTATE_LOG_SIZE, - 'backupCount': ROTATE_LOG_COUNT, - }, - 'upload_media': { - 'level': 'DEBUG', - 'class': 'logging.handlers.RotatingFileHandler', - 'filename': LOG_ROOT / 'upload_media.log', - 'formatter': 'extended', - 'maxBytes': ROTATE_LOG_SIZE, - 'backupCount': ROTATE_LOG_COUNT, - }, - }, - 'loggers': { - 'update_history': { - 'handlers': ['update_history', ], - 'level': 'INFO', - 'propagate': False, - }, - 'upload_media': { - 'handlers': ['upload_media', ], - 'level': 'INFO', - 'propagate': False, - }, - }, } - REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly' @@ -191,3 +160,4 @@ CORS_ALLOW_CREDENTIALS = True CORS_ALLOWED_ORIGINS = [ 'http://localhost:5173', ] +MIN_LEN_PASSWORD = 8 \ No newline at end of file diff --git a/server/proj/conf/settings/development.py b/server/proj/conf/settings/development.py index 9dc9cf2..9088409 100644 --- a/server/proj/conf/settings/development.py +++ b/server/proj/conf/settings/development.py @@ -6,7 +6,7 @@ ALLOWED_HOSTS = ['*'] # Database # https://docs.djangoproject.com/en/3.2/ref/settings/#databases -""" DATABASES = { +DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'it_radio', @@ -15,12 +15,6 @@ ALLOWED_HOSTS = ['*'] 'HOST': 'localhost', 'PORT': '5433', }, -} """ -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': BASE_DIR / 'db.sqlite3', - } } REST_FRAMEWORK['DEFAULT_PERMISSION_CLASSES'] = ('rest_framework.permissions.AllowAny',) diff --git a/server/proj/conf/settings/local.py b/server/proj/conf/settings/local.py new file mode 100644 index 0000000..c540fd7 --- /dev/null +++ b/server/proj/conf/settings/local.py @@ -0,0 +1,21 @@ +import sys +from .base import * + +DEBUG = True +ALLOWED_HOSTS = ['*'] + +# Database +# https://docs.djangoproject.com/en/3.2/ref/settings/#databases +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} +REST_FRAMEWORK['DEFAULT_PERMISSION_CLASSES'] = ('rest_framework.permissions.AllowAny',) + +if len(sys.argv) >= 2 and not sys.argv[0].endswith('manage.py'): + from conf.sentry import sentry_start, SENTRY_CONFIG + + SENTRY_CONFIG['environment'] = 'local' + sentry_start(SENTRY_CONFIG) diff --git a/server/proj/conf/settings/production.py b/server/proj/conf/settings/production.py index e7c3dd3..a17a09c 100644 --- a/server/proj/conf/settings/production.py +++ b/server/proj/conf/settings/production.py @@ -2,19 +2,20 @@ import sys from .base import * DEBUG = False -ALLOWED_HOSTS = ['*'] +ALLOWED_HOSTS = ['82.97.242.49'] # Database # https://docs.djangoproject.com/en/3.2/ref/settings/#databases -""" DATABASES = { +DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': 'ldirect', - 'USER': 'flexites', - 'PASSWORD': 'flexites', + 'NAME': 'itradio', + 'USER': 'postgres', + 'PASSWORD': '55667788Vxod', 'HOST': 'localhost', + 'PORT': '5432', }, -} """ +} if len(sys.argv) >= 2 and sys.argv[1] != 'runserver': from conf.sentry import sentry_start, SENTRY_CONFIG diff --git a/server/proj/conf/urls.py b/server/proj/conf/urls.py index f439fab..2bc3e01 100644 --- a/server/proj/conf/urls.py +++ b/server/proj/conf/urls.py @@ -12,12 +12,13 @@ from userProfile.views import TeamViewSet from django.conf import settings from rubricks.views import RubricViewSet from api.views import FetchAndServeFile -from audio.views import SongViewSet +from audio.views import SongViewSet, PlayListViewSet router = routers.DefaultRouter() router.register(r'teams', TeamViewSet, basename='teams') router.register(r'rubriks', RubricViewSet, basename='rubriks') +router.register(r'playlists', PlayListViewSet, basename='playlists') router.register(r'song', SongViewSet, basename='song') router.register(r'fetchandservefile', FetchAndServeFile, basename='fetchandservefile') diff --git a/server/proj/news/migrations/0001_initial.py b/server/proj/news/migrations/0001_initial.py index dac12a9..76d0977 100644 --- a/server/proj/news/migrations/0001_initial.py +++ b/server/proj/news/migrations/0001_initial.py @@ -1,5 +1,6 @@ -# Generated by Django 5.0.4 on 2024-04-16 15:16 +# Generated by Django 5.0.6 on 2024-06-19 12:09 +import django.utils.timezone from django.db import migrations, models @@ -12,13 +13,11 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='News', + name='HistoryRadio', fields=[ - ('id', models.BigAutoField(primary_key=True, serialize=False)), - ('name', models.CharField(max_length=255)), - ('description', models.TextField()), - ('date', models.DateTimeField()), - ('author', models.CharField(max_length=255)), + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('description', models.CharField(max_length=50, verbose_name='Описание события кратко')), + ('date', models.DateField(default=django.utils.timezone.now, null=True, verbose_name='Дата события')), ], ), ] diff --git a/server/proj/news/migrations/0002_alter_news_author_alter_news_date.py b/server/proj/news/migrations/0002_alter_news_author_alter_news_date.py deleted file mode 100644 index 85ef135..0000000 --- a/server/proj/news/migrations/0002_alter_news_author_alter_news_date.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 5.0.4 on 2024-04-16 15:47 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('news', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='news', - name='author', - field=models.CharField(blank=True, max_length=255), - ), - migrations.AlterField( - model_name='news', - name='date', - field=models.DateTimeField(blank=True), - ), - ] diff --git a/server/proj/news/migrations/__pycache__/0001_initial.cpython-310.pyc b/server/proj/news/migrations/__pycache__/0001_initial.cpython-310.pyc index 6e4bf6d..d544853 100644 Binary files a/server/proj/news/migrations/__pycache__/0001_initial.cpython-310.pyc and b/server/proj/news/migrations/__pycache__/0001_initial.cpython-310.pyc differ diff --git a/server/proj/news/migrations/__pycache__/0002_alter_news_author_alter_news_date.cpython-310.pyc b/server/proj/news/migrations/__pycache__/0002_alter_news_author_alter_news_date.cpython-310.pyc index f925faa..5d04926 100644 Binary files a/server/proj/news/migrations/__pycache__/0002_alter_news_author_alter_news_date.cpython-310.pyc and b/server/proj/news/migrations/__pycache__/0002_alter_news_author_alter_news_date.cpython-310.pyc differ diff --git a/server/proj/rubricks/migrations/0001_initial.py b/server/proj/rubricks/migrations/0001_initial.py index 591699c..fce9c1f 100644 --- a/server/proj/rubricks/migrations/0001_initial.py +++ b/server/proj/rubricks/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 5.0.4 on 2024-04-16 15:16 +# Generated by Django 5.0.6 on 2024-06-19 12:09 from django.db import migrations, models @@ -14,10 +14,15 @@ class Migration(migrations.Migration): migrations.CreateModel( name='Rubric', fields=[ - ('id', models.BigAutoField(primary_key=True, serialize=False)), - ('name', models.CharField(max_length=255)), - ('description', models.TextField()), - ('time', models.DateTimeField()), + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='Название рубрики')), + ('title', models.TextField(default='Null', max_length=1000, null=True, verbose_name='Заголовок рубрики')), + ('description', models.TextField(max_length=1000, verbose_name='Описание рубрики')), + ('img', models.ImageField(blank=True, null=True, upload_to='images/', verbose_name='Изображение рубрики')), ], + options={ + 'verbose_name': 'Рубрики', + 'verbose_name_plural': 'Рубрики', + }, ), ] diff --git a/server/proj/rubricks/migrations/0002_alter_rubric_time.py b/server/proj/rubricks/migrations/0002_alter_rubric_time.py deleted file mode 100644 index 9be64ae..0000000 --- a/server/proj/rubricks/migrations/0002_alter_rubric_time.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.0.4 on 2024-04-16 16:10 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('rubricks', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='rubric', - name='time', - field=models.DateTimeField(blank=True), - ), - ] diff --git a/server/proj/rubricks/migrations/0003_remove_rubric_time.py b/server/proj/rubricks/migrations/0003_remove_rubric_time.py deleted file mode 100644 index be34255..0000000 --- a/server/proj/rubricks/migrations/0003_remove_rubric_time.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 5.0.4 on 2024-05-06 19:19 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('rubricks', '0002_alter_rubric_time'), - ] - - operations = [ - migrations.RemoveField( - model_name='rubric', - name='time', - ), - ] diff --git a/server/proj/rubricks/migrations/__pycache__/0001_initial.cpython-310.pyc b/server/proj/rubricks/migrations/__pycache__/0001_initial.cpython-310.pyc index f35ca27..1edbec6 100644 Binary files a/server/proj/rubricks/migrations/__pycache__/0001_initial.cpython-310.pyc and b/server/proj/rubricks/migrations/__pycache__/0001_initial.cpython-310.pyc differ diff --git a/server/proj/rubricks/migrations/__pycache__/0002_alter_rubric_time.cpython-310.pyc b/server/proj/rubricks/migrations/__pycache__/0002_alter_rubric_time.cpython-310.pyc index 3d2a31a..36ffb17 100644 Binary files a/server/proj/rubricks/migrations/__pycache__/0002_alter_rubric_time.cpython-310.pyc and b/server/proj/rubricks/migrations/__pycache__/0002_alter_rubric_time.cpython-310.pyc differ diff --git a/server/proj/rubricks/migrations/__pycache__/0003_remove_rubric_time.cpython-310.pyc b/server/proj/rubricks/migrations/__pycache__/0003_remove_rubric_time.cpython-310.pyc index bc0e1e4..41afd3a 100644 Binary files a/server/proj/rubricks/migrations/__pycache__/0003_remove_rubric_time.cpython-310.pyc and b/server/proj/rubricks/migrations/__pycache__/0003_remove_rubric_time.cpython-310.pyc differ diff --git a/server/proj/userProfile/__pycache__/admin.cpython-310.pyc b/server/proj/userProfile/__pycache__/admin.cpython-310.pyc index 5c71264..917d8e3 100644 Binary files a/server/proj/userProfile/__pycache__/admin.cpython-310.pyc and b/server/proj/userProfile/__pycache__/admin.cpython-310.pyc differ diff --git a/server/proj/userProfile/__pycache__/models.cpython-310.pyc b/server/proj/userProfile/__pycache__/models.cpython-310.pyc index 9369b5d..58f92d9 100644 Binary files a/server/proj/userProfile/__pycache__/models.cpython-310.pyc and b/server/proj/userProfile/__pycache__/models.cpython-310.pyc differ diff --git a/server/proj/userProfile/__pycache__/serializers.cpython-310.pyc b/server/proj/userProfile/__pycache__/serializers.cpython-310.pyc index 5776f84..af1cb6a 100644 Binary files a/server/proj/userProfile/__pycache__/serializers.cpython-310.pyc and b/server/proj/userProfile/__pycache__/serializers.cpython-310.pyc differ diff --git a/server/proj/userProfile/__pycache__/views.cpython-310.pyc b/server/proj/userProfile/__pycache__/views.cpython-310.pyc index 8aee8d4..79e0a8c 100644 Binary files a/server/proj/userProfile/__pycache__/views.cpython-310.pyc and b/server/proj/userProfile/__pycache__/views.cpython-310.pyc differ diff --git a/server/proj/userProfile/admin.py b/server/proj/userProfile/admin.py index 72b223f..86b745d 100644 --- a/server/proj/userProfile/admin.py +++ b/server/proj/userProfile/admin.py @@ -1,13 +1,9 @@ from django.contrib import admin - from rest_framework.authtoken.admin import TokenAdmin from .models import Team - - TokenAdmin.raw_id_fields = ['user'] - @admin.register(Team) class TeamAdmin(admin.ModelAdmin): list_display = ('id', 'name', 'last_name', 'position', 'img_person') diff --git a/server/proj/userProfile/migrations/0001_initial.py b/server/proj/userProfile/migrations/0001_initial.py index 9237e7f..de79f13 100644 --- a/server/proj/userProfile/migrations/0001_initial.py +++ b/server/proj/userProfile/migrations/0001_initial.py @@ -1,7 +1,5 @@ -# Generated by Django 5.0.4 on 2024-04-25 14:58 +# Generated by Django 5.0.6 on 2024-06-19 12:09 -import django.db.models.deletion -from django.conf import settings from django.db import migrations, models @@ -10,16 +8,21 @@ class Migration(migrations.Migration): initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( - name='Profile', + name='Team', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('likedSongs', models.JSONField(default=list)), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('name', models.CharField(max_length=50, verbose_name='Имя участника')), + ('last_name', models.CharField(max_length=50, verbose_name='Фамилия участника')), + ('position', models.CharField(max_length=50, verbose_name='Должность участинка')), + ('img_person', models.ImageField(blank=True, null=True, upload_to='team_images/', verbose_name='Изображение участника')), ], + options={ + 'verbose_name': 'Команда', + 'verbose_name_plural': 'Команда', + }, ), ] diff --git a/server/proj/userProfile/migrations/0002_alter_profile_likedsongs.py b/server/proj/userProfile/migrations/0002_alter_profile_likedsongs.py deleted file mode 100644 index dad5ae5..0000000 --- a/server/proj/userProfile/migrations/0002_alter_profile_likedsongs.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.0.4 on 2024-05-06 19:19 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('userProfile', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='profile', - name='likedSongs', - field=models.JSONField(blank=True, null=True), - ), - ] diff --git a/server/proj/userProfile/migrations/__pycache__/0001_initial.cpython-310.pyc b/server/proj/userProfile/migrations/__pycache__/0001_initial.cpython-310.pyc index 2da3b86..f4b7d3a 100644 Binary files a/server/proj/userProfile/migrations/__pycache__/0001_initial.cpython-310.pyc and b/server/proj/userProfile/migrations/__pycache__/0001_initial.cpython-310.pyc differ diff --git a/server/proj/userProfile/migrations/__pycache__/0002_alter_profile_likedsongs.cpython-310.pyc b/server/proj/userProfile/migrations/__pycache__/0002_alter_profile_likedsongs.cpython-310.pyc index 4ba943f..6bb9b3e 100644 Binary files a/server/proj/userProfile/migrations/__pycache__/0002_alter_profile_likedsongs.cpython-310.pyc and b/server/proj/userProfile/migrations/__pycache__/0002_alter_profile_likedsongs.cpython-310.pyc differ diff --git a/server/proj/userProfile/models.py b/server/proj/userProfile/models.py index 3555a46..b84852f 100644 --- a/server/proj/userProfile/models.py +++ b/server/proj/userProfile/models.py @@ -2,34 +2,6 @@ from django.contrib.auth.models import User from django.db import models from django.db.models import JSONField -""" class Profile(models.Model): - user = models.OneToOneField(User, on_delete=models.CASCADE) - - likedSongs = JSONField(blank=True, null=True) - """ - - # likedSongs = models.ManyToManyField(Song) - # likedSongs = models.TextField() - # podcasts = models.ManyToManyField(Podcast) - # playlists = models.ManyToManyField(Playlist) - - -# #JWT -# from django.contrib.auth.models import User -# from rest_framework.authtoken.models import Token - -# for user in User.objects.all(): -# Token.objects.get_or_create(user=user) - -# from django.conf import settings -# from django.db.models.signals import post_save -# from django.dispatch import receiver - -# @receiver(post_save, sender=settings.AUTH_USER_MODEL) -# def create_auth_token(sender, instance=None, created=False, **kwargs): -# if created: -# Token.objects.create(user=instance) - class Team(models.Model): name = models.CharField('Имя участника', max_length=50) last_name = models.CharField('Фамилия участника', max_length=50) diff --git a/server/proj/userProfile/serializers.py b/server/proj/userProfile/serializers.py index 1b8a4f3..f69881f 100644 --- a/server/proj/userProfile/serializers.py +++ b/server/proj/userProfile/serializers.py @@ -2,25 +2,6 @@ from rest_framework import serializers, views, status from rest_framework.response import Response from .models import Team -""" class ProfileSerializer(serializers.ModelSerializer): - class Meta: - model = Profile - fields = ['user', 'likedSongs'] - - def update(self, instance, validated_data): - new_song = validated_data.get('likedSongs') - if new_song: - current_songs = instance.likedSongs or [] - # Check if the song ID already exists in the current songs - if not any(song['id'] == new_song['id'] for song in current_songs): - current_songs.append(new_song) - instance.likedSongs = current_songs - instance.save() - return instance - def create(self, validated_data): - validated_data['likedSongs'] = [] - return Profile.objects.create(**validated_data) """ - class TeamSerializer(serializers.ModelSerializer): class Meta: model = Team diff --git a/server/proj/userProfile/views.py b/server/proj/userProfile/views.py index 33435a2..90bf8bc 100644 --- a/server/proj/userProfile/views.py +++ b/server/proj/userProfile/views.py @@ -8,61 +8,9 @@ from rest_framework.decorators import api_view, permission_classes, action from django.contrib.auth.models import User from rest_framework_simplejwt.authentication import JWTAuthentication from rest_framework_simplejwt.exceptions import InvalidToken, AuthenticationFailed - -""" from .models import Profile, Team -from .serializers import ProfileSerializer, TeamSerializer """ - from .models import Team from .serializers import TeamSerializer -""" class ProfileViewSet(viewsets.ViewSet): - queryset = Profile.objects.all() - def list(self, request): - queryset = Profile.objects.all() - serializer = ProfileSerializer(queryset, many=True) - return Response(serializer.data) - - - @action(detail=False, methods=['post']) - def AddSong(self, request): - if request.method == 'POST': - user = request.user.pk - new_song = request.data.get('new_song') # new_song should be a dict - profile = get_object_or_404(Profile, user=user) - serializer = ProfileSerializer(profile, data={'likedSongs': new_song}, partial=True) - if serializer.is_valid(): - serializer.save() - return Response(serializer.data, status=status.HTTP_201_CREATED) - return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) - - @action(detail=False, methods=['post']) - def DeleteSong(self, request): - user = request.user.pk - song_id = request.data.get('id') # Assuming each song has a unique 'id' field - if not song_id: - return Response({'error': 'Song ID is required'}, status=status.HTTP_400_BAD_REQUEST) - profile = get_object_or_404(Profile, user=user) - if profile.likedSongs: - # Filter out the song with the given ID - updated_songs = [song for song in profile.likedSongs if song.get('id') != song_id] - profile.likedSongs = updated_songs - profile.save() - return Response({'message': 'Song deleted'}, status=status.HTTP_204_NO_CONTENT) - else: - return Response({'error': 'No songs to delete'}, status=status.HTTP_404_NOT_FOUND) - - @action( - detail=False, - methods=['get'], - url_path='getlikedsongs/', - url_name='liked_songs', - ) - def GetLikedSongs(request): - if request.method == 'GET': - user = request.user.pk - profile = get_object_or_404(Profile, user=user) - serializer = ProfileSerializer(profile) - return Response(serializer.data['likedSongs'], status=status.HTTP_200_OK) """ class TeamViewSet(ViewSet): def list(self, request): diff --git a/server/requirements.txt b/server/requirements.txt index c10edaf..fd7029d 100644 --- a/server/requirements.txt +++ b/server/requirements.txt @@ -1 +1 @@ -asgiref==3.8.1 backports.zoneinfo==0.2.1 certifi==2024.2.2 charset-normalizer==3.3.2 coreapi==2.3.3 coreschema==0.0.4 Django==4.1 django-coreapi==2.3.0 django-cors-headers==4.3.1 django-filter==24.2 djangorestframework==3.15.1 djangorestframework-simplejwt==5.3.1 idna==3.7 importlib_metadata==7.1.0 itypes==1.2.0 Jinja2==3.1.4 Markdown==3.6 MarkupSafe==2.1.5 pillow==10.3.0 psycopg2==2.9.9 PyJWT==2.8.0 pytz==2024.1 PyYAML==6.0.1 requests==2.32.2 sqlparse==0.5.0 typing_extensions==4.12.0 tzdata==2024.1 uritemplate==4.1.1 urllib3==1.26.15 zipp==3.19.0 \ No newline at end of file +asgiref==3.8.1 backports.zoneinfo==0.2.1 certifi==2024.2.2 charset-normalizer==3.3.2 coreapi==2.3.3 coreschema==0.0.4 django-coreapi==2.3.0 django-cors-headers==4.3.1 django-filter==24.2 djangorestframework==3.15.1 djangorestframework-simplejwt==5.3.1 idna==3.7 importlib_metadata==7.1.0 itypes==1.2.0 Jinja2==3.1.4 Markdown==3.6 MarkupSafe==2.1.5 pillow==10.3.0 PyJWT==2.8.0 pytz==2024.1 PyYAML==6.0.1 requests==2.32.2 sqlparse==0.5.0 typing_extensions==4.12.0 tzdata==2024.1 uritemplate==4.1.1 zipp==3.19.0 \ No newline at end of file