Merge branch 'feature/mobile_features' into 'develop'

Feature/mobile features

See merge request gm/gm-backend!53
This commit is contained in:
e.stoyushko 2019-10-17 13:29:29 +00:00
commit a553e459a1
16 changed files with 185 additions and 90 deletions

View File

@ -1,7 +1,6 @@
"""Location app web urlconf."""
from location.urls.common import urlpatterns as common_urlpatterns
urlpatterns = []
urlpatterns.extend(common_urlpatterns)
urlpatterns.extend(common_urlpatterns)

View File

@ -0,0 +1,19 @@
# Generated by Django 2.2.4 on 2019-10-07 14:39
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('main', '0016_merge_20190919_0954'),
]
operations = [
migrations.AddField(
model_name='feature',
name='route',
field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to='main.Page'),
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 2.2.4 on 2019-10-07 14:51
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('main', '0017_feature_route'),
]
operations = [
migrations.AddField(
model_name='feature',
name='source',
field=models.PositiveSmallIntegerField(choices=[(0, 'Mobile'), (1, 'Web'), (2, 'All')], default=0, verbose_name='Source'),
),
]

View File

@ -1,19 +1,23 @@
"""Main app models."""
from typing import Iterable
from django.conf import settings
from django.contrib.contenttypes import fields as generic
from django.contrib.contenttypes.models import ContentType
from django.contrib.postgres.fields import JSONField
from django.db import models
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from django.contrib.contenttypes.models import ContentType
from advertisement.models import Advertisement
from configuration.models import TranslationSettings
from location.models import Country
from main import methods
from review.models import Review
from utils.models import (ProjectBaseMixin, TJSONField,
TranslatedFieldsMixin, ImageMixin)
TranslatedFieldsMixin, ImageMixin, PlatformMixin)
from utils.querysets import ContentTypeQuerySetMixin
from configuration.models import TranslationSettings
#
#
@ -109,7 +113,6 @@ class SiteSettingsQuerySet(models.QuerySet):
class SiteSettings(ProjectBaseMixin):
subdomain = models.CharField(max_length=255, db_index=True, unique=True,
verbose_name=_('Subdomain'))
country = models.OneToOneField(Country, on_delete=models.PROTECT,
@ -150,7 +153,8 @@ class SiteSettings(ProjectBaseMixin):
@property
def published_sitefeatures(self):
return self.sitefeature_set.filter(published=True)
return self.sitefeature_set\
.filter(Q(published=True) and Q(feature__source__in=[PlatformMixin.WEB, PlatformMixin.ALL]))
@property
def site_url(self):
@ -159,11 +163,27 @@ class SiteSettings(ProjectBaseMixin):
domain=settings.SITE_DOMAIN_URI)
class Feature(ProjectBaseMixin):
class Page(models.Model):
"""Page model."""
page_name = models.CharField(max_length=255, unique=True)
advertisements = models.ManyToManyField(Advertisement)
class Meta:
"""Meta class."""
verbose_name = _('Page')
verbose_name_plural = _('Pages')
def __str__(self):
return f'{self.page_name}'
class Feature(ProjectBaseMixin, PlatformMixin):
"""Feature model."""
slug = models.CharField(max_length=255, unique=True)
priority = models.IntegerField(unique=True, null=True, default=None)
route = models.ForeignKey(Page, on_delete=models.PROTECT, null=True, default=None)
site_settings = models.ManyToManyField(SiteSettings, through='SiteFeature')
class Meta:
@ -181,6 +201,12 @@ class SiteFeatureQuerySet(models.QuerySet):
def published(self, switcher=True):
return self.filter(published=switcher)
def by_country_code(self, country_code: str):
return self.filter(site_settings__country__code=country_code)
def by_sources(self, sources: Iterable[int]):
return self.filter(feature__source__in=sources)
class SiteFeature(ProjectBaseMixin):
"""SiteFeature model."""
@ -351,19 +377,3 @@ class Carousel(models.Model):
def model_name(self):
if hasattr(self.content_object, 'establishment_type'):
return self.content_object.establishment_type.name_translated
class Page(models.Model):
"""Page model."""
page_name = models.CharField(max_length=255, unique=True)
advertisements = models.ManyToManyField(Advertisement)
class Meta:
"""Meta class."""
verbose_name = _('Page')
verbose_name_plural = _('Pages')
def __str__(self):
return f'{self.page_name}'

View File

@ -25,6 +25,8 @@ class SiteFeatureSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(source='feature.id')
slug = serializers.CharField(source='feature.slug')
priority = serializers.IntegerField(source='feature.priority')
route = serializers.CharField(source='feature.route.page_name')
source = serializers.IntegerField(source='feature.source')
class Meta:
"""Meta class."""
@ -32,7 +34,9 @@ class SiteFeatureSerializer(serializers.ModelSerializer):
fields = ('main',
'id',
'slug',
'priority'
'priority',
'route',
'source'
)

View File

@ -1,15 +0,0 @@
"""Main app urls."""
from django.urls import path
from main import views
app = 'main'
urlpatterns = [
path('determine-site/', views.DetermineSiteView.as_view(), name='determine-site'),
path('determine-location/', views.DetermineLocation.as_view(), name='determine-location'),
path('sites/', views.SiteListView.as_view(), name='site-list'),
path('site-settings/<subdomain>/', views.SiteSettingsView.as_view(), name='site-settings'),
path('awards/', views.AwardView.as_view(), name='awards_list'),
path('awards/<int:pk>/', views.AwardRetrieveView.as_view(), name='awards_retrieve'),
path('carousel/', views.CarouselListView.as_view(), name='carousel-list'),
]

View File

12
apps/main/urls/common.py Normal file
View File

@ -0,0 +1,12 @@
"""Main app urls."""
from django.urls import path
from main.views.common import *
app = 'main'
common_urlpatterns = [
path('awards/', AwardView.as_view(), name='awards_list'),
path('awards/<int:pk>/', AwardRetrieveView.as_view(), name='awards_retrieve'),
path('carousel/', CarouselListView.as_view(), name='carousel-list'),
path('determine-location/', DetermineLocation.as_view(), name='determine-location')
]

11
apps/main/urls/mobile.py Normal file
View File

@ -0,0 +1,11 @@
from main.urls.common import common_urlpatterns
from django.urls import path
from main.views.mobile import FeaturesView
urlpatterns = [
path('features/', FeaturesView.as_view(), name='features'),
]
urlpatterns.extend(common_urlpatterns)

11
apps/main/urls/web.py Normal file
View File

@ -0,0 +1,11 @@
from main.urls.common import common_urlpatterns
from django.urls import path
from main.views.web import DetermineSiteView, SiteListView, SiteSettingsView
urlpatterns = [
path('determine-site/', DetermineSiteView.as_view(), name='determine-site'),
path('sites/', SiteListView.as_view(), name='site-list'),
path('site-settings/<subdomain>/', SiteSettingsView.as_view(), name='site-settings'), ]
urlpatterns.extend(common_urlpatterns)

View File

View File

@ -1,56 +1,9 @@
"""Main app views."""
from django.http import Http404
from rest_framework import generics, permissions
from rest_framework.response import Response
from main import methods, models, serializers
from utils.serializers import EmptySerializer
from django.http import Http404
class DetermineSiteView(generics.GenericAPIView):
"""Determine user's site."""
permission_classes = (permissions.AllowAny,)
serializer_class = EmptySerializer
def get(self, request, *args, **kwargs):
user_ip = methods.get_user_ip(request)
country_code = methods.determine_country_code(user_ip)
url = methods.determine_user_site_url(country_code)
return Response(data={'url': url})
class DetermineLocation(generics.GenericAPIView):
"""Determine user's location."""
permission_classes = (permissions.AllowAny,)
serializer_class = EmptySerializer
def get(self, request, *args, **kwargs):
user_ip = methods.get_user_ip(request)
longitude, latitude = methods.determine_coordinates(user_ip)
city = methods.determine_user_city(user_ip)
if longitude and latitude and city:
return Response(data={'latitude': latitude, 'longitude': longitude, 'city': city})
else:
raise Http404
class SiteSettingsView(generics.RetrieveAPIView):
"""Site settings View."""
lookup_field = 'subdomain'
permission_classes = (permissions.AllowAny,)
queryset = models.SiteSettings.objects.all()
serializer_class = serializers.SiteSettingsSerializer
class SiteListView(generics.ListAPIView):
"""Site settings View."""
pagination_class = None
permission_classes = (permissions.AllowAny,)
queryset = models.SiteSettings.objects.with_country()
serializer_class = serializers.SiteSerializer
#
@ -89,6 +42,7 @@ class SiteListView(generics.ListAPIView):
# class SiteFeaturesRUDView(SiteFeaturesViewMixin,
# generics.RetrieveUpdateDestroyAPIView):
# """Site features RUD."""
from utils.serializers import EmptySerializer
class AwardView(generics.ListAPIView):
@ -111,3 +65,20 @@ class CarouselListView(generics.ListAPIView):
serializer_class = serializers.CarouselListSerializer
permission_classes = (permissions.AllowAny,)
pagination_class = None
class DetermineLocation(generics.GenericAPIView):
"""Determine user's location."""
permission_classes = (permissions.AllowAny,)
serializer_class = EmptySerializer
def get(self, request, *args, **kwargs):
user_ip = methods.get_user_ip(request)
longitude, latitude = methods.determine_coordinates(user_ip)
city = methods.determine_user_city(user_ip)
if longitude and latitude and city:
return Response(data={'latitude': latitude, 'longitude': longitude, 'city': city})
else:
raise Http404

16
apps/main/views/mobile.py Normal file
View File

@ -0,0 +1,16 @@
from rest_framework import generics, permissions
from main import models, serializers
from utils.models import PlatformMixin
class FeaturesView(generics.ListAPIView):
pagination_class = None
permission_classes = (permissions.AllowAny,)
serializer_class = serializers.SiteFeatureSerializer
def get_queryset(self):
return models.SiteFeature.objects\
.prefetch_related('feature', 'feature__route') \
.by_country_code(self.request.country_code) \
.by_sources([PlatformMixin.ALL, PlatformMixin.MOBILE])

38
apps/main/views/web.py Normal file
View File

@ -0,0 +1,38 @@
from typing import Iterable
from rest_framework import generics, permissions
from utils.serializers import EmptySerializer
from rest_framework.response import Response
from main import methods, models, serializers
class DetermineSiteView(generics.GenericAPIView):
"""Determine user's site."""
permission_classes = (permissions.AllowAny,)
serializer_class = EmptySerializer
def get(self, request, *args, **kwargs):
user_ip = methods.get_user_ip(request)
country_code = methods.determine_country_code(user_ip)
url = methods.determine_user_site_url(country_code)
return Response(data={'url': url})
class SiteSettingsView(generics.RetrieveAPIView):
"""Site settings View."""
lookup_field = 'subdomain'
permission_classes = (permissions.AllowAny,)
queryset = models.SiteSettings.objects.all()
serializer_class = serializers.SiteSettingsSerializer
class SiteListView(generics.ListAPIView):
"""Site settings View."""
pagination_class = None
permission_classes = (permissions.AllowAny,)
queryset = models.SiteSettings.objects.with_country()
serializer_class = serializers.SiteSerializer

View File

@ -4,6 +4,7 @@ app_name = 'mobile'
urlpatterns = [
path('establishments/', include('establishment.urls.mobile')),
path('main/', include('main.urls.mobile'))
# path('account/', include('account.urls.web')),
# path('advertisement/', include('advertisement.urls.web')),
# path('collection/', include('collection.urls.web')),

View File

@ -27,7 +27,7 @@ urlpatterns = [
path('notifications/', include(('notification.urls.web', "notification"), namespace='notification')),
path('partner/', include('partner.urls.web')),
path('location/', include('location.urls.web')),
path('main/', include('main.urls')),
path('main/', include('main.urls.web')),
path('recipes/', include('recipe.urls.web')),
path('translation/', include('translation.urls')),
path('comments/', include('comment.urls.web')),