refactored serializers that retrieving phone numbers

This commit is contained in:
Anatoly 2020-02-03 13:10:02 +03:00
parent 3c56b0c061
commit 15b8241213
11 changed files with 127 additions and 57 deletions

3
.gitignore vendored
View File

@ -26,7 +26,8 @@ celerybeat-schedule
local_files
celerybeat.pid
/gm_viktor.dump
/gm_victor.dump
/docker-compose.dump.yml
/gm_production_20191029.sql
/apps/transfer/log
/gm_production_*.sql
/gm_production_*.sql

View File

@ -22,7 +22,7 @@ from establishment.models import Establishment, EstablishmentSubType
from location.models import Country
from main.models import SiteSettings
from utils.models import GMTokenGenerator
from utils.models import ImageMixin, ProjectBaseMixin, PlatformMixin
from utils.models import ImageMixin, ProjectBaseMixin, PlatformMixin, PhoneModelMixin
from utils.tokens import GMRefreshToken
@ -207,7 +207,7 @@ class UserQuerySet(models.QuerySet):
return self.filter(userrole__role__country__code=country_code).distinct()
class User(AbstractUser):
class User(PhoneModelMixin, AbstractUser):
"""Base user model."""
username = models.CharField(
_('username'),

View File

@ -45,7 +45,9 @@ class BackUserSerializer(UserSerializer):
'roles',
'subscriptions',
'phone',
'phone_as_international',
'country_calling_code',
'national_calling_number',
)
extra_kwargs = {
'password': {'write_only': True},

View File

@ -3,7 +3,6 @@ from django.conf import settings
from django.contrib.auth import password_validation as password_validators
from django.utils.translation import gettext_lazy as _
from fcm_django.models import FCMDevice
from phonenumber_field.serializerfields import PhoneNumberField
from rest_framework import exceptions
from rest_framework import serializers
from rest_framework import validators as rest_validators
@ -14,6 +13,7 @@ from notification.models import Subscribe, Subscriber
from utils import exceptions as utils_exceptions
from utils import methods as utils_methods
from utils.methods import generate_string_code
from utils.serializers import PhoneMixinSerializer
def subscriptions_handler(subscriptions_list, user):
@ -60,7 +60,7 @@ class RoleBaseSerializer(serializers.ModelSerializer):
]
class UserSerializer(serializers.ModelSerializer):
class UserSerializer(PhoneMixinSerializer, serializers.ModelSerializer):
"""User serializer."""
# RESPONSE
fullname = serializers.CharField(source='get_full_name', read_only=True)
@ -81,9 +81,6 @@ class UserSerializer(serializers.ModelSerializer):
required=False,
help_text='list of subscription_types id',
)
phone_as_international = PhoneNumberField(source='phone.as_international',
allow_null=True,
read_only=True)
is_superuser = serializers.BooleanField(read_only=True)
class Meta:
@ -102,7 +99,8 @@ class UserSerializer(serializers.ModelSerializer):
'roles',
'subscriptions',
'phone',
'phone_as_international',
'country_calling_code',
'national_calling_number',
'is_superuser',
]
extra_kwargs = {

View File

@ -4,11 +4,11 @@ from django.contrib.contenttypes.admin import GenericTabularInline
from django.utils.translation import gettext_lazy as _
from comment.models import Comment
from utils.admin import BaseModelAdminMixin
from establishment import models
from main.models import Award
from product.models import Product, PurchasedProduct
from review import models as review_models
from utils.admin import BaseModelAdminMixin
@admin.register(models.EstablishmentType)
@ -87,11 +87,11 @@ class EstablishmentAdmin(BaseModelAdminMixin, admin.ModelAdmin):
search_fields = ['id', 'name', 'index_name', 'slug']
list_filter = ['public_mark', 'toque_number']
inlines = [CompanyInline, EstablishmentNote, GalleryImageInline,
PurchasedProductInline, ]
PurchasedProductInline, ContactPhoneInline, ]
# inlines = [
# AwardInline, ContactPhoneInline, ContactEmailInline,
# ReviewInline, CommentInline, ProductInline]
raw_id_fields = ('address', 'collections', 'tags', 'schedule')
raw_id_fields = ('address', 'collections', 'tags', 'schedule', )
@admin.register(models.Position)
@ -142,3 +142,7 @@ class CompanyAdmin(BaseModelAdminMixin, admin.ModelAdmin):
"""Admin conf for Company model."""
raw_id_fields = ['establishment', 'address', ]
@admin.register(models.Employee)
class EmployeeAdmin(BaseModelAdminMixin, admin.ModelAdmin):
raw_id_fields = ['establishments', 'tags', 'user', 'photo', ]

View File

@ -14,13 +14,14 @@ from django.contrib.postgres.fields import ArrayField
from django.contrib.postgres.indexes import GinIndex
from django.contrib.postgres.search import TrigramSimilarity
from django.core.exceptions import ValidationError
from django.core.validators import FileExtensionValidator, MaxValueValidator, MinValueValidator
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.db.models import Case, ExpressionWrapper, F, Prefetch, Q, Subquery, When
from django.shortcuts import get_object_or_404
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from phonenumber_field.modelfields import PhoneNumberField
from phonenumber_field.phonenumber import PhoneNumber
from timezone_field import TimeZoneField
from location.models import Address
@ -30,8 +31,9 @@ from tag.models import Tag
from timetable.models import Timetable
from utils.methods import transform_into_readable_str
from utils.models import (
BaseAttributes, FavoritesMixin, FileMixin, GalleryMixin, HasTagsMixin, IntermediateGalleryModelMixin,
ProjectBaseMixin, TJSONField, TranslatedFieldsMixin, TypeDefaultImageMixin, URLImageMixin, default_menu_bool_array
BaseAttributes, FavoritesMixin, FileMixin, GalleryMixin, HasTagsMixin,
IntermediateGalleryModelMixin, ProjectBaseMixin, TJSONField, TranslatedFieldsMixin,
TypeDefaultImageMixin, URLImageMixin, default_menu_bool_array, PhoneModelMixin,
)
@ -1124,7 +1126,7 @@ class EmployeeQuerySet(models.QuerySet):
)
class Employee(BaseAttributes):
class Employee(PhoneModelMixin, BaseAttributes):
"""Employee model."""
user = models.OneToOneField('account.User', on_delete=models.PROTECT,
@ -1210,7 +1212,7 @@ class EstablishmentScheduleQuerySet(models.QuerySet):
"""QuerySet for model EstablishmentSchedule"""
class ContactPhone(models.Model):
class ContactPhone(PhoneModelMixin, models.Model):
"""Contact phone model."""
establishment = models.ForeignKey(
Establishment, related_name='phones', on_delete=models.CASCADE)
@ -1223,16 +1225,6 @@ class ContactPhone(models.Model):
def __str__(self):
return f'{self.phone.as_e164}'
@property
def country_calling_code(self):
"""Return phone code from PhonеNumberField."""
return f'+{self.phone.country_code}' if self.phone and hasattr(self, 'phone') else None
@property
def national_calling_number(self):
"""Return phone national number from from PhonеNumberField."""
return self.phone.national_number if self.phone and hasattr(self, 'phone') else None
class ContactEmail(models.Model):
"""Contact email model."""
@ -1571,3 +1563,46 @@ class Company(ProjectBaseMixin):
"""Meta class."""
verbose_name = _('company')
verbose_name_plural = _('companies')
def _phonenumber_constructor(self, field_name: str) -> list:
array = []
if field_name in [field.name for field in self._meta.fields]:
values = getattr(self, field_name, None)
if values:
for number in values:
try:
obj = PhoneNumber.from_string(
phone_number=number,
region=None if number.startswith('+')
else settings.PHONENUMBER_DEFAULT_REGION)
except Exception as e:
pass
else:
array.append(obj) if obj.is_valid() else None
return array
def phones_(self) -> list:
"""Return PhoneNumber objects."""
return self._phonenumber_constructor('phones')
def faxes_(self) -> list:
"""Return PhoneNumber objects."""
return self._phonenumber_constructor('faxes')
def _array_constructor(self, field_name: str) -> list:
array = []
for obj in self._phonenumber_constructor(field_name):
if hasattr(obj, 'country_code') and hasattr(obj, 'national_number'):
array.append({
'country_calling_code': f'+{obj.country_code}',
'national_calling_number': str(obj.national_number),
})
return array
@property
def phones_array(self) -> list:
return self._array_constructor('phones')
@property
def faxes_array(self) -> list:
return self._array_constructor('faxes')

View File

@ -14,7 +14,8 @@ from location.serializers import AddressDetailSerializer, TranslatedField
from main.models import Currency
from main.serializers import AwardSerializer
from utils.decorators import with_base_attributes
from utils.serializers import ImageBaseSerializer, ProjectModelSerializer, TimeZoneChoiceField
from utils.serializers import ImageBaseSerializer, ProjectModelSerializer, TimeZoneChoiceField, \
PhoneMixinSerializer
def phones_handler(phones_list, establishment):
@ -136,6 +137,17 @@ class EstablishmentPositionListSerializer(model_serializers.EstablishmentBaseSer
]
class EstablishmentContactPhoneSerializer(PhoneMixinSerializer, serializers.ModelSerializer):
"""Establishment contact phone serializer."""
class Meta:
"""Meta class."""
model = models.ContactPhone
fields = [
'country_calling_code',
'national_calling_number',
]
class EstablishmentRUDSerializer(model_serializers.EstablishmentBaseSerializer):
"""Establishment create serializer"""
@ -156,16 +168,9 @@ class EstablishmentRUDSerializer(model_serializers.EstablishmentBaseSerializer):
subtypes = model_serializers.EstablishmentSubTypeBaseSerializer(source='establishment_subtypes',
read_only=True, many=True)
type = model_serializers.EstablishmentTypeBaseSerializer(source='establishment_type', read_only=True)
phones = serializers.ListField(
source='contact_phones',
allow_null=True,
allow_empty=True,
child=serializers.CharField(max_length=128),
required=False,
)
phones = EstablishmentContactPhoneSerializer(read_only=True, many=True)
class Meta:
model = models.Establishment
class Meta(model_serializers.EstablishmentBaseSerializer.Meta):
fields = [
'id',
'slug',
@ -248,10 +253,8 @@ class PlatesSerializers(model_serializers.PlateSerializer):
]
class ContactPhoneBackSerializers(model_serializers.PlateSerializer):
class ContactPhoneBackSerializers(PhoneMixinSerializer, serializers.ModelSerializer):
"""ContactPhone serializers."""
country_calling_code = serializers.CharField(read_only=True, allow_null=True)
national_calling_number = serializers.CharField(read_only=True, allow_null=True)
class Meta:
model = models.ContactPhone
@ -262,6 +265,9 @@ class ContactPhoneBackSerializers(model_serializers.PlateSerializer):
'country_calling_code',
'national_calling_number',
]
extra_kwarg = {
'phone': {'write_only': True}
}
class ContactEmailBackSerializers(model_serializers.PlateSerializer):
@ -293,7 +299,7 @@ class PositionBackSerializer(serializers.ModelSerializer):
# TODO: test decorator
@with_base_attributes
class EmployeeBackSerializers(serializers.ModelSerializer):
class EmployeeBackSerializers(PhoneMixinSerializer, serializers.ModelSerializer):
"""Employee serializers."""
public_mark = serializers.SerializerMethodField()
positions = serializers.SerializerMethodField()
@ -385,11 +391,16 @@ class EmployeeBackSerializers(serializers.ModelSerializer):
'birth_date',
'email',
'phone',
'country_calling_code',
'national_calling_number',
'toque_number',
'available_for_events',
'photo',
'photo_id',
]
extra_kwargs = {
'phone': {'write_only': True}
}
class EstablishmentEmployeeBackSerializer(serializers.ModelSerializer):
@ -411,6 +422,7 @@ class EstablishmentEmployeeBackSerializer(serializers.ModelSerializer):
class EstEmployeeBackSerializer(EmployeeBackSerializers):
@property
def request_kwargs(self):
"""Get url kwargs from request."""
@ -451,10 +463,15 @@ class EstEmployeeBackSerializer(EmployeeBackSerializers):
'birth_date',
'email',
'phone',
'country_calling_code',
'national_calling_number',
'toque_number',
'available_for_events',
'photo',
]
extra_kwargs = {
'phone': {'write_only': True}
}
class EstablishmentBackOfficeGallerySerializer(serializers.ModelSerializer):

View File

@ -633,8 +633,8 @@ class EstablishmentCarouselCreateSerializer(CarouselCreateSerializer):
class CompanyBaseSerializer(serializers.ModelSerializer):
"""Company base serializer"""
phone_list = serializers.SerializerMethodField(source='phones', read_only=True)
fax_list = serializers.SerializerMethodField(source='faxes', read_only=True)
phone_list = serializers.ListField(source='phones_array', read_only=True)
fax_list = serializers.ListField(source='faxes_array', read_only=True)
address_detail = AddressDetailSerializer(source='address', read_only=True)
class Meta:
@ -662,14 +662,6 @@ class CompanyBaseSerializer(serializers.ModelSerializer):
'address': {'write_only': True}
}
def get_phone_list(self, instance):
"""Return list of phone numbers."""
return instance.phones
def get_fax_list(self, instance):
"""Return list of fax numbers."""
return instance.faxes
def validate(self, attrs):
"""Overridden validate method"""
phones = [str_to_phonenumber(phone).as_national for phone in attrs.get('phones')]

View File

@ -511,3 +511,18 @@ class TypeDefaultImageMixin:
def default_menu_bool_array():
return [False] * 7
class PhoneModelMixin:
"""Mixin for PhoneNumberField."""
@property
def country_calling_code(self):
"""Return phone code from PhonеNumberField."""
if hasattr(self, 'phone') and self.phone:
return f'+{self.phone.country_code}'
@property
def national_calling_number(self):
"""Return phone national number from from PhonеNumberField."""
if hasattr(self, 'phone') and (self.phone and hasattr(self.phone, 'national_number')):
return self.phone.national_number

View File

@ -137,3 +137,9 @@ class ImageBaseSerializer(serializers.Serializer):
original_url = serializers.URLField()
orientation_display = serializers.CharField()
auto_crop_images = serializers.DictField(allow_null=True)
class PhoneMixinSerializer(serializers.Serializer):
"""Phone mixin serializer."""
country_calling_code = serializers.CharField(read_only=True, allow_null=True)
national_calling_number = serializers.CharField(read_only=True, allow_null=True)

View File

@ -86,11 +86,11 @@ LOGGING = {
'py.warnings': {
'handlers': ['console'],
},
'django.db.backends': {
'handlers': ['console', ],
'level': 'DEBUG',
'propagate': False,
},
# 'django.db.backends': {
# 'handlers': ['console', ],
# 'level': 'DEBUG',
# 'propagate': False,
# },
}
}