From c0e47bc7dc1437d163b14a4f969b19471e7f290d Mon Sep 17 00:00:00 2001 From: YeonJeong Kim Date: Mon, 20 Nov 2023 22:01:56 +0900 Subject: [PATCH 1/4] :recycle: Add updated_at field in settings-backup --- backend/config/settings.py | 1 + .../migrations/0002_setting_updated_at.py | 18 ++++++++++++++++++ backend/setup/models.py | 1 + backend/setup/serializers.py | 6 ++++++ backend/setup/views.py | 3 ++- backend/weight_table/__init__.py | 0 backend/weight_table/admin.py | 3 +++ backend/weight_table/apps.py | 6 ++++++ backend/weight_table/migrations/__init__.py | 0 backend/weight_table/models.py | 3 +++ backend/weight_table/tests.py | 3 +++ backend/weight_table/views.py | 3 +++ 12 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 backend/setup/migrations/0002_setting_updated_at.py create mode 100644 backend/weight_table/__init__.py create mode 100644 backend/weight_table/admin.py create mode 100644 backend/weight_table/apps.py create mode 100644 backend/weight_table/migrations/__init__.py create mode 100644 backend/weight_table/models.py create mode 100644 backend/weight_table/tests.py create mode 100644 backend/weight_table/views.py diff --git a/backend/config/settings.py b/backend/config/settings.py index 1751779d..655a3bd3 100644 --- a/backend/config/settings.py +++ b/backend/config/settings.py @@ -114,6 +114,7 @@ def get_secret(setting, secrets=secrets): 'entry', 'setup', 'storages', + 'weight_table' ] MIDDLEWARE = [ diff --git a/backend/setup/migrations/0002_setting_updated_at.py b/backend/setup/migrations/0002_setting_updated_at.py new file mode 100644 index 00000000..393df7c0 --- /dev/null +++ b/backend/setup/migrations/0002_setting_updated_at.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.6 on 2023-11-20 12:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('setup', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='setting', + name='updated_at', + field=models.DateTimeField(auto_now=True), + ), + ] diff --git a/backend/setup/models.py b/backend/setup/models.py index 34a41a00..f976ffcf 100644 --- a/backend/setup/models.py +++ b/backend/setup/models.py @@ -16,5 +16,6 @@ class Setting(models.Model): user = models.OneToOneField('user.User', related_name='settings', on_delete=models.CASCADE) display_mode = models.IntegerField(null=False, default=0, choices=DISPLAY_CHOICE) default_menu = models.IntegerField(null=False, default=0, choices=MENU_CHOICE) + updated_at = models.DateTimeField(auto_now=True) diff --git a/backend/setup/serializers.py b/backend/setup/serializers.py index de66b8bf..7c1f4090 100644 --- a/backend/setup/serializers.py +++ b/backend/setup/serializers.py @@ -7,6 +7,7 @@ class SettingBackupSerializer(serializers.Serializer): display_mode = serializers.IntegerField(required=True) default_menu = serializers.IntegerField(required=True) + updated_at = serializers.DateTimeField(read_only=True) def validate(self, data): display_mode = data.get('display_mode') @@ -16,3 +17,8 @@ def validate(self, data): if default_menu not in [0, 1]: raise ValidationError({"default_menu": ["invalid default_menu (not 0 or 1)"]}) return data + + def to_representation(self, instance): + representation = super(SettingBackupSerializer, self).to_representation(instance) + representation['updated_at'] = instance.updated_at.strftime('%Y-%m-%d') + return representation diff --git a/backend/setup/views.py b/backend/setup/views.py index 9e999935..e3670d88 100644 --- a/backend/setup/views.py +++ b/backend/setup/views.py @@ -33,7 +33,8 @@ def get(self, request): if not Setting.objects.filter(user=user).exists(): response_data = { "display_mode": 0, - "default_menu": 0 + "default_menu": 0, + "updated_at": "" } else: curr_setting = Setting.objects.get(user=user) diff --git a/backend/weight_table/__init__.py b/backend/weight_table/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/weight_table/admin.py b/backend/weight_table/admin.py new file mode 100644 index 00000000..8c38f3f3 --- /dev/null +++ b/backend/weight_table/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/backend/weight_table/apps.py b/backend/weight_table/apps.py new file mode 100644 index 00000000..e9843a3e --- /dev/null +++ b/backend/weight_table/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class WeightTableConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'weight_table' diff --git a/backend/weight_table/migrations/__init__.py b/backend/weight_table/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/backend/weight_table/models.py b/backend/weight_table/models.py new file mode 100644 index 00000000..71a83623 --- /dev/null +++ b/backend/weight_table/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/backend/weight_table/tests.py b/backend/weight_table/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/backend/weight_table/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/backend/weight_table/views.py b/backend/weight_table/views.py new file mode 100644 index 00000000..91ea44a2 --- /dev/null +++ b/backend/weight_table/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. From d8b40c65cb8d02b7e14097067f01280ad0b29cd1 Mon Sep 17 00:00:00 2001 From: YeonJeong Kim Date: Mon, 20 Nov 2023 22:13:49 +0900 Subject: [PATCH 2/4] :card_file_box: Add weight table in models and DB --- backend/entry/models.py | 2 +- .../weight_table/migrations/0001_initial.py | 27 +++++++++++++++++++ backend/weight_table/models.py | 7 +++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 backend/weight_table/migrations/0001_initial.py diff --git a/backend/entry/models.py b/backend/entry/models.py index 43b82738..c6b9b9a3 100644 --- a/backend/entry/models.py +++ b/backend/entry/models.py @@ -30,4 +30,4 @@ class Symbol(models.Model): class FavoriteSymbol(models.Model): symbol = models.ForeignKey('Symbol', related_name='favorites', on_delete=models.CASCADE) user = models.ForeignKey('user.User', related_name='favorites', on_delete=models.CASCADE) - created_at = models.DateTimeField(auto_now_add=True) \ No newline at end of file + created_at = models.DateTimeField(auto_now_add=True) diff --git a/backend/weight_table/migrations/0001_initial.py b/backend/weight_table/migrations/0001_initial.py new file mode 100644 index 00000000..77c22659 --- /dev/null +++ b/backend/weight_table/migrations/0001_initial.py @@ -0,0 +1,27 @@ +# Generated by Django 3.2.6 on 2023-11-20 13:13 + +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), + ] + + operations = [ + migrations.CreateModel( + name='WeightTable', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('symbol_id', models.IntegerField()), + ('weight', models.TextField()), + ('updated_at', models.DateTimeField(auto_now=True)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='weight_table', to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/backend/weight_table/models.py b/backend/weight_table/models.py index 71a83623..74fc137b 100644 --- a/backend/weight_table/models.py +++ b/backend/weight_table/models.py @@ -1,3 +1,10 @@ from django.db import models + # Create your models here. + +class WeightTable(models.Model): + symbol_id = models.IntegerField(null=False, blank=False) + weight = models.TextField(null=False, blank=False) + user = models.ForeignKey('user.User', related_name='weight_table', on_delete=models.CASCADE) + updated_at = models.DateTimeField(auto_now=True) From 348f567f47352ace23c9e15c7e2ae20a06c6998e Mon Sep 17 00:00:00 2001 From: YeonJeong Kim Date: Mon, 20 Nov 2023 22:42:26 +0900 Subject: [PATCH 3/4] :sparkles: Add weight table backup related urls --- backend/config/urls.py | 1 + backend/entry/views.py | 1 - backend/weight_table/urls.py | 8 ++++++++ 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 backend/weight_table/urls.py diff --git a/backend/config/urls.py b/backend/config/urls.py index 51671bd5..746aa938 100644 --- a/backend/config/urls.py +++ b/backend/config/urls.py @@ -6,4 +6,5 @@ path('user/', include('user.urls')), path('setting/', include('setup.urls', namespace='default')), path('symbol/', include('entry.urls')), + path('weight/', include('weight_table.urls')) ] diff --git a/backend/entry/views.py b/backend/entry/views.py index cabdcdb0..6c72bce2 100644 --- a/backend/entry/views.py +++ b/backend/entry/views.py @@ -1,5 +1,4 @@ import boto3 -import botocore from rest_framework import permissions, status from rest_framework.response import Response from rest_framework.views import APIView diff --git a/backend/weight_table/urls.py b/backend/weight_table/urls.py new file mode 100644 index 00000000..008b17bd --- /dev/null +++ b/backend/weight_table/urls.py @@ -0,0 +1,8 @@ +from django.urls import path +from . import views + + +app_name = 'weight_table' +urlpatterns = [ + path('backup/', views.WeightTableBackupView.as_view(), name='backup weight table'), +] \ No newline at end of file From 6fd77fdda3372209d150702efda842c87250be7a Mon Sep 17 00:00:00 2001 From: YeonJeong Kim Date: Mon, 20 Nov 2023 23:26:35 +0900 Subject: [PATCH 4/4] :sparkles: Implement weight table backup serializer and view --- backend/weight_table/serializers.py | 39 +++++++++++++++++++++++++++++ backend/weight_table/views.py | 30 ++++++++++++++++++++-- 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 backend/weight_table/serializers.py diff --git a/backend/weight_table/serializers.py b/backend/weight_table/serializers.py new file mode 100644 index 00000000..9e677749 --- /dev/null +++ b/backend/weight_table/serializers.py @@ -0,0 +1,39 @@ +from rest_framework import serializers +from rest_framework.exceptions import ValidationError + +from entry.models import Symbol +from weight_table.models import WeightTable + + +class WeightTableBackupSerializer(serializers.Serializer): + # symbol_id + id = serializers.IntegerField(source='symbol_id', required=True) + weight = serializers.CharField(required=True) + + def validate(self, data): + id = data.get('symbol_id') + user = self.context['user'] + + all_symbols = list(Symbol.objects.values_list('id', flat=True)) + if id not in all_symbols: + raise ValidationError({"id": ["Invalid symbol (no such symbol)"]}) + + # Default symbol이 아니라면 + if id > 500: + symbol = Symbol.objects.get(id=id) + if symbol.created_by != user: + raise ValidationError({"not_mine": ["the requested symbol is created by another user"]}) + + return data + + def create(self, validated_data): + user = self.context['user'] + symbol_id = validated_data.get('symbol_id') + weight = validated_data.get('weight') + + if not WeightTable.objects.filter(user=user, symbol_id=symbol_id).exists(): + WeightTable.objects.create(user=user, symbol_id=symbol_id, weight=weight) + else: + weight_row = WeightTable.objects.get(user=user, symbol_id=symbol_id) + weight_row.weight = weight + weight_row.save() diff --git a/backend/weight_table/views.py b/backend/weight_table/views.py index 91ea44a2..59b604bb 100644 --- a/backend/weight_table/views.py +++ b/backend/weight_table/views.py @@ -1,3 +1,29 @@ -from django.shortcuts import render +from rest_framework import permissions, status +from rest_framework.response import Response +from rest_framework.views import APIView -# Create your views here. +from weight_table.models import WeightTable +from weight_table.serializers import WeightTableBackupSerializer + + +class WeightTableBackupView(APIView): + permission_classes = (permissions.IsAuthenticated,) + + def post(self, request): + user = request.user + data = request.data.get('weight_table') + + serializer = WeightTableBackupSerializer(data=data, context={'user': user}, many=True) + serializer.is_valid(raise_exception=True) + serializer.save() + + return Response(status=status.HTTP_200_OK) + + def get(self, request): + user = request.user + weight_table = WeightTable.objects.filter(user=user) + response_data = WeightTableBackupSerializer(weight_table, many=True).data + response_data = { + "weight_table": response_data + } + return Response(response_data, status=status.HTTP_200_OK)