From 49d20705448777677023808cd5c15211312a9c71 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 14:31:02 +0300 Subject: [PATCH 01/31] Add establishment tests --- apps/establishment/tests.py | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index b64a971c..08e89f10 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -2,7 +2,10 @@ from rest_framework.test import APITestCase from account.models import User from rest_framework import status from http.cookies import SimpleCookie -from establishment.models import Employee +from establishment.models import Establishment, EstablishmentType, Employee + +from rest_framework.reverse import reverse + # Create your tests here. @@ -20,6 +23,29 @@ class BaseTestCase(APITestCase): 'refresh_token': tokkens.get('refresh_token')}) +class EstablishmentTests(BaseTestCase): + def test_establishment_CRD(self): + response = self.client.get('/api/back/establishments/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + establishment_type = EstablishmentType.objects.create(name="Test establishment type") + + data = { + 'name': 'Test establishment', + 'type_id': establishment_type.id, + } + + response = self.client.post('/api/back/establishments/', data=data, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + print(response.json()) + + response = self.client.get('/api/back/establishments/1/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + response = self.client.delete('/api/back/establishments/1/', format='json') + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + + class EmployeeTests(BaseTestCase): def test_employee_CRD(self): response = self.client.get('/api/back/establishments/employees/', format='json') @@ -39,6 +65,3 @@ class EmployeeTests(BaseTestCase): response = self.client.delete('/api/back/establishments/employees/1/', format='json') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) - - - From 00d8f09881093fddcb83148869e7cf70ee22bf1b Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 14:42:00 +0300 Subject: [PATCH 02/31] Add email tests --- apps/establishment/tests.py | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index 08e89f10..6d84cbe1 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -22,22 +22,23 @@ class BaseTestCase(APITestCase): self.client.cookies = SimpleCookie({'access_token': tokkens.get('access_token'), 'refresh_token': tokkens.get('refresh_token')}) + self.establishment_type = EstablishmentType.objects.create(name="Test establishment type") + class EstablishmentTests(BaseTestCase): def test_establishment_CRD(self): response = self.client.get('/api/back/establishments/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) - establishment_type = EstablishmentType.objects.create(name="Test establishment type") + data = { 'name': 'Test establishment', - 'type_id': establishment_type.id, + 'type_id': self.establishment_type.id, } response = self.client.post('/api/back/establishments/', data=data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) - print(response.json()) response = self.client.get('/api/back/establishments/1/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -65,3 +66,27 @@ class EmployeeTests(BaseTestCase): response = self.client.delete('/api/back/establishments/employees/1/', format='json') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + +class EmailTests(BaseTestCase): + def test_email_CRD(self): + response = self.client.get('/api/back/establishments/emails/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + establishment = Establishment.objects.create( + name="Test establishment", + establishment_type_id=self.establishment_type.id + ) + + data = { + 'email': "test@test.com", + 'establishment': establishment.id + } + + response = self.client.post('/api/back/establishments/emails/', data=data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + response = self.client.get('/api/back/establishments/emails/1/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + response = self.client.delete('/api/back/establishments/emails/1/') + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) From ee93905556107536c8db43c1fd0e162923a5451f Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 14:49:04 +0300 Subject: [PATCH 03/31] Add phone tests --- apps/establishment/tests.py | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index 6d84cbe1..43f7547f 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -2,9 +2,7 @@ from rest_framework.test import APITestCase from account.models import User from rest_framework import status from http.cookies import SimpleCookie -from establishment.models import Establishment, EstablishmentType, Employee - -from rest_framework.reverse import reverse +from establishment.models import Establishment, EstablishmentType # Create your tests here. @@ -90,3 +88,28 @@ class EmailTests(BaseTestCase): response = self.client.delete('/api/back/establishments/emails/1/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + + +class PhoneTests(BaseTestCase): + def test_phone_CRD(self): + response = self.client.get('/api/back/establishments/phones/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + establishment = Establishment.objects.create( + name="Test establishment", + establishment_type_id=self.establishment_type.id + ) + + data = { + 'phone': "+79999999999", + 'establishment': establishment.id + } + + response = self.client.post('/api/back/establishments/phones/', data=data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + response = self.client.get('/api/back/establishments/phones/1/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + response = self.client.delete('/api/back/establishments/phones/1/') + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) From e616d3970cc84a803e4c4cd593224c0af059eb65 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 14:55:34 +0300 Subject: [PATCH 04/31] Add class to test childs --- apps/establishment/tests.py | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index 43f7547f..d9573191 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -65,19 +65,25 @@ class EmployeeTests(BaseTestCase): self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) -class EmailTests(BaseTestCase): - def test_email_CRD(self): - response = self.client.get('/api/back/establishments/emails/', format='json') - self.assertEqual(response.status_code, status.HTTP_200_OK) - - establishment = Establishment.objects.create( +# Class to test childs +class ChildTestCase(BaseTestCase): + def setUp(self): + super().setUp() + self.establishment = Establishment.objects.create( name="Test establishment", establishment_type_id=self.establishment_type.id ) + +# Test childs +class EmailTests(ChildTestCase): + def test_email_CRD(self): + response = self.client.get('/api/back/establishments/emails/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + data = { 'email': "test@test.com", - 'establishment': establishment.id + 'establishment': self.establishment.id } response = self.client.post('/api/back/establishments/emails/', data=data) @@ -90,19 +96,14 @@ class EmailTests(BaseTestCase): self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) -class PhoneTests(BaseTestCase): +class PhoneTests(ChildTestCase): def test_phone_CRD(self): response = self.client.get('/api/back/establishments/phones/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) - establishment = Establishment.objects.create( - name="Test establishment", - establishment_type_id=self.establishment_type.id - ) - data = { 'phone': "+79999999999", - 'establishment': establishment.id + 'establishment': self.establishment.id } response = self.client.post('/api/back/establishments/phones/', data=data) From 014931d2c4fe550fa52a07883ca9e91d002d383f Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 15:39:53 +0300 Subject: [PATCH 05/31] Add plate tests Add is_publish to serializer Add TODO for is_publish --- apps/establishment/serializers/back.py | 4 +- apps/establishment/tests.py | 53 +++++++++++++++++++++++--- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/apps/establishment/serializers/back.py b/apps/establishment/serializers/back.py index caa13742..e20cc087 100644 --- a/apps/establishment/serializers/back.py +++ b/apps/establishment/serializers/back.py @@ -34,7 +34,9 @@ class EstablishmentListCreateSerializer(EstablishmentBaseSerializer): 'type_id', 'type', 'socials', - 'image_url' + 'image_url', + # TODO: check in admin filters + 'is_publish' ] diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index d9573191..ee4e444a 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -28,20 +28,19 @@ class EstablishmentTests(BaseTestCase): response = self.client.get('/api/back/establishments/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) - - data = { 'name': 'Test establishment', 'type_id': self.establishment_type.id, + 'is_publish': True } response = self.client.post('/api/back/establishments/', data=data, format='json') self.assertEqual(response.status_code, status.HTTP_201_CREATED) - response = self.client.get('/api/back/establishments/1/', format='json') + response = self.client.get('/api/back/establishments/2/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) - response = self.client.delete('/api/back/establishments/1/', format='json') + response = self.client.delete('/api/back/establishments/2/', format='json') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) @@ -71,7 +70,8 @@ class ChildTestCase(BaseTestCase): super().setUp() self.establishment = Establishment.objects.create( name="Test establishment", - establishment_type_id=self.establishment_type.id + establishment_type_id=self.establishment_type.id, + is_publish=True ) @@ -114,3 +114,46 @@ class PhoneTests(ChildTestCase): response = self.client.delete('/api/back/establishments/phones/1/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + + +class SocialTests(ChildTestCase): + def test_social_CRD(self): + response = self.client.get('/api/back/establishments/socials/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = { + 'title': "Test social", + 'url': 'https://testsocial.com', + 'establishment': self.establishment.id + } + + response = self.client.post('/api/back/establishments/socials/', data=data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + response = self.client.get('/api/back/establishments/socials/1/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + response = self.client.delete('/api/back/establishments/socials/1/') + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + + +class PlatesTests(ChildTestCase): + def test_plates_CRD(self): + response = self.client.get('/api/back/establishments/plates/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = { + 'title': "Test social", + 'url': 'https://testsocial.com', + 'establishment': self.establishment.id + } + + response = self.client.post('/api/back/establishments/plates/', data=data) + print(f"PLATE: {response.json()}") + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + response = self.client.get('/api/back/establishments/plates/1/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + response = self.client.delete('/api/back/establishments/plates/1/') + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) From 2f74c63fd9c2be470dd550e5ef7b3bad2ec26475 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 15:58:23 +0300 Subject: [PATCH 06/31] Fix plate tests Add menu tests --- apps/establishment/tests.py | 40 ++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index ee4e444a..726eee5b 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -1,8 +1,10 @@ +import json from rest_framework.test import APITestCase from account.models import User from rest_framework import status from http.cookies import SimpleCookie -from establishment.models import Establishment, EstablishmentType +from main.models import Currency +from establishment.models import Establishment, EstablishmentType, Menu # Create your tests here. @@ -138,14 +140,22 @@ class SocialTests(ChildTestCase): class PlatesTests(ChildTestCase): - def test_plates_CRD(self): + def test_plate_CRD(self): response = self.client.get('/api/back/establishments/plates/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) + menu = Menu.objects.create( + category=json.dumps({"en-GB": "Test category"}), + establishment=self.establishment + ) + currency = Currency.objects.create(name="Test currency") + data = { - 'title': "Test social", - 'url': 'https://testsocial.com', - 'establishment': self.establishment.id + 'name': json.dumps({"en-GB": "Test plate"}), + 'establishment': self.establishment.id, + 'price': 10, + 'menu': menu.id, + 'currency_id': currency.id } response = self.client.post('/api/back/establishments/plates/', data=data) @@ -157,3 +167,23 @@ class PlatesTests(ChildTestCase): response = self.client.delete('/api/back/establishments/plates/1/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + + +class MenusTests(ChildTestCase): + def test_menu_CRD(self): + response = self.client.get('/api/back/establishments/menus/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = { + 'category': json.dumps({"en-GB": "Test category"}), + 'establishment': self.establishment.id + } + + response = self.client.post('/api/back/establishments/menus/', data=data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + response = self.client.get('/api/back/establishments/menus/1/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + response = self.client.delete('/api/back/establishments/menus/1/') + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) From df0afc56538a320015dd63a3c4324b0b3c63dbbf Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 16:00:16 +0300 Subject: [PATCH 07/31] Fix plates RUD view --- apps/establishment/urls/back.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/establishment/urls/back.py b/apps/establishment/urls/back.py index 9c0aac73..0983efa4 100644 --- a/apps/establishment/urls/back.py +++ b/apps/establishment/urls/back.py @@ -17,7 +17,7 @@ urlpatterns = [ path('menus/', views.MenuListCreateView.as_view(), name='menu-list'), path('menus//', views.MenuRUDView.as_view(), name='menu-rud'), path('plates/', views.PlateListCreateView.as_view(), name='plates'), - path('plates//', views.PlateListCreateView.as_view(), name='plate-rud'), + path('plates//', views.PlateRUDView.as_view(), name='plate-rud'), path('socials/', views.SocialListCreateView.as_view(), name='socials'), path('socials//', views.SocialRUDView.as_view(), name='social-rud'), path('phones/', views.PhonesListCreateView.as_view(), name='phones'), From 277c7ba2ebf25e96d1a953281640ef70b4bf802d Mon Sep 17 00:00:00 2001 From: Anatoly Date: Fri, 20 Sep 2019 16:08:23 +0300 Subject: [PATCH 08/31] added field old_password to endpoint for change user password --- apps/account/serializers/common.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/apps/account/serializers/common.py b/apps/account/serializers/common.py index d5f89526..e8d6ba30 100644 --- a/apps/account/serializers/common.py +++ b/apps/account/serializers/common.py @@ -1,5 +1,6 @@ """Common account serializers""" from django.conf import settings +from django.utils.translation import gettext_lazy as _ from django.contrib.auth import password_validation as password_validators from fcm_django.models import FCMDevice from rest_framework import exceptions @@ -80,23 +81,31 @@ class ChangePasswordSerializer(serializers.ModelSerializer): """Serializer for model User.""" password = serializers.CharField(write_only=True) + old_password = serializers.CharField(write_only=True) class Meta: """Meta class""" model = models.User - fields = ('password', ) + fields = ( + 'password', + 'old_password', + ) def validate(self, attrs): """Override validate method""" password = attrs.get('password') + old_password = attrs.get('old_password') try: + # Check old password + if not self.instance.check_password(raw_password=old_password): + raise serializers.ValidationError(_('Old password mismatch.')) # Compare new password with the old ones if self.instance.check_password(raw_password=password): - raise utils_exceptions.PasswordsAreEqual() + raise serializers.ValidationError(_('Password is already in use')) # Validate password password_validators.validate_password(password=password) except serializers.ValidationError as e: - raise serializers.ValidationError(str(e)) + raise serializers.ValidationError({'detail': e.detail}) else: return attrs From 2d8b30c3eeecd759a7aeac5efc3eb1985a7e6832 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 16:10:51 +0300 Subject: [PATCH 09/31] Add patch test to plates class --- apps/establishment/tests.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index d4a6418b..c3c50617 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -161,12 +161,18 @@ class PlatesTests(ChildTestCase): } response = self.client.post('/api/back/establishments/plates/', data=data) - print(f"PLATE: {response.json()}") self.assertEqual(response.status_code, status.HTTP_201_CREATED) response = self.client.get('/api/back/establishments/plates/1/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) + update_data = { + 'name': json.dumps({"en-GB": "Test new plate"}) + } + + response = self.client.patch('/api/back/establishments/plates/1/', data=update_data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + response = self.client.delete('/api/back/establishments/plates/1/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) From aaff7fd3bae3cb3758695c470ef4de939ec68b25 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 16:22:41 +0300 Subject: [PATCH 10/31] Add schedule tests --- apps/establishment/tests.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index c3c50617..c112e067 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -39,6 +39,7 @@ class EstablishmentTests(BaseTestCase): } response = self.client.post('/api/back/establishments/', data=data, format='json') + print(f"ESTABLISHMENT: {response.json()}") self.assertEqual(response.status_code, status.HTTP_201_CREATED) response = self.client.get('/api/back/establishments/2/', format='json') @@ -141,8 +142,8 @@ class SocialTests(ChildTestCase): self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) -class PlatesTests(ChildTestCase): - def test_plate_CRD(self): +class PlateTests(ChildTestCase): + def test_plate_CRUD(self): response = self.client.get('/api/back/establishments/plates/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -177,7 +178,7 @@ class PlatesTests(ChildTestCase): self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) -class MenusTests(ChildTestCase): +class MenuTests(ChildTestCase): def test_menu_CRD(self): response = self.client.get('/api/back/establishments/menus/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -195,3 +196,18 @@ class MenusTests(ChildTestCase): response = self.client.delete('/api/back/establishments/menus/1/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + + +class EstablishShedulerTests(ChildTestCase): + def test_shedule_CRD(self): + data = { + 'weekday': 1 + } + response = self.client.post(f'/api/back/establishments/{self.establishment.id}/schedule/', data=data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + response = self.client.get(f'/api/back/establishments/{self.establishment.id}/schedule/1/') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + response = self.client.delete(f'/api/back/establishments/{self.establishment.id}/schedule/1/') + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) From 85fef10eb301371c62c1ee5ce3aa25139882a5f9 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 16:28:23 +0300 Subject: [PATCH 11/31] Fix establishment tests --- apps/establishment/tests.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index c112e067..12afdce2 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -39,13 +39,14 @@ class EstablishmentTests(BaseTestCase): } response = self.client.post('/api/back/establishments/', data=data, format='json') - print(f"ESTABLISHMENT: {response.json()}") self.assertEqual(response.status_code, status.HTTP_201_CREATED) - response = self.client.get('/api/back/establishments/2/', format='json') + establishment = response.json() + + response = self.client.get(f'/api/back/establishments/{establishment["id"]}/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) - response = self.client.delete('/api/back/establishments/2/', format='json') + response = self.client.delete(f'/api/back/establishments/{establishment["id"]}/', format='json') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) From 0d7b26bbb21efde811b45ec3bf85f75f4aa7e098 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 16:40:53 +0300 Subject: [PATCH 12/31] Add update tests --- apps/establishment/tests.py | 64 +++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index 12afdce2..04637068 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -28,7 +28,7 @@ class BaseTestCase(APITestCase): class EstablishmentTests(BaseTestCase): - def test_establishment_CRD(self): + def test_establishment_CRUD(self): response = self.client.get('/api/back/establishments/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -46,12 +46,19 @@ class EstablishmentTests(BaseTestCase): response = self.client.get(f'/api/back/establishments/{establishment["id"]}/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) + update_data = { + 'name': 'Test new establishment' + } + + response = self.client.patch(f'/api/back/establishments/{establishment["id"]}/', data=update_data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + response = self.client.delete(f'/api/back/establishments/{establishment["id"]}/', format='json') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) class EmployeeTests(BaseTestCase): - def test_employee_CRD(self): + def test_employee_CRUD(self): response = self.client.get('/api/back/establishments/employees/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -66,6 +73,13 @@ class EmployeeTests(BaseTestCase): response = self.client.get('/api/back/establishments/employees/1/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) + update_data = { + 'name': 'Test new name' + } + + response = self.client.patch('/api/back/establishments/employees/1/', data=update_data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + response = self.client.delete('/api/back/establishments/employees/1/', format='json') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) @@ -83,7 +97,7 @@ class ChildTestCase(BaseTestCase): # Test childs class EmailTests(ChildTestCase): - def test_email_CRD(self): + def test_email_CRUD(self): response = self.client.get('/api/back/establishments/emails/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -98,12 +112,19 @@ class EmailTests(ChildTestCase): response = self.client.get('/api/back/establishments/emails/1/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) + update_data = { + 'email': 'testnew@test.com' + } + + response = self.client.patch('/api/back/establishments/emails/1/', data=update_data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + response = self.client.delete('/api/back/establishments/emails/1/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) class PhoneTests(ChildTestCase): - def test_phone_CRD(self): + def test_phone_CRUD(self): response = self.client.get('/api/back/establishments/phones/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -118,12 +139,20 @@ class PhoneTests(ChildTestCase): response = self.client.get('/api/back/establishments/phones/1/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) + update_data = { + 'phone': '+79999999998' + } + + response = self.client.patch('/api/back/establishments/phones/1/', data=update_data) + print(f"PHONE: {response.json()}") + self.assertEqual(response.status_code, status.HTTP_200_OK) + response = self.client.delete('/api/back/establishments/phones/1/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) class SocialTests(ChildTestCase): - def test_social_CRD(self): + def test_social_CRUD(self): response = self.client.get('/api/back/establishments/socials/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -139,6 +168,13 @@ class SocialTests(ChildTestCase): response = self.client.get('/api/back/establishments/socials/1/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) + update_data = { + 'title': 'Test new social' + } + + response = self.client.patch('/api/back/establishments/socials/1/', data=update_data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + response = self.client.delete('/api/back/establishments/socials/1/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) @@ -180,7 +216,7 @@ class PlateTests(ChildTestCase): class MenuTests(ChildTestCase): - def test_menu_CRD(self): + def test_menu_CRUD(self): response = self.client.get('/api/back/establishments/menus/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -195,12 +231,19 @@ class MenuTests(ChildTestCase): response = self.client.get('/api/back/establishments/menus/1/', format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) + update_data = { + 'category': json.dumps({"en-GB": "Test new category"}) + } + + response = self.client.patch('/api/back/establishments/menus/1/', data=update_data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + response = self.client.delete('/api/back/establishments/menus/1/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) class EstablishShedulerTests(ChildTestCase): - def test_shedule_CRD(self): + def test_shedule_CRUD(self): data = { 'weekday': 1 } @@ -210,5 +253,12 @@ class EstablishShedulerTests(ChildTestCase): response = self.client.get(f'/api/back/establishments/{self.establishment.id}/schedule/1/') self.assertEqual(response.status_code, status.HTTP_200_OK) + update_data = { + 'weekday': 2 + } + + response = self.client.patch(f'/api/back/establishments/{self.establishment.id}/schedule/1/', data=update_data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + response = self.client.delete(f'/api/back/establishments/{self.establishment.id}/schedule/1/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) From e39bc835fd9e5f48527abd37b6b050b88daa5d99 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 16:41:24 +0300 Subject: [PATCH 13/31] Fix class name --- apps/establishment/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index 04637068..08f4ac16 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -242,7 +242,7 @@ class MenuTests(ChildTestCase): self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) -class EstablishShedulerTests(ChildTestCase): +class EstablishmentShedulerTests(ChildTestCase): def test_shedule_CRUD(self): data = { 'weekday': 1 From 4e495fa47d51b18a2f23508f76d6979f99b825f6 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 16:42:35 +0300 Subject: [PATCH 14/31] Remove debug --- apps/establishment/tests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index 08f4ac16..5de7d779 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -144,7 +144,6 @@ class PhoneTests(ChildTestCase): } response = self.client.patch('/api/back/establishments/phones/1/', data=update_data) - print(f"PHONE: {response.json()}") self.assertEqual(response.status_code, status.HTTP_200_OK) response = self.client.delete('/api/back/establishments/phones/1/') From eaac6ca8856bcee6a6bde53dc97f4dd4c5a06baf Mon Sep 17 00:00:00 2001 From: littlewolf Date: Fri, 20 Sep 2019 16:47:20 +0300 Subject: [PATCH 15/31] Fix --- apps/establishment/views/back.py | 5 +++-- apps/establishment/views/web.py | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/establishment/views/back.py b/apps/establishment/views/back.py index aa52caec..c8915e91 100644 --- a/apps/establishment/views/back.py +++ b/apps/establishment/views/back.py @@ -83,7 +83,8 @@ class EmployeeListCreateView(generics.ListCreateAPIView): queryset = models.Employee.objects.all() pagination_class = None -class EmployeeRUDView(generics.RetrieveDestroyAPIView): + +class EmployeeRUDView(generics.RetrieveUpdateDestroyAPIView): """Social RUD view.""" serializer_class = serializers.EmployeeBackSerializers - queryset = models.Employee.objects.all() \ No newline at end of file + queryset = models.Employee.objects.all() diff --git a/apps/establishment/views/web.py b/apps/establishment/views/web.py index 53382be9..7be9f49e 100644 --- a/apps/establishment/views/web.py +++ b/apps/establishment/views/web.py @@ -36,7 +36,6 @@ class EstablishmentSimilarListView(EstablishmentListView): .order_by('-total_mark')[:13] - class EstablishmentRetrieveView(EstablishmentMixin, generics.RetrieveAPIView): """Resource for getting a establishment.""" serializer_class = serializers.EstablishmentDetailSerializer From 07d17d5bf1103eb50ef4edb523de85691210abec Mon Sep 17 00:00:00 2001 From: Anatoly Date: Fri, 20 Sep 2019 16:55:04 +0300 Subject: [PATCH 16/31] refactored similar establishment endpoint --- apps/establishment/views/web.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/establishment/views/web.py b/apps/establishment/views/web.py index 53382be9..32decde0 100644 --- a/apps/establishment/views/web.py +++ b/apps/establishment/views/web.py @@ -29,12 +29,8 @@ class EstablishmentSimilarListView(EstablishmentListView): def get_queryset(self): """Override get_queryset method""" - qs = super().get_queryset() - if not qs.filter(pk=self.kwargs.get('pk')).exists(): - return qs.none() - return qs.similar(establishment_pk=self.kwargs.get('pk'))\ - .order_by('-total_mark')[:13] - + return super().get_queryset().similar(establishment_pk=self.kwargs.get('pk'))\ + .order_by('-total_mark')[:13] class EstablishmentRetrieveView(EstablishmentMixin, generics.RetrieveAPIView): From 7729ab5653d8e8f280e6538e9e84e7917e33abcb Mon Sep 17 00:00:00 2001 From: michail Date: Sat, 21 Sep 2019 17:44:27 +0500 Subject: [PATCH 17/31] Add news tests --- apps/news/tests.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/apps/news/tests.py b/apps/news/tests.py index 7ce503c2..bf6577d9 100644 --- a/apps/news/tests.py +++ b/apps/news/tests.py @@ -1,3 +1,44 @@ +from http.cookies import SimpleCookie + from django.test import TestCase +from rest_framework.test import APITestCase +from rest_framework import status + +from news.models import NewsType, News +from account.models import User # Create your tests here. + + +class BaseTestCase(APITestCase): + + def setUp(self): + self.username = 'sedragurda' + self.password = 'sedragurdaredips19' + self.email = 'sedragurda@desoz.com' + self.user = User.objects.create_user(username=self.username, email=self.email, password=self.password) + #get tokkens + tokkens = User.create_jwt_tokens(self.user) + self.client.cookies = SimpleCookie({'access_token': tokkens.get('access_token'), + 'refresh_token': tokkens.get('refresh_token')}) + self.test_news_type = NewsType.objects.create(name="Test news type") + self.test_news = News.objects.create(created_by=self.user, modified_by=self.user, title={"en-GB": "Test news"}, + news_type=self.test_news_type, description={"en-GB": "Description test news"}, + playlist=1, start="2020-12-03 12:00:00", end="2020-12-13 12:00:00", + is_publish=True) + + +class NewsTestCase(BaseTestCase): + + def test_news_list(self): + response = self.client.get("/api/web/news/") + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_news_detail(self): + response = self.client.get(f"/api/web/news/{self.test_news.id}/") + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_news_type_list(self): + response = self.client.get("/api/web/news/type/") + self.assertEqual(response.status_code, status.HTTP_200_OK) + From b8c734f5e63a6e27338d8ed6c346cd7c867dc6ee Mon Sep 17 00:00:00 2001 From: michail Date: Sun, 22 Sep 2019 15:37:51 +0500 Subject: [PATCH 18/31] Add partner tests --- apps/partner/tests.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps/partner/tests.py b/apps/partner/tests.py index a39b155a..494e7f7e 100644 --- a/apps/partner/tests.py +++ b/apps/partner/tests.py @@ -1 +1,16 @@ # Create your tests here. +from rest_framework.test import APITestCase +from rest_framework import status + +from partner.models import Partner + + +class PartnerTestCase(APITestCase): + + def setUp(self): + self.test_url = "www.example.com" + self.test_partner = Partner.objects.create(url=self.test_url) + + def test_partner_list(self): + response = self.client.get("/api/web/partner/") + self.assertEqual(response.status_code, status.HTTP_200_OK) From 20766768d8c7a560766e5ba65650f1f0afdae3f7 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Mon, 23 Sep 2019 10:12:14 +0300 Subject: [PATCH 19/31] fixed establishment filter by geo --- apps/establishment/models.py | 4 +--- apps/establishment/views/web.py | 25 ++++++++++++++----------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 042c25e0..ca9fccd3 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -219,10 +219,8 @@ class EstablishmentQuerySet(models.QuerySet): :return: all establishments within the specified radius of specified point :param unit: length unit e.g. m, km. Default is 'm'. """ - - from django.contrib.gis.measure import Distance kwargs = {unit: radius} - return self.filter(address__coordinates__distance_lte=(center, Distance(**kwargs))) + return self.filter(address__coordinates__distance_lte=(center, DistanceMeasure(**kwargs))) class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin): diff --git a/apps/establishment/views/web.py b/apps/establishment/views/web.py index 32decde0..78aa3a5f 100644 --- a/apps/establishment/views/web.py +++ b/apps/establishment/views/web.py @@ -1,5 +1,6 @@ """Establishment app views.""" +from django.contrib.gis.geos import Point from django.shortcuts import get_object_or_404 from rest_framework import generics, permissions @@ -104,23 +105,25 @@ class EstablishmentFavoritesCreateDestroyView(generics.CreateAPIView, generics.D return obj -class EstablishmentNearestRetrieveView(EstablishmentMixin, generics.ListAPIView): +class EstablishmentNearestRetrieveView(EstablishmentListView, generics.ListAPIView): """Resource for getting list of nearest establishments.""" serializer_class = serializers.EstablishmentListSerializer filter_class = filters.EstablishmentFilter def get_queryset(self): - """Overrided method 'get_queryset'.""" - from django.contrib.gis.geos import Point + """Overridden method 'get_queryset'.""" + lat = self.request.query_params.get('lat') + lon = self.request.query_params.get('lon') + radius = self.request.query_params.get('radius') + unit = self.request.query_params.get('unit') - center = Point(float(self.request.query_params["lat"]), float(self.request.query_params["lon"])) - radius = float(self.request.query_params["radius"]) - unit = self.request.query_params.get("unit", None) - by_distance_from_point_kwargs = {"center": center, "radius": radius, "unit": unit} - return super(EstablishmentNearestRetrieveView, self).get_queryset() \ - .by_distance_from_point(**{k: v for k, v in by_distance_from_point_kwargs.items() if v is not None}) \ - .by_country_code(code=self.request.country_code) \ - .annotate_in_favorites(user=self.request.user) + qs = super(EstablishmentNearestRetrieveView, self).get_queryset() + if lat and lon and radius and unit: + center = Point(float(lat), float(lon)) + filter_kwargs = {'center': center, 'radius': float(radius), 'unit': unit} + return qs.by_distance_from_point(**{k: v for k, v in filter_kwargs.items() + if v is not None}) + return qs class EstablishmentTagListView(generics.ListAPIView): From 9f89deb23b27f4a60f633739d8fc5bdf13663d70 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Mon, 23 Sep 2019 11:16:22 +0300 Subject: [PATCH 20/31] Fix establishment RUD serializer --- apps/establishment/serializers/back.py | 30 ++++++++++++++++++++++++++ apps/establishment/urls/back.py | 2 +- apps/establishment/views/back.py | 5 +++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/apps/establishment/serializers/back.py b/apps/establishment/serializers/back.py index e20cc087..7199eb54 100644 --- a/apps/establishment/serializers/back.py +++ b/apps/establishment/serializers/back.py @@ -40,6 +40,36 @@ class EstablishmentListCreateSerializer(EstablishmentBaseSerializer): ] +class EstablishmentRUDSerializer(EstablishmentBaseSerializer): + """Establishment create serializer""" + + type_id = serializers.PrimaryKeyRelatedField( + source='establishment_type', + queryset=models.EstablishmentType.objects.all(), write_only=True + ) + phones = ContactPhonesSerializer(read_only=False, many=True, ) + emails = ContactEmailsSerializer(read_only=False, many=True, ) + socials = SocialNetworkRelatedSerializers(read_only=False, many=True, ) + + class Meta: + model = models.Establishment + fields = [ + 'id', + 'name', + 'website', + 'phones', + 'emails', + 'price_level', + 'toque_number', + 'type_id', + 'type', + 'socials', + 'image_url', + # TODO: check in admin filters + 'is_publish' + ] + + class SocialNetworkSerializers(serializers.ModelSerializer): """Social network serializers.""" class Meta: diff --git a/apps/establishment/urls/back.py b/apps/establishment/urls/back.py index 0983efa4..dca5fb55 100644 --- a/apps/establishment/urls/back.py +++ b/apps/establishment/urls/back.py @@ -9,7 +9,7 @@ app_name = 'establishment' urlpatterns = [ path('', views.EstablishmentListCreateView.as_view(), name='list'), - path('/', views.EstablishmentRetrieveView.as_view(), name='detail'), + path('/', views.EstablishmentRUDView.as_view(), name='detail'), path('/schedule//', views.EstablishmentScheduleRUDView.as_view(), name='schedule-rud'), path('/schedule/', views.EstablishmentScheduleCreateView.as_view(), diff --git a/apps/establishment/views/back.py b/apps/establishment/views/back.py index c8915e91..974fca8a 100644 --- a/apps/establishment/views/back.py +++ b/apps/establishment/views/back.py @@ -13,6 +13,11 @@ class EstablishmentListCreateView(EstablishmentMixin, generics.ListCreateAPIView serializer_class = serializers.EstablishmentListCreateSerializer +class EstablishmentRUDView(generics.RetrieveUpdateDestroyAPIView): + queryset = models.Establishment.objects.all() + serializer_class = serializers.EstablishmentRUDSerializer + + class MenuListCreateView(generics.ListCreateAPIView): """Menu list create view.""" serializer_class = serializers.MenuSerializers From 217c11b9709c19540785012c36b8f4673503c8c8 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Mon, 23 Sep 2019 12:29:08 +0300 Subject: [PATCH 21/31] =?UTF-8?q?GM-124:=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=B0=D1=82=D1=8C=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D1=8C=20establishment-=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/establishment/models.py | 2 ++ apps/establishment/serializers/common.py | 1 + 2 files changed, 3 insertions(+) diff --git a/apps/establishment/models.py b/apps/establishment/models.py index ca9fccd3..5eac27fd 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -227,6 +227,8 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin): """Establishment model.""" name = models.CharField(_('name'), max_length=255, default='') + name_transliterated = models.CharField(_('Transliterated name'), + max_length=255, default='') description = TJSONField(blank=True, null=True, default=None, verbose_name=_('description'), help_text='{"en-GB":"some text"}') diff --git a/apps/establishment/serializers/common.py b/apps/establishment/serializers/common.py index 65522942..5eb1b9ae 100644 --- a/apps/establishment/serializers/common.py +++ b/apps/establishment/serializers/common.py @@ -154,6 +154,7 @@ class EstablishmentBaseSerializer(serializers.ModelSerializer): fields = [ 'id', 'name', + 'name_transliterated', 'price_level', 'toque_number', 'public_mark', From 202aabf15e5df684bb5211c882c7b950e7566633 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Mon, 23 Sep 2019 12:40:27 +0300 Subject: [PATCH 22/31] GM-124: added establishment migration --- .../0029_establishment_name_transliterated.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 apps/establishment/migrations/0029_establishment_name_transliterated.py diff --git a/apps/establishment/migrations/0029_establishment_name_transliterated.py b/apps/establishment/migrations/0029_establishment_name_transliterated.py new file mode 100644 index 00000000..54fb4ea0 --- /dev/null +++ b/apps/establishment/migrations/0029_establishment_name_transliterated.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.4 on 2019-09-23 09:20 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('establishment', '0028_auto_20190920_1205'), + ] + + operations = [ + migrations.AddField( + model_name='establishment', + name='name_transliterated', + field=models.CharField(default='', max_length=255, verbose_name='Transliterated name'), + ), + ] From 2c43a371088f111163fc4731bd0efd9c9c76f2ba Mon Sep 17 00:00:00 2001 From: Anatoly Date: Mon, 23 Sep 2019 12:49:14 +0300 Subject: [PATCH 23/31] =?UTF-8?q?GM-125:=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1?= =?UTF-8?q?=D0=BE=D1=82=D0=B0=D1=82=D1=8C=20=D0=B0=D0=B2=D1=82=D0=BE=D1=80?= =?UTF-8?q?=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8E=20=D1=87=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B7=20FB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authorization/views/common.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/authorization/views/common.py b/apps/authorization/views/common.py index 4231ed7a..bb337dce 100644 --- a/apps/authorization/views/common.py +++ b/apps/authorization/views/common.py @@ -144,7 +144,8 @@ class OAuth2SignUpView(OAuth2ViewMixin, JWTGenericViewMixin): status=status.HTTP_200_OK) return self._put_cookies_in_response( cookies=self._put_data_in_cookies(access_token=access_token, - refresh_token=refresh_token), + refresh_token=refresh_token, + permanent=True), response=response) From 466c0f80d709ea4ca8b38ac86945fc0e7dba1cf6 Mon Sep 17 00:00:00 2001 From: littlewolf Date: Mon, 23 Sep 2019 14:17:19 +0300 Subject: [PATCH 24/31] Add list read test Add detail read test --- apps/collection/tests.py | 93 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/apps/collection/tests.py b/apps/collection/tests.py index 7ce503c2..df75d00f 100644 --- a/apps/collection/tests.py +++ b/apps/collection/tests.py @@ -1,3 +1,94 @@ -from django.test import TestCase +import json +from datetime import datetime +from rest_framework.test import APITestCase +from account.models import User +from rest_framework import status +from http.cookies import SimpleCookie + +from collection.models import Collection +from location.models import Country # Create your tests here. + + +class BaseTestCase(APITestCase): + + def setUpT(self): + self.username = 'sedragurda' + self.password = 'sedragurdaredips19' + self.email = 'sedragurda@desoz.com' + self.newsletter = True + self.user = User.objects.create_user( + username=self.username, email=self.email, password=self.password) + #get tokkens + tokkens = User.create_jwt_tokens(self.user) + self.client.cookies = SimpleCookie( + {'access_token': tokkens.get('access_token'), + 'refresh_token': tokkens.get('refresh_token')}) + + +class CollectionListTests(BaseTestCase): + def test_collection_list_Read(self): + response = self.client.get('/api/web/collections/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + +class CollectionDetailTests(BaseTestCase): + + def setUp(self): + super().setUp() + + country = Country.objects.first() + if not country: + country = Country.objects.create( + name=json.dumps({"en-GB": "Test country"}), + code="test" + ) + + self.collection = Collection.objects.create( + name='Test collection', + is_publish=True, + start=datetime.now(), + end=datetime.now(), + country=country + ) + + def test_collection_detail_Read(self): + response = self.client.get(f'/api/web/collections/{self.collection.id}/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + + + # data = { + # 'name': 'Test collection', + # + # } + # + # response = self.client.post('/api/web/collections/', data=data, format='json') + # self.assertEqual(response.status_code, status.HTTP_201_CREATED) + # + # establishment = response.json() + # + # response = self.client.get(f'/api/back/establishments/{establishment["id"]}/', format='json') + # self.assertEqual(response.status_code, status.HTTP_200_OK) + # + # update_data = { + # 'name': 'Test new establishment' + # } + # + # response = self.client.patch(f'/api/back/establishments/{establishment["id"]}/', data=update_data) + # self.assertEqual(response.status_code, status.HTTP_200_OK) + # + # response = self.client.delete(f'/api/back/establishments/{establishment["id"]}/', format='json') + # self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + + +# Class to test childs +# class ChildTestCase(BaseTestCase): +# def setUp(self): +# super().setUp() +# self.establishment = Establishment.objects.create( +# name="Test establishment", +# establishment_type_id=self.establishment_type.id, +# is_publish=True +# ) From aedcd795a9cd0c8ea889444791f36425fa37e55b Mon Sep 17 00:00:00 2001 From: littlewolf Date: Mon, 23 Sep 2019 14:21:05 +0300 Subject: [PATCH 25/31] Fix establishment model --- apps/establishment/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 5eac27fd..5b188c3c 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -227,7 +227,7 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin): """Establishment model.""" name = models.CharField(_('name'), max_length=255, default='') - name_transliterated = models.CharField(_('Transliterated name'), + name_translated = models.CharField(_('Transliterated name'), max_length=255, default='') description = TJSONField(blank=True, null=True, default=None, verbose_name=_('description'), From 06764d05e8295749731a89ec68d2a390f2d262d5 Mon Sep 17 00:00:00 2001 From: michail Date: Mon, 23 Sep 2019 16:21:48 +0500 Subject: [PATCH 26/31] Add recipe tests --- apps/recipe/tests.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 apps/recipe/tests.py diff --git a/apps/recipe/tests.py b/apps/recipe/tests.py new file mode 100644 index 00000000..d0a17a36 --- /dev/null +++ b/apps/recipe/tests.py @@ -0,0 +1,33 @@ +from http.cookies import SimpleCookie + + +from rest_framework.test import APITestCase +from rest_framework import status + +from account.models import User +from recipe.models import Recipe + + +class BaseTestCase(APITestCase): + + def setUp(self): + self.username = 'sedragurda' + self.password = 'sedragurdaredips19' + self.email = 'sedragurda@desoz.com' + self.user = User.objects.create_user(username=self.username, email=self.email, password=self.password) + tokkens = User.create_jwt_tokens(self.user) + self.client.cookies = SimpleCookie({'access_token': tokkens.get('access_token'), + 'refresh_token': tokkens.get('refresh_token')}) + self.test_recipe = Recipe.objects.create(title={"en-GB": "test title"}, description={"en-GB": "test description"}, + state=2, author="Test Author", created_by=self.user, + modified_by=self.user) + + def test_recipe_list(self): + response = self.client.get("/api/web/recipes/") + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_recipe_detail(self): + print(self.test_recipe.id) + response = self.client.get(f"/api/web/recipes/{self.test_recipe.id}/") + print(response.json()) + self.assertEqual(response.status_code, status.HTTP_200_OK) From b4a2893fcd7fa9d33fb98db4f92a07a2299d112c Mon Sep 17 00:00:00 2001 From: littlewolf Date: Mon, 23 Sep 2019 15:27:38 +0300 Subject: [PATCH 27/31] Add tests to guide --- apps/collection/tests.py | 66 ++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 39 deletions(-) diff --git a/apps/collection/tests.py b/apps/collection/tests.py index df75d00f..463d5fe5 100644 --- a/apps/collection/tests.py +++ b/apps/collection/tests.py @@ -1,11 +1,11 @@ -import json +import json, pytz from datetime import datetime from rest_framework.test import APITestCase from account.models import User from rest_framework import status from http.cookies import SimpleCookie -from collection.models import Collection +from collection.models import Collection, Guide from location.models import Country # Create your tests here. @@ -13,7 +13,7 @@ from location.models import Country class BaseTestCase(APITestCase): - def setUpT(self): + def setUp(self): self.username = 'sedragurda' self.password = 'sedragurdaredips19' self.email = 'sedragurda@desoz.com' @@ -24,7 +24,8 @@ class BaseTestCase(APITestCase): tokkens = User.create_jwt_tokens(self.user) self.client.cookies = SimpleCookie( {'access_token': tokkens.get('access_token'), - 'refresh_token': tokkens.get('refresh_token')}) + 'refresh_token': tokkens.get('refresh_token'), + 'country_code': 'en'}) class CollectionListTests(BaseTestCase): @@ -42,53 +43,40 @@ class CollectionDetailTests(BaseTestCase): if not country: country = Country.objects.create( name=json.dumps({"en-GB": "Test country"}), - code="test" + code="en" ) self.collection = Collection.objects.create( name='Test collection', is_publish=True, - start=datetime.now(), - end=datetime.now(), + start=datetime.now(pytz.utc), + end=datetime.now(pytz.utc), country=country ) def test_collection_detail_Read(self): - response = self.client.get(f'/api/web/collections/{self.collection.id}/', format='json') + response = self.client.get(f'/api/web/collections/{self.collection.id}/establishments/?country_code=en', + format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) +class CollectionGuideTests(CollectionDetailTests): - # data = { - # 'name': 'Test collection', - # - # } - # - # response = self.client.post('/api/web/collections/', data=data, format='json') - # self.assertEqual(response.status_code, status.HTTP_201_CREATED) - # - # establishment = response.json() - # - # response = self.client.get(f'/api/back/establishments/{establishment["id"]}/', format='json') - # self.assertEqual(response.status_code, status.HTTP_200_OK) - # - # update_data = { - # 'name': 'Test new establishment' - # } - # - # response = self.client.patch(f'/api/back/establishments/{establishment["id"]}/', data=update_data) - # self.assertEqual(response.status_code, status.HTTP_200_OK) - # - # response = self.client.delete(f'/api/back/establishments/{establishment["id"]}/', format='json') - # self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + def test_guide_list_Read(self): + response = self.client.get('/api/web/collections/guides/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) -# Class to test childs -# class ChildTestCase(BaseTestCase): -# def setUp(self): -# super().setUp() -# self.establishment = Establishment.objects.create( -# name="Test establishment", -# establishment_type_id=self.establishment_type.id, -# is_publish=True -# ) +class CollectionGuideDetailTests(CollectionDetailTests): + + def setUp(self): + super().setUp() + self.guide = Guide.objects.create( + collection=self.collection, + start=datetime.now(pytz.utc), + end=datetime.now(pytz.utc) + ) + + def test_guide_detail_Read(self): + response = self.client.get(f'/api/web/collections/guides/{self.guide.id}/', format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) From eca921592d00c2d3a395c59c3c284f3e57763f6c Mon Sep 17 00:00:00 2001 From: littlewolf Date: Mon, 23 Sep 2019 15:28:59 +0300 Subject: [PATCH 28/31] Fix guide parent --- apps/collection/models.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/collection/models.py b/apps/collection/models.py index a4a9bcae..928370d7 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -91,7 +91,9 @@ class GuideQuerySet(models.QuerySet): class Guide(ProjectBaseMixin, CollectionNameMixin, CollectionDateMixin): """Guide model.""" parent = models.ForeignKey( - 'self', verbose_name=_('parent'), on_delete=models.CASCADE) + 'self', verbose_name=_('parent'), on_delete=models.CASCADE, + null=True, blank=True, default=None + ) advertorials = JSONField( _('advertorials'), null=True, blank=True, default=None, help_text='{"key":"value"}') From dc4b63d8b22c9aa3965e45330ce54a3aa5efb228 Mon Sep 17 00:00:00 2001 From: evgeniy-st Date: Mon, 23 Sep 2019 15:35:37 +0300 Subject: [PATCH 29/31] Refactor news --- apps/location/serializers/common.py | 14 +++ .../migrations/0010_auto_20190923_1131.py | 54 +++++++++++ .../migrations/0011_auto_20190923_1134.py | 27 ++++++ apps/news/models.py | 74 ++++++++------ apps/news/serializers.py | 97 +++++++++++++++++++ apps/news/serializers/__init__.py | 0 apps/news/serializers/common.py | 76 --------------- apps/news/serializers/web.py | 0 apps/news/urls/back.py | 11 +++ apps/news/urls/web.py | 11 +-- apps/news/views.py | 68 +++++++++++++ apps/news/views/__init__.py | 0 apps/news/views/common.py | 38 -------- apps/news/views/web.py | 0 apps/utils/serializers.py | 10 +- project/urls/back.py | 1 + 16 files changed, 329 insertions(+), 152 deletions(-) create mode 100644 apps/news/migrations/0010_auto_20190923_1131.py create mode 100644 apps/news/migrations/0011_auto_20190923_1134.py create mode 100644 apps/news/serializers.py delete mode 100644 apps/news/serializers/__init__.py delete mode 100644 apps/news/serializers/common.py delete mode 100644 apps/news/serializers/web.py create mode 100644 apps/news/urls/back.py create mode 100644 apps/news/views.py delete mode 100644 apps/news/views/__init__.py delete mode 100644 apps/news/views/common.py delete mode 100644 apps/news/views/web.py diff --git a/apps/location/serializers/common.py b/apps/location/serializers/common.py index 63fe39e1..555cf499 100644 --- a/apps/location/serializers/common.py +++ b/apps/location/serializers/common.py @@ -1,7 +1,9 @@ +"""Location app common serializers.""" from django.contrib.gis.geos import Point from rest_framework import serializers from location import models +from utils.serializers import TranslatedField class CountrySerializer(serializers.ModelSerializer): @@ -20,6 +22,18 @@ class CountrySerializer(serializers.ModelSerializer): ] +class CountrySimpleSerializer(serializers.ModelSerializer): + """Simple country serializer.""" + + name_translated = TranslatedField() + + class Meta: + """Meta class.""" + + model = models.Country + fields = ('id', 'code', 'name_translated') + + class RegionSerializer(serializers.ModelSerializer): """Region serializer""" diff --git a/apps/news/migrations/0010_auto_20190923_1131.py b/apps/news/migrations/0010_auto_20190923_1131.py new file mode 100644 index 00000000..0bd6fd24 --- /dev/null +++ b/apps/news/migrations/0010_auto_20190923_1131.py @@ -0,0 +1,54 @@ +# Generated by Django 2.2.4 on 2019-09-23 11:31 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('news', '0009_auto_20190901_1032'), + ] + + operations = [ + migrations.AddField( + model_name='news', + name='author', + field=models.CharField(blank=True, default=None, max_length=255, null=True, verbose_name='Author'), + ), + migrations.AddField( + model_name='news', + name='image_url', + field=models.URLField(blank=True, default=None, null=True, verbose_name='Image URL path'), + ), + migrations.AddField( + model_name='news', + name='preview_image_url', + field=models.URLField(blank=True, default=None, null=True, verbose_name='Preview image URL path'), + ), + migrations.AlterField( + model_name='news', + name='address', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to='location.Address', verbose_name='address'), + ), + migrations.AlterField( + model_name='news', + name='country', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='location.Country', verbose_name='country'), + ), + migrations.AlterField( + model_name='news', + name='end', + field=models.DateTimeField(verbose_name='End'), + ), + migrations.AlterField( + model_name='news', + name='news_type', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='news.NewsType', verbose_name='news type'), + ), + migrations.AlterField( + model_name='news', + name='start', + field=models.DateTimeField(verbose_name='Start'), + ), + ] diff --git a/apps/news/migrations/0011_auto_20190923_1134.py b/apps/news/migrations/0011_auto_20190923_1134.py new file mode 100644 index 00000000..859cb636 --- /dev/null +++ b/apps/news/migrations/0011_auto_20190923_1134.py @@ -0,0 +1,27 @@ +# Generated by Django 2.2.4 on 2019-09-23 11:34 + +from django.db import migrations +from django.conf import settings + + +def copy_image_links(apps, schemaeditor): + News = apps.get_model('news', 'News') + for news in News.objects.all(): + if news.image: + news.image_url = f'{settings.SCHEMA_URI}://{settings.DOMAIN_URI}{news.image.image.url}' + + +class Migration(migrations.Migration): + + dependencies = [ + ('news', '0010_auto_20190923_1131'), + ] + + operations = [ + migrations.RunPython(copy_image_links, migrations.RunPython.noop), + + migrations.RemoveField( + model_name='news', + name='image', + ), + ] diff --git a/apps/news/models.py b/apps/news/models.py index 3be34261..75ae49c9 100644 --- a/apps/news/models.py +++ b/apps/news/models.py @@ -1,25 +1,30 @@ """News app models.""" from django.db import models +from django.utils import timezone from django.utils.translation import gettext_lazy as _ from rest_framework.reverse import reverse - from utils.models import BaseAttributes, TJSONField, TranslatedFieldsMixin class NewsType(models.Model): """NewsType model.""" + name = models.CharField(_('name'), max_length=250) class Meta: + """Meta class.""" + verbose_name_plural = _('news types') verbose_name = _('news type') def __str__(self): + """Overrided __str__ method.""" return self.name class NewsQuerySet(models.QuerySet): """QuerySet for model News""" + def by_type(self, news_type): """Filter News by type""" return self.filter(news_type__name=news_type) @@ -30,48 +35,55 @@ class NewsQuerySet(models.QuerySet): def published(self): """Return only published news""" - return self.filter(is_publish=True) + now = timezone.now() + return self.filter(is_publish=True, start__lte=now, end__gte=now) + + def with_related(self): + """Return qs with related objects.""" + return self.select_related('news_type') class News(BaseAttributes, TranslatedFieldsMixin): """News model.""" - image = models.ForeignKey( - 'gallery.Image', null=True, blank=True, default=None, - verbose_name=_('News image'), on_delete=models.CASCADE) - news_type = models.ForeignKey( - NewsType, verbose_name=_('news type'), on_delete=models.CASCADE) - - title = TJSONField( - _('title'), null=True, blank=True, - default=None, help_text='{"en-GB":"some text"}') - subtitle = TJSONField( - _('subtitle'), null=True, blank=True, - default=None, help_text='{"en-GB":"some text"}' - ) - description = TJSONField( - _('description'), null=True, blank=True, - default=None, help_text='{"en-GB":"some text"}' - ) - start = models.DateTimeField(_('start')) - end = models.DateTimeField(_('end')) + news_type = models.ForeignKey(NewsType, on_delete=models.PROTECT, + verbose_name=_('news type')) + title = TJSONField(blank=True, null=True, default=None, + verbose_name=_('title'), + help_text='{"en-GB":"some text"}') + subtitle = TJSONField(blank=True, null=True, default=None, + verbose_name=_('subtitle'), + help_text='{"en-GB":"some text"}') + description = TJSONField(blank=True, null=True, default=None, + verbose_name=_('description'), + help_text='{"en-GB":"some text"}') + start = models.DateTimeField(verbose_name=_('Start')) + end = models.DateTimeField(verbose_name=_('End')) playlist = models.IntegerField(_('playlist')) - address = models.ForeignKey( - 'location.Address', verbose_name=_('address'), blank=True, - null=True, default=None, on_delete=models.CASCADE) - is_publish = models.BooleanField( - default=False, verbose_name=_('Publish status')) - country = models.ForeignKey( - 'location.Country', blank=True, null=True, - verbose_name=_('country'), on_delete=models.CASCADE) - is_highlighted = models.BooleanField( - default=False, verbose_name=_('Is highlighted')) + is_publish = models.BooleanField(default=False, + verbose_name=_('Publish status')) + author = models.CharField(max_length=255, blank=True, null=True, + default=None,verbose_name=_('Author')) + is_highlighted = models.BooleanField(default=False, + verbose_name=_('Is highlighted')) # TODO: metadata_keys - описание ключей для динамического построения полей метаданных # TODO: metadata_values - Описание значений для динамических полей из MetadataKeys + image_url = models.URLField(blank=True, null=True, default=None, + verbose_name=_('Image URL path')) + preview_image_url = models.URLField(blank=True, null=True, default=None, + verbose_name=_('Preview image URL path')) + address = models.ForeignKey('location.Address', blank=True, null=True, + default=None, verbose_name=_('address'), + on_delete=models.SET_NULL) + country = models.ForeignKey('location.Country', blank=True, null=True, + on_delete=models.SET_NULL, + verbose_name=_('country')) objects = NewsQuerySet.as_manager() class Meta: + """Meta class.""" + verbose_name = _('news') verbose_name_plural = _('news') diff --git a/apps/news/serializers.py b/apps/news/serializers.py new file mode 100644 index 00000000..a734a264 --- /dev/null +++ b/apps/news/serializers.py @@ -0,0 +1,97 @@ +"""News app common serializers.""" +from rest_framework import serializers +from location import models as location_models +from location.serializers import CountrySimpleSerializer +from news import models +from utils.serializers import TranslatedField + + +class NewsTypeSerializer(serializers.ModelSerializer): + """News type serializer.""" + + class Meta: + """Meta class.""" + + model = models.NewsType + fields = ('id', 'name') + + +class NewsBaseSerializer(serializers.ModelSerializer): + """Base serializer for News model.""" + + # read only fields + title_translated = TranslatedField() + subtitle_translated = TranslatedField() + + # related fields + news_type = NewsTypeSerializer(read_only=True) + country = CountrySimpleSerializer(read_only=True) + + class Meta: + """Meta class.""" + + model = models.News + fields = ( + 'id', + 'title_translated', + 'subtitle_translated', + 'image_url', + 'image_url', + 'preview_image_url', + 'news_type', + 'country', + ) + + +class NewsDetailSerializer(NewsBaseSerializer): + """News detail serializer.""" + + description_translated = TranslatedField() + + class Meta(NewsBaseSerializer.Meta): + """Meta class.""" + + fields = NewsBaseSerializer.Meta.fields + ( + 'description_translated', + 'start', + 'end', + 'playlist', + 'is_highlighted', + 'is_publish', + ) + + +class NewsBackOfficeBaseSerializer(NewsBaseSerializer): + """News back office base serializer.""" + + class Meta(NewsBaseSerializer.Meta): + """Meta class.""" + + fields = NewsBaseSerializer.Meta.fields + ( + 'title', + 'subtitle', + ) + + +class NewsBackOfficeDetailSerializer(NewsBackOfficeBaseSerializer, + NewsDetailSerializer): + """News detail serializer for back-office users.""" + + news_type_id = serializers.PrimaryKeyRelatedField( + source='news_type', write_only=True, + queryset=models.NewsType.objects.all()) + + country_id = serializers.PrimaryKeyRelatedField( + source='country', write_only=True, + queryset=location_models.Country.objects.all()) + + class Meta(NewsBackOfficeBaseSerializer.Meta, NewsDetailSerializer.Meta): + """Meta class.""" + + fields = NewsBackOfficeBaseSerializer.Meta.fields + \ + NewsDetailSerializer.Meta.fields + ( + 'description', + 'news_type_id', + 'country_id', + ) + diff --git a/apps/news/serializers/__init__.py b/apps/news/serializers/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/apps/news/serializers/common.py b/apps/news/serializers/common.py deleted file mode 100644 index b64a7fc9..00000000 --- a/apps/news/serializers/common.py +++ /dev/null @@ -1,76 +0,0 @@ -"""News app common serializers.""" -from rest_framework import serializers -from gallery import models as gallery_models -from location.models import Address -from location.serializers import AddressSerializer -from news import models - - -class NewsTypeSerializer(serializers.ModelSerializer): - """News type serializer.""" - class Meta: - model = models.NewsType - fields = [ - 'id', - 'name' - ] - - -class NewsSerializer(serializers.ModelSerializer): - """News serializer.""" - - address = AddressSerializer() - title_translated = serializers.CharField(read_only=True, allow_null=True) - subtitle_translated = serializers.CharField(read_only=True, allow_null=True) - description_translated = serializers.CharField(read_only=True, allow_null=True) - image_url = serializers.ImageField(source='image.image', allow_null=True) - - class Meta: - model = models.News - fields = [ - 'id', - 'news_type', - 'start', - 'end', - 'playlist', - 'address', - 'is_highlighted', - 'image_url', - # Localized fields - 'title_translated', - 'subtitle_translated', - 'description_translated', - ] - - -class NewsCreateUpdateSerializer(NewsSerializer): - """News update serializer.""" - title = serializers.JSONField() - subtitle = serializers.JSONField() - description = serializers.JSONField() - image = serializers.PrimaryKeyRelatedField( - queryset=gallery_models.Image.objects.all(), required=True,) - news_type = serializers.PrimaryKeyRelatedField( - queryset=models.NewsType.objects.all(), write_only=True) - address = serializers.PrimaryKeyRelatedField( - queryset=Address.objects.all(), write_only=True) - - class Meta: - model = models.News - read_only_fields = [ - 'id' - ] - fields = [ - 'id', - 'news_type', - 'title', - 'subtitle', - 'description', - 'start', - 'end', - 'playlist', - 'address', - 'image', - 'is_publish', - 'country' - ] diff --git a/apps/news/serializers/web.py b/apps/news/serializers/web.py deleted file mode 100644 index e69de29b..00000000 diff --git a/apps/news/urls/back.py b/apps/news/urls/back.py new file mode 100644 index 00000000..8522592e --- /dev/null +++ b/apps/news/urls/back.py @@ -0,0 +1,11 @@ +"""News app urlpatterns for backoffice""" +from django.urls import path +from news import views + +app_name = 'news' + +urlpatterns = [ + path('', views.NewsBackOfficeLCView.as_view(), name='list-create'), + path('/', views.NewsBackOfficeRUDView.as_view(), + name='retrieve-update-destroy'), +] \ No newline at end of file diff --git a/apps/news/urls/web.py b/apps/news/urls/web.py index 1dbcc0fe..9ec7e644 100644 --- a/apps/news/urls/web.py +++ b/apps/news/urls/web.py @@ -1,12 +1,11 @@ -"""Location app urlconf.""" +"""News app urlconf.""" from django.urls import path - -from news.views import common +from news import views app_name = 'news' urlpatterns = [ - path('', common.NewsListView.as_view(), name='list'), - path('/', common.NewsDetailView.as_view(), name='rud'), - path('type/', common.NewsTypeListView.as_view(), name='type'), + path('', views.NewsListView.as_view(), name='list'), + path('/', views.NewsDetailView.as_view(), name='rud'), + path('types/', views.NewsTypeListView.as_view(), name='type'), ] diff --git a/apps/news/views.py b/apps/news/views.py new file mode 100644 index 00000000..7d6da3f7 --- /dev/null +++ b/apps/news/views.py @@ -0,0 +1,68 @@ +"""News app views.""" +from rest_framework import generics, permissions +from news import filters, models, serializers + + +class NewsMixinView: + """News mixin.""" + + permission_classes = (permissions.AllowAny, ) + serializer_class = serializers.NewsBaseSerializer + + def get_queryset(self, *args, **kwargs): + """Override get_queryset method.""" + qs = models.News.objects.with_related().published()\ + .order_by('-is_highlighted', '-created') + if self.request.country_code: + qs = qs.by_country_code(self.request.country_code) + return qs + + +class NewsListView(NewsMixinView, generics.ListAPIView): + """News list view.""" + + filter_class = filters.NewsListFilterSet + + +class NewsDetailView(NewsMixinView, generics.RetrieveAPIView): + """News detail view.""" + + serializer_class = serializers.NewsDetailSerializer + + +class NewsTypeListView(generics.ListAPIView): + """NewsType list view.""" + + pagination_class = None + permission_classes = (permissions.AllowAny, ) + queryset = models.NewsType.objects.all() + serializer_class = serializers.NewsTypeSerializer + + +class NewsBackOfficeMixinView: + """News back office mixin view.""" + + permission_classes = (permissions.IsAuthenticated,) + queryset = models.News.objects.with_related() \ + .order_by('-is_highlighted', '-created') + + +class NewsBackOfficeLCView(NewsBackOfficeMixinView, + generics.ListCreateAPIView): + """Resource for a list of news for back-office users.""" + + serializer_class = serializers.NewsBackOfficeBaseSerializer + create_serializers_class = serializers.NewsBackOfficeDetailSerializer + + def get_serializer_class(self): + if self.request.method == 'POST': + return self.create_serializers_class + return super().get_serializer_class() + + +class NewsBackOfficeRUDView(NewsBackOfficeMixinView, + generics.RetrieveUpdateDestroyAPIView): + """Resource for detailed information about news for back-office users.""" + + serializer_class = serializers.NewsBackOfficeDetailSerializer + diff --git a/apps/news/views/__init__.py b/apps/news/views/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/apps/news/views/common.py b/apps/news/views/common.py deleted file mode 100644 index cf3c7e29..00000000 --- a/apps/news/views/common.py +++ /dev/null @@ -1,38 +0,0 @@ -"""News app common app.""" -from rest_framework import generics, permissions - -from news import filters, models -from news.serializers import common as serializers -from utils.views import JWTGenericViewMixin - - -class NewsMixin: - """News mixin.""" - - permission_classes = (permissions.AllowAny, ) - serializer_class = serializers.NewsSerializer - - def get_queryset(self, *args, **kwargs): - """Override get_queryset method""" - return models.News.objects.published() \ - .by_country_code(code=self.request.country_code) \ - .order_by('-is_highlighted', '-created') - - -class NewsListView(NewsMixin, generics.ListAPIView): - """News list view.""" - - filter_class = filters.NewsListFilterSet - - -class NewsDetailView(NewsMixin, JWTGenericViewMixin, generics.RetrieveAPIView): - """News detail view.""" - - -class NewsTypeListView(generics.ListAPIView): - """NewsType list view.""" - - serializer_class = serializers.NewsTypeSerializer - permission_classes = (permissions.AllowAny, ) - pagination_class = None - queryset = models.NewsType.objects.all() diff --git a/apps/news/views/web.py b/apps/news/views/web.py deleted file mode 100644 index e69de29b..00000000 diff --git a/apps/utils/serializers.py b/apps/utils/serializers.py index 33463ebe..1f4c6f96 100644 --- a/apps/utils/serializers.py +++ b/apps/utils/serializers.py @@ -1,6 +1,5 @@ """Utils app serializer.""" from rest_framework import serializers - from utils.models import PlatformMixin @@ -13,3 +12,12 @@ class SourceSerializerMixin(serializers.Serializer): source = serializers.ChoiceField(choices=PlatformMixin.SOURCES, default=PlatformMixin.WEB, write_only=True) + + +class TranslatedField(serializers.CharField): + """Translated field.""" + + def __init__(self, allow_null=True, required=False, read_only=True, + **kwargs): + super().__init__(allow_null=allow_null, required=required, + read_only=read_only, **kwargs) diff --git a/project/urls/back.py b/project/urls/back.py index 5a64b955..7b4146eb 100644 --- a/project/urls/back.py +++ b/project/urls/back.py @@ -7,4 +7,5 @@ urlpatterns = [ namespace='gallery')), path('establishments/', include('establishment.urls.back')), path('location/', include('location.urls.back')), + path('news/', include('news.urls.back')) ] \ No newline at end of file From 009533d7644c509461368c216ff7e54767d8b9d4 Mon Sep 17 00:00:00 2001 From: evgeniy-st Date: Mon, 23 Sep 2019 16:06:40 +0300 Subject: [PATCH 30/31] Tags & disable elasticsearch indexing --- apps/main/serializers.py | 16 ++++++++-------- apps/news/models.py | 4 +++- apps/news/serializers.py | 8 ++++++-- apps/search_indexes/urls.py | 2 +- project/settings/development.py | 2 +- project/settings/local.py | 2 +- project/settings/stage.py | 2 +- 7 files changed, 21 insertions(+), 15 deletions(-) diff --git a/apps/main/serializers.py b/apps/main/serializers.py index f2beb768..10d75f2b 100644 --- a/apps/main/serializers.py +++ b/apps/main/serializers.py @@ -1,9 +1,9 @@ """Main app serializers.""" from rest_framework import serializers - from advertisement.serializers.web import AdvertisementSerializer from location.serializers import CountrySerializer from main import models +from utils.serializers import TranslatedField class FeatureSerializer(serializers.ModelSerializer): @@ -109,16 +109,16 @@ class AwardSerializer(AwardBaseSerializer): class MetaDataContentSerializer(serializers.ModelSerializer): - id = serializers.IntegerField(source='metadata.id', read_only=True, ) - label_translated = serializers.CharField( - source='metadata.label_translated', read_only=True, allow_null=True) + """MetaData content serializer.""" + + id = serializers.IntegerField(source='metadata.id', read_only=True) + label_translated = TranslatedField(source='metadata.label_translated') class Meta: + """Meta class.""" + model = models.MetaDataContent - fields = [ - 'id', - 'label_translated', - ] + fields = ('id', 'label_translated') class CurrencySerializer(serializers.ModelSerializer): diff --git a/apps/news/models.py b/apps/news/models.py index 75ae49c9..c132f6fc 100644 --- a/apps/news/models.py +++ b/apps/news/models.py @@ -1,5 +1,6 @@ """News app models.""" from django.db import models +from django.contrib.contenttypes import fields as generic from django.utils import timezone from django.utils.translation import gettext_lazy as _ from rest_framework.reverse import reverse @@ -40,7 +41,7 @@ class NewsQuerySet(models.QuerySet): def with_related(self): """Return qs with related objects.""" - return self.select_related('news_type') + return self.select_related('news_type', 'country').prefetch_related('tags') class News(BaseAttributes, TranslatedFieldsMixin): @@ -78,6 +79,7 @@ class News(BaseAttributes, TranslatedFieldsMixin): country = models.ForeignKey('location.Country', blank=True, null=True, on_delete=models.SET_NULL, verbose_name=_('country')) + tags = generic.GenericRelation(to='main.MetaDataContent') objects = NewsQuerySet.as_manager() diff --git a/apps/news/serializers.py b/apps/news/serializers.py index a734a264..c0d424ad 100644 --- a/apps/news/serializers.py +++ b/apps/news/serializers.py @@ -2,6 +2,7 @@ from rest_framework import serializers from location import models as location_models from location.serializers import CountrySimpleSerializer +from main.serializers import MetaDataContentSerializer from news import models from utils.serializers import TranslatedField @@ -25,7 +26,7 @@ class NewsBaseSerializer(serializers.ModelSerializer): # related fields news_type = NewsTypeSerializer(read_only=True) - country = CountrySimpleSerializer(read_only=True) + tags = MetaDataContentSerializer(read_only=True, many=True) class Meta: """Meta class.""" @@ -39,7 +40,7 @@ class NewsBaseSerializer(serializers.ModelSerializer): 'image_url', 'preview_image_url', 'news_type', - 'country', + 'tags', ) @@ -47,6 +48,7 @@ class NewsDetailSerializer(NewsBaseSerializer): """News detail serializer.""" description_translated = TranslatedField() + country = CountrySimpleSerializer(read_only=True) class Meta(NewsBaseSerializer.Meta): """Meta class.""" @@ -58,6 +60,8 @@ class NewsDetailSerializer(NewsBaseSerializer): 'playlist', 'is_highlighted', 'is_publish', + 'author', + 'country', ) diff --git a/apps/search_indexes/urls.py b/apps/search_indexes/urls.py index 60b05fb5..664e0b99 100644 --- a/apps/search_indexes/urls.py +++ b/apps/search_indexes/urls.py @@ -4,7 +4,7 @@ from search_indexes import views router = routers.SimpleRouter() -router.register(r'news', views.NewsDocumentViewSet, basename='news') +# router.register(r'news', views.NewsDocumentViewSet, basename='news') # temporarily disabled router.register(r'establishments', views.EstablishmentDocumentViewSet, basename='establishment') urlpatterns = router.urls diff --git a/project/settings/development.py b/project/settings/development.py index a7c8d9fd..43a60935 100644 --- a/project/settings/development.py +++ b/project/settings/development.py @@ -24,7 +24,7 @@ ELASTICSEARCH_DSL = { ELASTICSEARCH_INDEX_NAMES = { - 'search_indexes.documents.news': 'development_news', + # 'search_indexes.documents.news': 'development_news', # temporarily disabled 'search_indexes.documents.establishment': 'development_establishment', } diff --git a/project/settings/local.py b/project/settings/local.py index febe4dd4..503ad191 100644 --- a/project/settings/local.py +++ b/project/settings/local.py @@ -64,6 +64,6 @@ ELASTICSEARCH_DSL = { ELASTICSEARCH_INDEX_NAMES = { - 'search_indexes.documents.news': 'local_news', + # 'search_indexes.documents.news': 'local_news', 'search_indexes.documents.establishment': 'local_establishment', } \ No newline at end of file diff --git a/project/settings/stage.py b/project/settings/stage.py index 59fc78ed..c0d6fdb1 100644 --- a/project/settings/stage.py +++ b/project/settings/stage.py @@ -22,6 +22,6 @@ ELASTICSEARCH_DSL = { ELASTICSEARCH_INDEX_NAMES = { - 'search_indexes.documents.news': 'stage_news', + # 'search_indexes.documents.news': 'stage_news', #temporarily disabled 'search_indexes.documents.establishment': 'stage_establishment', } From d424704cec2079f782b3374636ee5d5bfc26e99a Mon Sep 17 00:00:00 2001 From: evgeniy-st Date: Mon, 23 Sep 2019 16:13:48 +0300 Subject: [PATCH 31/31] fix migration --- apps/news/migrations/0011_auto_20190923_1134.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/news/migrations/0011_auto_20190923_1134.py b/apps/news/migrations/0011_auto_20190923_1134.py index 859cb636..6e457b80 100644 --- a/apps/news/migrations/0011_auto_20190923_1134.py +++ b/apps/news/migrations/0011_auto_20190923_1134.py @@ -9,6 +9,7 @@ def copy_image_links(apps, schemaeditor): for news in News.objects.all(): if news.image: news.image_url = f'{settings.SCHEMA_URI}://{settings.DOMAIN_URI}{news.image.image.url}' + news.save() class Migration(migrations.Migration):