From 29d60411c134f458d9925a67546529867d287e0a Mon Sep 17 00:00:00 2001 From: s460930 Date: Mon, 14 Dec 2020 20:01:40 +0100 Subject: [PATCH 1/7] SMART-48 create new django app - project --- rest-app/smartpicasso/app/project/__init__.py | 0 rest-app/smartpicasso/app/project/admin.py | 3 +++ rest-app/smartpicasso/app/project/apps.py | 5 +++++ .../app/project/migrations/__init__.py | 0 rest-app/smartpicasso/app/project/models.py | 3 +++ rest-app/smartpicasso/app/project/tests.py | 3 +++ rest-app/smartpicasso/app/project/views.py | 3 +++ .../__pycache__/models.cpython-38.pyc | Bin 1266 -> 1266 bytes rest-app/smartpicasso/settings.py | 3 ++- 9 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 rest-app/smartpicasso/app/project/__init__.py create mode 100644 rest-app/smartpicasso/app/project/admin.py create mode 100644 rest-app/smartpicasso/app/project/apps.py create mode 100644 rest-app/smartpicasso/app/project/migrations/__init__.py create mode 100644 rest-app/smartpicasso/app/project/models.py create mode 100644 rest-app/smartpicasso/app/project/tests.py create mode 100644 rest-app/smartpicasso/app/project/views.py diff --git a/rest-app/smartpicasso/app/project/__init__.py b/rest-app/smartpicasso/app/project/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/rest-app/smartpicasso/app/project/admin.py b/rest-app/smartpicasso/app/project/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/rest-app/smartpicasso/app/project/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/rest-app/smartpicasso/app/project/apps.py b/rest-app/smartpicasso/app/project/apps.py new file mode 100644 index 0000000..e50f77b --- /dev/null +++ b/rest-app/smartpicasso/app/project/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class ProjectConfig(AppConfig): + name = 'smartpicasso.app.project' diff --git a/rest-app/smartpicasso/app/project/migrations/__init__.py b/rest-app/smartpicasso/app/project/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/rest-app/smartpicasso/app/project/models.py b/rest-app/smartpicasso/app/project/models.py new file mode 100644 index 0000000..71a8362 --- /dev/null +++ b/rest-app/smartpicasso/app/project/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/rest-app/smartpicasso/app/project/tests.py b/rest-app/smartpicasso/app/project/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/rest-app/smartpicasso/app/project/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/rest-app/smartpicasso/app/project/views.py b/rest-app/smartpicasso/app/project/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/rest-app/smartpicasso/app/project/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/rest-app/smartpicasso/app/user_profile/__pycache__/models.cpython-38.pyc b/rest-app/smartpicasso/app/user_profile/__pycache__/models.cpython-38.pyc index 615a5950e9d2ebf7c76a343adbdb1d744eb65d7e..47aca4f6911dfe8fc17bf8b2d27d4d5b0d346a61 100644 GIT binary patch delta 19 Zcmeyw`H7P&l$V!_0SI=rZRC2v0suAa1z`XH delta 19 Zcmeyw`H7P&l$V!_0SG2BY~*^u0st~z1hW7D diff --git a/rest-app/smartpicasso/settings.py b/rest-app/smartpicasso/settings.py index ee23a99..fee38e9 100644 --- a/rest-app/smartpicasso/settings.py +++ b/rest-app/smartpicasso/settings.py @@ -38,7 +38,8 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', 'smartpicasso.app.user', - 'smartpicasso.app.user_profile' + 'smartpicasso.app.user_profile', + 'smartpicasso.app.project' ] MIDDLEWARE = [ From ee9261f504fed7e9b7f844ded52d03dbc248d59d Mon Sep 17 00:00:00 2001 From: s460930 Date: Mon, 14 Dec 2020 20:09:31 +0100 Subject: [PATCH 2/7] SMART-48 created new model in db - Project, and made migration --- rest-app/db.sqlite3 | Bin 172032 -> 172032 bytes .../__pycache__/settings.cpython-38.pyc | Bin 3500 -> 3530 bytes .../__pycache__/urls.cpython-38.pyc | Bin 1065 -> 1065 bytes .../app/project/migrations/0001_initial.py | 31 ++++++++++++++++++ rest-app/smartpicasso/app/project/models.py | 28 +++++++++++++++- .../__pycache__/models.cpython-38.pyc | Bin 1266 -> 1267 bytes .../smartpicasso/app/user_profile/models.py | 2 +- 7 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 rest-app/smartpicasso/app/project/migrations/0001_initial.py diff --git a/rest-app/db.sqlite3 b/rest-app/db.sqlite3 index d864fe3c5e86be76a82c7f9267861324c9416e76..006ab8ef5df3c5a7aa82e1abb914c4c745787830 100644 GIT binary patch delta 902 zcmZ9K&rcIU6vy|`mUb7)@T1zsy)4@zEl}DmEm{(T3pN66TBB$@XtvvS#npBpbrBB| zSu`<`3uO;`ln~VOhQt~pk+WVnc<@Jrzd)~E-O_E7GReG|`M%HO&71eu4v4h_Vw3Di zVi-1L%*MD;85x75p4~+j4}PrLyF+dGv97$sqY;k{BL~=}^5O#_FNecnh7%=G7WrZ% z90>=RNRWwAOnf4IaUwcC8XJ#}$Krc^=T^>uPu&R30Iq%u4U-`g2`2;o3 zPNfnQZ926(CGcA%z9eWB5!@F>C^}yjcv&cLyi8LCV<(Fxfl6oQsr1cM%J45Q)zntM zwqJrl?ZZ{*)c%!V$Q}sJw!2wUU91-t{EnS%+p3y!V1_QyCDo^tgRjWE>zTmvqU;@mkve&43BQ!a>&b4+zjjJmS kj_Nl!?{KX-+>P$2QO3D}RQid+4&yyW#x{`ng*--+L}mqU yjp^(c7=Z>n;M%TnoAE}=X2FK{{F@aT9`H|`V8O`*bgl*vtAmBN|L%2AB1$k(7PG`r zAp=#RK!*hz4qViP7BbWmO)$z~f$~^HBbdXIt6(`%Lq-KOu_8B3tfsz}`g+KOMn!B; z2`w_AQ(3AaRmI&VS!k1uEo=)Fo?zHXRC2J3J?!HEhd4qf<*~e?g9R#1aQed1?(9FE z%Y2cT{OAuyQP}t6c;NX_v@)-DHrCXc@_uT$Gn&1vs`;<6HvBTs=MCCXIXqF7cWN7V&{ z)Tq;-N$kv6v6>jCBu`5Utg$}IvJnStCVH%-NSiHx)25T^cB(sL<&2crl`?x$A(R!* zs%MR^4D0MmgB}M?bLbRDiIyhEoN&q+=UmWFap_+PQ6tS2gEy7#uIK5-=i8(rG5zPD mdpCPfPkQ#9k)_U;Z)~DSMVZ2a$rx=yt>)0){Tcf)u0RSdu16BY4 diff --git a/rest-app/smartpicasso/app/project/migrations/0001_initial.py b/rest-app/smartpicasso/app/project/migrations/0001_initial.py new file mode 100644 index 0000000..3822f16 --- /dev/null +++ b/rest-app/smartpicasso/app/project/migrations/0001_initial.py @@ -0,0 +1,31 @@ +# Generated by Django 3.1.3 on 2020-12-14 19:08 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Project', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=100)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'db_table': 'project', + }, + ), + ] diff --git a/rest-app/smartpicasso/app/project/models.py b/rest-app/smartpicasso/app/project/models.py index 71a8362..e4f5eb3 100644 --- a/rest-app/smartpicasso/app/project/models.py +++ b/rest-app/smartpicasso/app/project/models.py @@ -1,3 +1,29 @@ +""" +@author p.dolata +""" + +import uuid + from django.db import models -# Create your models here. +from smartpicasso.app.user.models import User + + +class Project(models.Model): + """ + Model representing user's project + """ + id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + user = models.ForeignKey(User, on_delete=models.CASCADE) + name = models.CharField(max_length=100) + created_at = models.DateTimeField(auto_now_add=True) + updated_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return self.name + + class Meta: + """ + Meta to set table name in database + """ + db_table = 'project' diff --git a/rest-app/smartpicasso/app/user_profile/__pycache__/models.cpython-38.pyc b/rest-app/smartpicasso/app/user_profile/__pycache__/models.cpython-38.pyc index 47aca4f6911dfe8fc17bf8b2d27d4d5b0d346a61..80f08c37d919f6abd102f5f7177255c375bda26f 100644 GIT binary patch delta 49 ycmeyw`I(b9l$V!_0SMk~zaB5Pk(ZZQ)Pzd`3Vc&b5*14F6^c_!HtR7TVFUm{m<=re delta 48 xcmey&`H7P^l$V!_0SI=rU5^*t$ji$tV$7ug1-_{zi3%n83dO0L^_h<_0stl~3{(IB diff --git a/rest-app/smartpicasso/app/user_profile/models.py b/rest-app/smartpicasso/app/user_profile/models.py index 8f25c64..e14ef4a 100644 --- a/rest-app/smartpicasso/app/user_profile/models.py +++ b/rest-app/smartpicasso/app/user_profile/models.py @@ -22,6 +22,6 @@ class UserProfile(models.Model): class Meta: """ - Meta to se table name in database + Meta to set table name in database """ db_table = 'user_profile' From 97c968c3cb255eb19042e36eecc8cf3555b8b338 Mon Sep 17 00:00:00 2001 From: s460930 Date: Mon, 14 Dec 2020 20:29:38 +0100 Subject: [PATCH 3/7] SMART-48 implemented create project endpoint --- rest-app/db.sqlite3 | Bin 172032 -> 172032 bytes .../__pycache__/urls.cpython-38.pyc | Bin 1065 -> 1110 bytes .../__pycache__/wsgi.cpython-38.pyc | Bin 580 -> 580 bytes .../smartpicasso/app/project/serializers.py | 17 +++++++++ rest-app/smartpicasso/app/project/urls.py | 11 ++++++ rest-app/smartpicasso/app/project/views.py | 33 ++++++++++++++++-- rest-app/smartpicasso/urls.py | 1 + 7 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 rest-app/smartpicasso/app/project/serializers.py create mode 100644 rest-app/smartpicasso/app/project/urls.py diff --git a/rest-app/db.sqlite3 b/rest-app/db.sqlite3 index 006ab8ef5df3c5a7aa82e1abb914c4c745787830..a535fbea4a5b141051a4e8b52e17271486c2c37c 100644 GIT binary patch delta 721 zcmaiwJ8#-x7=>-1NI?p2yH&k_)UF_Z_U9W*Wx$0v7|bP*uuzP#>npYk#IOX~?oFpi zovU`Hjnpm5Pl!5o$WUeNpJ=F(B~q02eRaJOK(=gNxoO7~6F>ISftF~|Q^~SJg zIJRkuT_}nz;2M%bI2C?mDdLV%nVQXlqxZ_ew5MqPustbj_Sj-3T-R-Pgi67+@FL%= z25?6)5B#mkUWwQ#S2}NoV#D2~=d+sSL5^|qFhe%`s<&HH8Bm!RMJ5>0RLfRd?qCXQ zd7CbGLjP6q?G_X#xE@-eAvW|my)EQ{P%m~3C)BrbxbKyGAQVTkJj%D-8LKsgyq*Kr zXe`J%vg!)@xC2FFT=#rZ45)5d97_e2XwUbAk}TC^dr&D*RiX|FoWL`H$PjEAa5;eI zaF8W&7Kb2#AP9<`BiQ+m2i`C2#q+4Nao3*T7qRsF*x9$(8Jdox*ad=JT!w#R&z?s4 zjoVSjkxlF&fNKMS$x$#1IEVxKD1}8nU)`_G01MfpKdDIi=U*)HNWO&35p2F%dYHD1 zqH!t3^Ae}^VV_okMh-NnF$0Ai!afHTp!5eSNAzwPT`RYOZqpnJoqEO=zu`efo%sESqv7lGze^EVdCT$GO$!I zGO#kTv@$Z$v#>O>G&P_8AfHKLx;;Nr6-d(1!pg+d%E&^`)Xd1#%wqZjc_xMJulboI Q0~WJ9FxbvAf$0xF03C87R}Z70u?%9_I7%-GD7%96s7 z%9O>H#oo-6&Jx9u!Wqn<$+fZO0h6R`ac*K!NkL|EVsUZ4USdIkUO`cQR%&v|;vfT7AjbiSi+v_)+X=I$GG(!4u{SfNGe>cx ha0D}Ga&GK+z%;p?d9MHuP!$V552FAx4 Date: Mon, 14 Dec 2020 20:29:50 +0100 Subject: [PATCH 4/7] SMART-48 implemented create project endpoint --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c33ae12..0d03275 100644 --- a/README.md +++ b/README.md @@ -22,4 +22,4 @@ To run tests: `pip3 install -r requirements.txt` -`python3 app.py` \ No newline at end of file +`python3 app.py` From c3a50e0552df78b5b48d5d860b49625e22445a76 Mon Sep 17 00:00:00 2001 From: s460930 Date: Tue, 15 Dec 2020 16:28:25 +0100 Subject: [PATCH 5/7] SMART-48 change implementation of create project endpoint --- rest-app/db.sqlite3 | Bin 172032 -> 172032 bytes .../__pycache__/settings.cpython-38.pyc | Bin 3530 -> 3530 bytes .../__pycache__/urls.cpython-38.pyc | Bin 1110 -> 1110 bytes rest-app/smartpicasso/app/project/urls.py | 8 +++---- rest-app/smartpicasso/app/project/views.py | 21 ++++-------------- 5 files changed, 8 insertions(+), 21 deletions(-) diff --git a/rest-app/db.sqlite3 b/rest-app/db.sqlite3 index a535fbea4a5b141051a4e8b52e17271486c2c37c..2414073beab6a27f43deb3d987b75cfdf4fec5ac 100644 GIT binary patch delta 431 zcmZoTz}0YoYl1Xm@I)DB#^A<;)&$0_2~6ww1WgqTO|6WKtW3@Ij4h4Kjm)M$$Y)a6 zZqLtjG=PhlFOPx0ith_w-p0lRzO+VWW;S1WM@Qc@gH&VlG!xS#3rlm8RO4jJv=o!X z38axG$7{R0onjD Xp9Q299M-I0Q@~6{rtNq7nN$P-`z&*3 delta 91 zcmZoTz}0YoYl1Xmz(g5m#(>6z)&$0_2~6ww1WgnSEv<~qtxQey3@uFz49%uL$Y)a6 tZqLtjG=PnfzlwpsYGY#o|MaSSrmoE_3-0hwe^Ae)0%mQ0(9fhG000Zf9o7H< diff --git a/rest-app/smartpicasso/__pycache__/settings.cpython-38.pyc b/rest-app/smartpicasso/__pycache__/settings.cpython-38.pyc index d45f22ec0d2aabc9aaa15421e5c3329c353440c2..68dbbda0dc09c8e2598ab360a1610297c3dec1ae 100644 GIT binary patch delta 20 acmX>leM*`;l$V!_0SHPi-Pp*zpBDf+9tHIP delta 20 acmX>leM*`;l$V!_0SKbEUEj#PpBDf)!Uewo diff --git a/rest-app/smartpicasso/__pycache__/urls.cpython-38.pyc b/rest-app/smartpicasso/__pycache__/urls.cpython-38.pyc index 8ca7aebd49506e1b9f27b846acd1d15a3f08de6e..d832aea1c7fd30a3ac3b86954119100184199922 100644 GIT binary patch delta 20 acmcb{agBpJl$V!_0SHPi-Pp+O%>n>8Nd;;E delta 20 acmcb{agBpJl$V!_0SG?sxxSIxn*{(nD+SO1 diff --git a/rest-app/smartpicasso/app/project/urls.py b/rest-app/smartpicasso/app/project/urls.py index 72aa447..f966670 100644 --- a/rest-app/smartpicasso/app/project/urls.py +++ b/rest-app/smartpicasso/app/project/urls.py @@ -2,10 +2,10 @@ @author: p.dolata """ -from django.conf.urls import url +from rest_framework.routers import SimpleRouter from smartpicasso.app.project.views import ProjectsView -urlpatterns = [ - url(r'^projects', ProjectsView.as_view(), name='projects') -] +router = SimpleRouter(trailing_slash=False) +router.register('projects', ProjectsView, basename="projects") +urlpatterns = router.urls diff --git a/rest-app/smartpicasso/app/project/views.py b/rest-app/smartpicasso/app/project/views.py index a20dc68..df6ffb0 100644 --- a/rest-app/smartpicasso/app/project/views.py +++ b/rest-app/smartpicasso/app/project/views.py @@ -2,31 +2,18 @@ @author p.dolata """ -from rest_framework import status -from rest_framework.generics import CreateAPIView from rest_framework.permissions import IsAuthenticated -from rest_framework.response import Response +from rest_framework.viewsets import ModelViewSet from smartpicasso.app.project.serializers import ProjectSerializer -class ProjectsView(CreateAPIView): +class ProjectsView(ModelViewSet): """ View for project endpoints """ permission_classes = (IsAuthenticated,) serializer_class = ProjectSerializer - def post(self, request): - serializer = self.serializer_class(data=request.data) - serializer.is_valid(raise_exception=True) - project = serializer.save(user=request.user) - status_code = status.HTTP_201_CREATED - response = { - 'success': 'True', - 'status_code': status_code, - 'data': { - 'id': project.id - } - } - return Response(response, status=status_code) + def perform_create(self, serializer): + serializer.save(user=self.request.user) From b313e583dc0688cc4132c57e3ee68e0550c3dd5c Mon Sep 17 00:00:00 2001 From: s460930 Date: Tue, 15 Dec 2020 16:33:28 +0100 Subject: [PATCH 6/7] SMART-52 implementation of retrieve user's projects endpoint --- rest-app/db.sqlite3 | Bin 172032 -> 172032 bytes rest-app/smartpicasso/app/project/views.py | 5 +++++ 2 files changed, 5 insertions(+) diff --git a/rest-app/db.sqlite3 b/rest-app/db.sqlite3 index 2414073beab6a27f43deb3d987b75cfdf4fec5ac..2f940d68bfed3ed880e7eeae47ba1d9e28f1f8f0 100644 GIT binary patch delta 373 zcmZoTz}0YoYl1Xm=tLQ3#?Z!utqF_^|MT-nGO+NRW#A9zTg`Kpw{m0SMjrk~O(xDp zO-El_P7aPnP3GzA_?YCTTk$bjN*Ng#8R!}s=^C0U7@Arc8(A3{=owmA7?@j3SFmSN zm_C`0NpgA>FVlP$1_p*n6C3-cALL8(X9pBw3oI7#b%5>BQuu)MU##wmmP8X&NIB3x6&H|91X6{FC@|H#WxdYpO8&G7_?#1*B+tc^=Sz h+v=J8Acoul8Ur;1A`kLED}?zVpGjf+wtglr0RS)hWPbnv delta 313 zcmZoTz}0YoYl1Xm@I)DB#^A<;tqF_^|MN32FtG4eGVq7%;Dt=!nSk!Sj9J|@Nb z@U)`T{ECQxJY!D_75{>W>?r-9vhoxk|F9~z&|-JtIp4BQpy#OH?vj{z;n!3tISDRG57kr Date: Thu, 17 Dec 2020 17:00:32 +0100 Subject: [PATCH 7/7] SMART-52 implementation of tests for projects' endpoints --- rest-app/smartpicasso/app/project/tests.py | 71 +++++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/rest-app/smartpicasso/app/project/tests.py b/rest-app/smartpicasso/app/project/tests.py index 7ce503c..376f3fb 100644 --- a/rest-app/smartpicasso/app/project/tests.py +++ b/rest-app/smartpicasso/app/project/tests.py @@ -1,3 +1,70 @@ -from django.test import TestCase +""" +@author: p.dolata +""" -# Create your tests here. +from datetime import datetime + +from django.test import TestCase +from django.urls import reverse +from rest_framework import status +from rest_framework.test import APITestCase, APIClient + +from smartpicasso.app.project.models import Project +from smartpicasso.app.user.models import User + + +class ProjectsApiTest(APITestCase): + client = APIClient() + projects_url = reverse('projects-list') + new_project = {'name': 'test_project'} + + def test_create_project_without_auth(self): + response = self.client.post(self.projects_url, self.new_project, format='json') + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + + def test_create_project_with_invalid_token(self): + self.client.force_authenticate(user=None) + response = self.client.post(self.projects_url, self.new_project, format='json') + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + + def test_create_project(self): + user = User.objects.create_user(email='test@test.com', password='test') + self.client.force_authenticate(user=user) + response = self.client.post(self.projects_url, self.new_project, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + project = Project.objects.get(id=response.data['id']) + self.assertEqual(project.user.id, user.id) + self.assertEqual(project.name, self.new_project['name']) + self.assertAlmostEqual(datetime.timestamp(project.created_at), datetime.timestamp(datetime.now()), + delta=600) + self.assertAlmostEqual(datetime.timestamp(project.updated_at), datetime.timestamp(datetime.now()), + delta=600) + + def test_get_user_projects_without_auth(self): + response = self.client.get(self.projects_url, format='json') + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + + def test_get_user_projects_with_invalid_token(self): + self.client.force_authenticate(user=None) + response = self.client.get(self.projects_url, format='json') + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + + def test_get_user_projects(self): + user = User.objects.create_user(email='test@test.com', password='test') + self.client.force_authenticate(user=user) + Project.objects.create(user=user, name='project_1') + Project.objects.create(user=user, name='project_2') + response = self.client.get(self.projects_url, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + projects = response.data + self.assertEqual(len(projects), 2) + self.assertEqual(projects[0]['name'], 'project_1') + self.assertEqual(projects[1]['name'], 'project_2') + + +class ProjectTest(TestCase): + + def test_project_str(self): + user = User.objects.create_user(email='test@test.com', password='test') + project = Project.objects.create(user=user, name='test_project') + self.assertEqual(str(project), 'test_project')