Merge branch 'develop' into feature/fix_role

This commit is contained in:
Виктор Гладких 2019-10-25 10:15:38 +03:00
commit c33ea42b8e
14 changed files with 164 additions and 73 deletions

View File

@ -0,0 +1,19 @@
# Generated by Django 2.2.4 on 2019-10-24 13:34
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('collection', '0015_auto_20191023_0715'),
]
operations = [
migrations.AlterField(
model_name='guide',
name='collection',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='collection.Collection', verbose_name='collection'),
),
]

View File

@ -101,8 +101,9 @@ class Guide(ProjectBaseMixin, CollectionNameMixin, CollectionDateMixin):
advertorials = JSONField( advertorials = JSONField(
_('advertorials'), null=True, blank=True, _('advertorials'), null=True, blank=True,
default=None, help_text='{"key":"value"}') default=None, help_text='{"key":"value"}')
collection = models.ForeignKey( collection = models.ForeignKey(Collection, on_delete=models.CASCADE,
Collection, verbose_name=_('collection'), on_delete=models.CASCADE) null=True, blank=True, default=None,
verbose_name=_('collection'))
objects = GuideQuerySet.as_manager() objects = GuideQuerySet.as_manager()

View File

@ -9,6 +9,7 @@ from establishment.models import Establishment, EstablishmentType, Menu
from translation.models import Language from translation.models import Language
from account.models import Role, UserRole from account.models import Role, UserRole
from location.models import Country, Address, City, Region from location.models import Country, Address, City, Region
from pytz import timezone as py_tz
class BaseTestCase(APITestCase): class BaseTestCase(APITestCase):
@ -77,7 +78,8 @@ class EstablishmentBTests(BaseTestCase):
'name': 'Test establishment', 'name': 'Test establishment',
'type_id': self.establishment_type.id, 'type_id': self.establishment_type.id,
'is_publish': True, 'is_publish': True,
'slug': 'test-establishment-slug' 'slug': 'test-establishment-slug',
'tz': py_tz('Europe/Moscow').zone
} }
response = self.client.post('/api/back/establishments/', data=data, format='json') response = self.client.post('/api/back/establishments/', data=data, format='json')

View File

@ -1,14 +1,16 @@
# Create your tests here. # Create your tests here.
from http.cookies import SimpleCookie from http.cookies import SimpleCookie
from django.contrib.contenttypes.models import ContentType
from rest_framework.test import APITestCase from django.contrib.contenttypes.models import ContentType
from django.urls import reverse
from rest_framework import status from rest_framework import status
from rest_framework.test import APITestCase
from account.models import User from account.models import User
from establishment.models import Establishment, EstablishmentType
from favorites.models import Favorites from favorites.models import Favorites
from establishment.models import Establishment, EstablishmentType, EstablishmentSubType
from news.models import NewsType, News from news.models import NewsType, News
from datetime import datetime
class BaseTestCase(APITestCase): class BaseTestCase(APITestCase):
@ -17,38 +19,57 @@ class BaseTestCase(APITestCase):
self.username = 'sedragurda' self.username = 'sedragurda'
self.password = 'sedragurdaredips19' self.password = 'sedragurdaredips19'
self.email = 'sedragurda@desoz.com' self.email = 'sedragurda@desoz.com'
self.user = User.objects.create_user(username=self.username, email=self.email, password=self.password) self.user = User.objects.create_user(
tokkens = User.create_jwt_tokens(self.user) username=self.username,
self.client.cookies = SimpleCookie({'access_token': tokkens.get('access_token'), email=self.email,
'refresh_token': tokkens.get('refresh_token')}) password=self.password
)
self.test_news_type = NewsType.objects.create(name="Test news type") tokens = User.create_jwt_tokens(self.user)
self.test_news = News.objects.create(created_by=self.user, modified_by=self.user, title={"en-GB": "Test news"}, self.client.cookies = SimpleCookie(
news_type=self.test_news_type, {'access_token': tokens.get('access_token'),
description={"en-GB": "Description test news"}, 'refresh_token': tokens.get('refresh_token')})
start="2020-12-03 12:00:00", end="2020-12-13 12:00:00",
state=News.PUBLISHED, slug='test-news')
self.test_content_type = ContentType.objects.get(app_label="news", model="news") 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"},
start=datetime.fromisoformat("2020-12-03 12:00:00"),
end=datetime.fromisoformat("2020-12-03 12:00:00"),
state=News.PUBLISHED,
slug='test-news'
)
self.test_favorites = Favorites.objects.create(user=self.user, content_type=self.test_content_type, self.test_content_type = ContentType.objects.get(
object_id=self.test_news.id) app_label="news", model="news")
self.test_establishment_type = EstablishmentType.objects.create(name={"en-GB": "test establishment type"}, self.test_favorites = Favorites.objects.create(
use_subtypes=False) user=self.user, content_type=self.test_content_type,
object_id=self.test_news.id)
self.test_establishment = Establishment.objects.create(name="test establishment", self.test_establishment_type = EstablishmentType.objects.create(
description={"en-GB": "description of test establishment"}, name={"en-GB": "test establishment type"},
establishment_type=self.test_establishment_type, use_subtypes=False)
is_publish=True)
self.test_establishment = Establishment.objects.create(
name="test establishment",
description={"en-GB": "description of test establishment"},
establishment_type=self.test_establishment_type,
is_publish=True)
# value for GenericRelation(reverse side) field must be iterable # value for GenericRelation(reverse side) field must be iterable
# value for GenericRelation(reverse side) field must be assigned through "set" method of field # value for GenericRelation(reverse side) field must be assigned through
# "set" method of field
self.test_establishment.favorites.set([self.test_favorites]) self.test_establishment.favorites.set([self.test_favorites])
class FavoritesTestCase(BaseTestCase): class FavoritesTestCase(BaseTestCase):
def test_func(self): def test_func(self):
response = self.client.get("/api/web/favorites/establishments/") url = reverse('web:favorites:establishment-list')
print(response.json()) response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)

View File

@ -0,0 +1,28 @@
# Generated by Django 2.2.4 on 2019-10-24 16:49
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('news', '0027_remove_news_playlist'),
]
operations = [
migrations.AlterField(
model_name='newsgallery',
name='image',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='news_gallery', to='gallery.Image', verbose_name='gallery'),
),
migrations.AlterField(
model_name='newsgallery',
name='news',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='news_gallery', to='news.News', verbose_name='news'),
),
migrations.AlterUniqueTogether(
name='newsgallery',
unique_together={('news', 'is_main')},
),
]

View File

@ -194,13 +194,24 @@ class News(BaseAttributes, TranslatedFieldsMixin):
@property @property
def main_image(self): def main_image(self):
return self.news_gallery.main_images().first().image qs = self.news_gallery.main_image()
if qs.exists():
return qs.first().image
@property
def image_url(self):
return self.main_image.image.url if self.main_image else None
@property
def preview_image_url(self):
if self.main_image:
return self.main_image.get_image_url(thumbnail_key='news_preview')
class NewsGalleryQuerySet(models.QuerySet): class NewsGalleryQuerySet(models.QuerySet):
"""QuerySet for model News""" """QuerySet for model News"""
def main_images(self): def main_image(self):
"""Return objects with flag is_main is True""" """Return objects with flag is_main is True"""
return self.filter(is_main=True) return self.filter(is_main=True)
@ -209,11 +220,11 @@ class NewsGallery(models.Model):
news = models.ForeignKey(News, null=True, news = models.ForeignKey(News, null=True,
related_name='news_gallery', related_name='news_gallery',
on_delete=models.SET_NULL, on_delete=models.CASCADE,
verbose_name=_('news')) verbose_name=_('news'))
image = models.ForeignKey('gallery.Image', null=True, image = models.ForeignKey('gallery.Image', null=True,
related_name='news_gallery', related_name='news_gallery',
on_delete=models.SET_NULL, on_delete=models.CASCADE,
verbose_name=_('gallery')) verbose_name=_('gallery'))
is_main = models.BooleanField(default=False, is_main = models.BooleanField(default=False,
verbose_name=_('Is the main image')) verbose_name=_('Is the main image'))
@ -224,3 +235,4 @@ class NewsGallery(models.Model):
"""NewsGallery meta class.""" """NewsGallery meta class."""
verbose_name = _('news gallery') verbose_name = _('news gallery')
verbose_name_plural = _('news galleries') verbose_name_plural = _('news galleries')
unique_together = ('news', 'is_main')

View File

@ -281,7 +281,7 @@ class NewsBackOfficeGallerySerializer(serializers.ModelSerializer):
if news.news_gallery.filter(image=image).exists(): if news.news_gallery.filter(image=image).exists():
raise serializers.ValidationError({'detail': _('Image is already added')}) raise serializers.ValidationError({'detail': _('Image is already added')})
if is_main and news.news_gallery.main_images().exists(): if is_main and news.news_gallery.main_image().exists():
raise serializers.ValidationError({'detail': _('Main image is already added')}) raise serializers.ValidationError({'detail': _('Main image is already added')})
attrs['news'] = news attrs['news'] = news

View File

@ -18,11 +18,14 @@ class BaseTestCase(APITestCase):
self.username = 'sedragurda' self.username = 'sedragurda'
self.password = 'sedragurdaredips19' self.password = 'sedragurdaredips19'
self.email = 'sedragurda@desoz.com' self.email = 'sedragurda@desoz.com'
self.user = User.objects.create_user(username=self.username, email=self.email, password=self.password) self.user = User.objects.create_user(
#get tokkens 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'), # get tokens
'refresh_token': tokkens.get('refresh_token')}) tokens = User.create_jwt_tokens(self.user)
self.client.cookies = SimpleCookie(
{'access_token': tokens.get('access_token'),
'refresh_token': tokens.get('refresh_token')})
self.test_news_type = NewsType.objects.create(name="Test news type") self.test_news_type = NewsType.objects.create(name="Test news type")
self.lang = Language.objects.get( self.lang = Language.objects.get(
@ -46,21 +49,25 @@ class BaseTestCase(APITestCase):
) )
user_role.save() user_role.save()
self.test_news = News.objects.create(created_by=self.user, modified_by=self.user, self.test_news = News.objects.create(
title={"en-GB": "Test news"}, created_by=self.user, modified_by=self.user,
news_type=self.test_news_type, title={"en-GB": "Test news"},
description={"en-GB": "Description test news"}, news_type=self.test_news_type,
start=datetime.now() + timedelta(hours=-2), description={"en-GB": "Description test news"},
end=datetime.now() + timedelta(hours=2), start=datetime.now() + timedelta(hours=-2),
state=News.PUBLISHED, slug='test-news-slug', end=datetime.now() + timedelta(hours=2),
country=self.country_ru) state=News.PUBLISHED,
slug='test-news-slug',
country=self.country_ru,
)
class NewsTestCase(BaseTestCase): class NewsTestCase(BaseTestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
def test_web_news(self): def test_web_news(self):
response = self.client.get("/api/web/news/") response = self.client.get(reverse('web:news:list'))
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
response = self.client.get(f"/api/web/news/slug/{self.test_news.slug}/") response = self.client.get(f"/api/web/news/slug/{self.test_news.slug}/")

View File

@ -20,19 +20,28 @@ class NewsMixinView:
def get_queryset(self, *args, **kwargs): def get_queryset(self, *args, **kwargs):
from django.conf import settings from django.conf import settings
"""Override get_queryset method.""" """Override get_queryset method."""
qs = models.News.objects.published().with_base_related() \ qs = models.News.objects.published().with_base_related() \
.order_by('-is_highlighted', '-created') .order_by('-is_highlighted', '-created')
country_code = self.request.country_code country_code = self.request.country_code
if country_code and country_code != 'www' and country_code != 'main': if country_code:
return qs.by_country_code(self.request.country_code)
else: # temp code
if settings.HARDCODED_INTERNATIONAL_NEWS_IDS: # Temporary stub for international news logic
# Temporary stub for international news logic # (по договорённости с заказчиком на демонстрации 4 ноября
# (по договорённости с заказчиком на демонстрации 4 ноября здесь будет 6 фиксированных новостей) # здесь будет 6 фиксированных новостей)
# TODO replace this stub with actual logic # TODO replace this stub with actual logic
return models.News.objects.filter(id__in=settings.HARDCODED_INTERNATIONAL_NEWS_IDS) if hasattr(settings, 'HARDCODED_INTERNATIONAL_NEWS_IDS'):
else: if country_code and country_code != 'www' and country_code != 'main':
qs = qs.by_country_code(country_code)
else:
qs = models.News.objects.filter(
id__in=settings.HARDCODED_INTERNATIONAL_NEWS_IDS)
return qs return qs
# temp code
qs = qs.by_country_code(country_code)
return qs
class NewsListView(NewsMixinView, generics.ListAPIView): class NewsListView(NewsMixinView, generics.ListAPIView):

View File

@ -24,6 +24,8 @@ class NewsDocument(Document):
country = fields.ObjectField(properties={'id': fields.IntegerField(), country = fields.ObjectField(properties={'id': fields.IntegerField(),
'code': fields.KeywordField()}) 'code': fields.KeywordField()})
web_url = fields.KeywordField(attr='web_url') web_url = fields.KeywordField(attr='web_url')
image_url = fields.KeywordField(attr='image_url')
preview_image_url = fields.KeywordField(attr='preview_image_url')
tags = fields.ObjectField( tags = fields.ObjectField(
properties={ properties={
'id': fields.IntegerField(attr='id'), 'id': fields.IntegerField(attr='id'),

View File

@ -58,7 +58,11 @@ class TimeZoneChoiceField(serializers.ChoiceField):
super().__init__(choices=choices, **kwargs) super().__init__(choices=choices, **kwargs)
def to_representation(self, value): def to_representation(self, value):
return value.zone if isinstance(value, str):
return value
elif isinstance(value, pytz.tzinfo.BaseTzInfo):
return value.zone
return None
def to_internal_value(self, data): def to_internal_value(self, data):
return pytz.timezone(data) return pytz.timezone(data)

View File

@ -27,7 +27,7 @@ class BaseTestCase(APITestCase):
self.client.cookies = SimpleCookie( self.client.cookies = SimpleCookie(
{'access_token': tokkens.get('access_token'), {'access_token': tokkens.get('access_token'),
'refresh_token': tokkens.get('refresh_token'), 'refresh_token': tokkens.get('refresh_token'),
'locale': "en" 'locale': "en-GB"
}) })
@ -58,12 +58,11 @@ class TranslateFieldTests(BaseTestCase):
def test_model_field(self): def test_model_field(self):
self.assertTrue(hasattr(self.news_item, "title_translated")) self.assertTrue(hasattr(self.news_item, "title_translated"))
def test_read_locale(self): def test_read_locale(self):
response = self.client.get(f"/api/web/news/slug/{self.news_item.slug}/", format='json') response = self.client.get(f"/api/web/news/slug/{self.news_item.slug}/", format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
news_data = response.json() news_data = response.json()
print(news_data)
self.assertIn("title_translated", news_data) self.assertIn("title_translated", news_data)
self.assertIn("Test news item", news_data['title_translated']) self.assertIn("Test news item", news_data['title_translated'])

View File

@ -31,14 +31,6 @@ services:
# Redis # Redis
redis: redis:
image: redis:2.8.23 image: redis:2.8.23
ports:
- "6379:6379"
# RabbitMQ
#rabbitmq:
# image: rabbitmq:latest
# ports:
# - "5672:5672"
# Celery # Celery
worker: worker:

View File

@ -88,8 +88,3 @@ ELASTICSEARCH_INDEX_NAMES = {
TESTING = sys.argv[1:2] == ['test'] TESTING = sys.argv[1:2] == ['test']
if TESTING: if TESTING:
ELASTICSEARCH_INDEX_NAMES = {} ELASTICSEARCH_INDEX_NAMES = {}
# TMP ( TODO remove it later)
# Временный хардкод для демонстрации 4 ноября, потом удалить!
HARDCODED_INTERNATIONAL_NEWS_IDS = [8, 9, 10, 11, 15, 17]