Merge branch 'feature/roles' into 'develop'

Feature/roles

See merge request gm/gm-backend!50
This commit is contained in:
d.kuzmenko 2019-10-14 07:09:18 +00:00
commit 1f6bf819e8
21 changed files with 1256 additions and 4 deletions

View File

@ -2,10 +2,19 @@
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.utils.translation import ugettext_lazy as _
from account import models
@admin.register(models.Role)
class RoleAdmin(admin.ModelAdmin):
list_display = ['role', 'country']
@admin.register(models.UserRole)
class UserRoleAdmin(admin.ModelAdmin):
list_display = ['user', 'role']
@admin.register(models.User)
class UserAdmin(BaseUserAdmin):
"""User model admin settings."""

View File

@ -0,0 +1,48 @@
# Generated by Django 2.2.4 on 2019-10-11 11:23
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('location', '0011_country_languages'),
('account', '0008_auto_20190912_1325'),
]
operations = [
migrations.CreateModel(
name='Role',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')),
('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('role', models.PositiveIntegerField(choices=[(1, 'Standard user'), (2, 'Comments moderator')], verbose_name='Role')),
('country', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='location.Country', verbose_name='Country')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='UserRole',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')),
('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')),
('role', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='account.Role', verbose_name='Role')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')),
],
options={
'abstract': False,
},
),
migrations.AddField(
model_name='user',
name='roles',
field=models.ManyToManyField(through='account.UserRole', to='account.Role', verbose_name='Roles'),
),
]

View File

@ -13,11 +13,30 @@ from django.utils.translation import ugettext_lazy as _
from rest_framework.authtoken.models import Token
from authorization.models import Application
from location.models import Country
from utils.models import GMTokenGenerator
from utils.models import ImageMixin, ProjectBaseMixin, PlatformMixin
from utils.tokens import GMRefreshToken
class Role(ProjectBaseMixin):
"""Base Role model."""
STANDARD_USER = 1
COMMENTS_MODERATOR = 2
ROLE_CHOICES =(
(STANDARD_USER, 'Standard user'),
(COMMENTS_MODERATOR, 'Comments moderator'),
)
role = models.PositiveIntegerField(verbose_name=_('Role'), choices=ROLE_CHOICES,
null=False, blank=False)
country = models.ForeignKey(Country, verbose_name=_('Country'), on_delete=models.CASCADE)
# is_list = models.BooleanField(verbose_name=_('list'), default=True, null=False)
# is_create = models.BooleanField(verbose_name=_('create'), default=False, null=False)
# is_update = models.BooleanField(verbose_name=_('update'), default=False, null=False)
# is_delete = models.BooleanField(verbose_name=_('delete'), default=False, null=False)
class UserManager(BaseUserManager):
"""Extended manager for User model."""
@ -69,6 +88,7 @@ class User(AbstractUser):
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
roles = models.ManyToManyField(Role, verbose_name=_('Roles'), through='UserRole')
objects = UserManager.from_queryset(UserQuerySet)()
class Meta:
@ -218,3 +238,9 @@ class User(AbstractUser):
return render_to_string(
template_name=settings.CHANGE_EMAIL_TEMPLATE,
context=context)
class UserRole(ProjectBaseMixin):
"""UserRole model."""
user = models.ForeignKey(User, verbose_name=_('User'), on_delete=models.CASCADE)
role = models.ForeignKey(Role, verbose_name=_('Role'), on_delete=models.SET_NULL, null=True)

View File

View File

@ -0,0 +1,21 @@
"""Back account serializers"""
from rest_framework import serializers
from account import models
class RoleSerializer(serializers.ModelSerializer):
class Meta:
model = models.Role
fields = [
'role',
'country'
]
class UserRoleSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserRole
fields = [
'user',
'role'
]

View File

@ -0,0 +1,81 @@
from rest_framework.test import APITestCase
from rest_framework import status
from authorization.tests.tests_authorization import get_tokens_for_user
from django.urls import reverse
from http.cookies import SimpleCookie
from location.models import Country
from account.models import Role, User, UserRole
class RoleTests(APITestCase):
def setUp(self):
self.data = get_tokens_for_user()
self.client.cookies = SimpleCookie(
{'access_token': self.data['tokens'].get('access_token'),
'refresh_token': self.data['tokens'].get('access_token')})
def test_role_get(self):
url = reverse('back:account:role-list-create')
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_role_post(self):
url = reverse('back:account:role-list-create')
country = Country.objects.create(
name='{"ru-RU":"Russia"}',
code='23',
low_price=15,
high_price=150000
)
country.save()
data = {
"role": 2,
"country": country.pk
}
response = self.client.post(url, data=data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
class UserRoleTests(APITestCase):
def setUp(self):
self.data = get_tokens_for_user()
self.client.cookies = SimpleCookie(
{'access_token': self.data['tokens'].get('access_token'),
'refresh_token': self.data['tokens'].get('access_token')})
self.country_ru = Country.objects.create(
name='{"ru-RU":"Russia"}',
code='23',
low_price=15,
high_price=150000
)
self.country_ru.save()
self.country_en = Country.objects.create(
name='{"en-GB":"England"}',
code='25',
low_price=15,
high_price=150000
)
self.country_en.save()
self.role = Role.objects.create(
role=2,
country=self.country_ru
)
self.role.save()
self.user_test = User.objects.create_user(username='test',
email='testemail@mail.com',
password='passwordtest')
def test_user_role_post(self):
url = reverse('back:account:user-role-list-create')
data = {
"user": self.user_test.id,
"role": self.role.id
}
response = self.client.post(url, data=data, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)

12
apps/account/urls/back.py Normal file
View File

@ -0,0 +1,12 @@
"""Back account URLs"""
from django.urls import path
from account.views import back as views
app_name = 'account'
urlpatterns = [
path('role/', views.RoleLstView.as_view(), name='role-list-create'),
path('user-role/', views.UserRoleLstView.as_view(), name='user-role-list-create'),
]

View File

@ -0,0 +1,13 @@
from rest_framework import generics
from account.serializers import back as serializers
from account import models
class RoleLstView(generics.ListCreateAPIView):
serializer_class = serializers.RoleSerializer
queryset = models.Role.objects.all()
class UserRoleLstView(generics.ListCreateAPIView):
serializer_class = serializers.UserRoleSerializer
queryset = models.Role.objects.all()

View File

@ -0,0 +1,20 @@
# Generated by Django 2.2.4 on 2019-10-10 11:46
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('translation', '0003_auto_20190901_1032'),
('comment', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='comment',
name='language',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='translation.Language', verbose_name='Locale'),
),
]

View File

@ -6,7 +6,7 @@ from django.utils.translation import gettext_lazy as _
from account.models import User
from utils.models import ProjectBaseMixin
from utils.querysets import ContentTypeQuerySetMixin
from translation.models import Language
class CommentQuerySet(ContentTypeQuerySetMixin):
"""QuerySets for Comment model."""
@ -41,6 +41,7 @@ class Comment(ProjectBaseMixin):
content_object = generic.GenericForeignKey('content_type', 'object_id')
objects = CommentQuerySet.as_manager()
language = models.ForeignKey(Language, verbose_name=_('Locale'), on_delete=models.SET_NULL, null=True)
class Meta:
"""Meta class"""

View File

@ -0,0 +1,28 @@
from rest_framework import permissions
from account.models import UserRole, Role, User
class IsCommentModerator(permissions.IsAuthenticatedOrReadOnly):
"""
Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `owner` attribute.
"""
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS or \
obj.user == request.user or request.user.is_superuser:
return True
# Must have role
role = Role.objects.filter(role=Role.COMMENTS_MODERATOR,
country__languages__id=obj.language_id)\
.first() # 'Comments moderator'
is_access = UserRole.objects.filter(user=request.user, role=role).exists()
if obj.user != request.user and is_access:
return True
return False

View File

@ -0,0 +1,9 @@
"""Comment app common serializers."""
from comment import models
from rest_framework import serializers
class CommentBaseSerializer(serializers.ModelSerializer):
class Meta:
model = models.Comment
fields = ('id', 'text', 'mark', 'user')

View File

@ -1 +1,123 @@
# Create your tests here.
from rest_framework.test import APITestCase
from rest_framework import status
from authorization.tests.tests_authorization import get_tokens_for_user
from django.urls import reverse
from django.contrib.contenttypes.models import ContentType
from http.cookies import SimpleCookie
from location.models import Country
from account.models import Role, User, UserRole
from comment.models import Comment
from translation.models import Language
class CommentModeratorPermissionTests(APITestCase):
def setUp(self):
self.lang = Language.objects.create(
title='Russia',
locale='ru-RU'
)
self.lang.save()
self.country_ru = Country.objects.create(
name='{"ru-RU":"Russia"}',
code='23',
low_price=15,
high_price=150000,
)
self.country_ru.languages.add(self.lang)
self.country_ru.save()
self.role = Role.objects.create(
role=2,
country=self.country_ru
)
self.role.save()
self.moderator = User.objects.create_user(username='moderator',
email='moderator@mail.com',
password='passwordmoderator')
self.userRole = UserRole.objects.create(
user=self.moderator,
role=self.role
)
self.userRole.save()
content_type = ContentType.objects.get(app_label='location', model='country')
self.user_test = get_tokens_for_user()
self.comment = Comment.objects.create(text='Test comment', mark=1,
user=self.user_test["user"],
object_id= self.country_ru.pk,
content_type_id=content_type.id,
language=self.lang
)
self.comment.save()
self.url = reverse('back:comment:comment-crud', kwargs={"id": self.comment.id})
def test_get(self):
response = self.client.get(self.url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_put_moderator(self):
tokens = User.create_jwt_tokens(self.moderator)
self.client.cookies = SimpleCookie(
{'access_token': tokens.get('access_token'),
'refresh_token': tokens.get('access_token')})
data = {
"id": self.comment.id,
"text": "test text moderator",
"mark": 1,
"user": self.moderator.id
}
response = self.client.put(self.url, data=data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_put_other_user(self):
other_user = User.objects.create_user(username='test',
email='test@mail.com',
password='passwordtest')
tokens = User.create_jwt_tokens(other_user)
self.client.cookies = SimpleCookie(
{'access_token': tokens.get('access_token'),
'refresh_token': tokens.get('access_token')})
data = {
"id": self.comment.id,
"text": "test text moderator",
"mark": 1,
"user": other_user.id
}
response = self.client.put(self.url, data=data, format='json')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def test_put_super_user(self):
super_user = User.objects.create_user(username='super',
email='super@mail.com',
password='passwordtestsuper',
is_superuser=True)
tokens = User.create_jwt_tokens(super_user)
self.client.cookies = SimpleCookie(
{'access_token': tokens.get('access_token'),
'refresh_token': tokens.get('access_token')})
data = {
"id": self.comment.id,
"text": "test text moderator",
"mark": 1,
"user": super_user.id
}
response = self.client.put(self.url, data=data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)

11
apps/comment/urls/back.py Normal file
View File

@ -0,0 +1,11 @@
"""Back comment URLs"""
from django.urls import path
from comment.views import back as views
app_name = 'comment'
urlpatterns = [
path('', views.CommentLstView.as_view(), name='comment-list-create'),
path('<int:id>/', views.CommentRUDView.as_view(), name='comment-crud'),
]

View File

@ -0,0 +1,19 @@
from rest_framework import generics, permissions
from comment.serializers import back as serializers
from comment import models
from comment.permissions import IsCommentModerator
class CommentLstView(generics.ListCreateAPIView):
"""Comment list create view."""
serializer_class = serializers.CommentBaseSerializer
queryset = models.Comment.objects.all()
permission_classes = [permissions.IsAuthenticatedOrReadOnly,]
class CommentRUDView(generics.RetrieveUpdateDestroyAPIView):
"""Comment RUD view."""
serializer_class = serializers.CommentBaseSerializer
queryset = models.Comment.objects.all()
permission_classes = [IsCommentModerator]
lookup_field = 'id'

View File

@ -0,0 +1,19 @@
# Generated by Django 2.2.4 on 2019-10-10 12:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('translation', '0003_auto_20190901_1032'),
('location', '0010_auto_20190904_0711'),
]
operations = [
migrations.AddField(
model_name='country',
name='languages',
field=models.ManyToManyField(to='translation.Language', verbose_name='Languages'),
),
]

View File

@ -0,0 +1,25 @@
from django.db import migrations, connection
import os
class Migration(migrations.Migration):
def load_data_from_sql(apps, schema_editor):
file_path = os.path.join(os.path.dirname(__file__), 'migrate_lang.sql')
sql_statement = open(file_path).read()
with connection.cursor() as c:
c.execute(sql_statement)
def revert_data(apps, schema_editor):
file_path = os.path.join(os.path.dirname(__file__), 'remigrate_lang.sql')
sql_statement = open(file_path).read()
with connection.cursor() as c:
c.execute(sql_statement)
dependencies = [
('location', '0011_country_languages'),
]
operations = [
migrations.RunPython(load_data_from_sql, revert_data),
]

View File

@ -0,0 +1,390 @@
delete from comment_comment as cc;
delete from location_country_languages;
delete from translation_language as tl;
delete from location_country as lc;
CREATE TABLE public.codelang (
code varchar(100) NULL,
country varchar(10000) NULL
);
-- Permissions
ALTER TABLE public.codelang OWNER TO postgres;
GRANT ALL ON TABLE public.codelang TO postgres;
INSERT INTO public.codelang (code,country) VALUES
('af','Afrikaans')
,('af-ZA','Afrikaans (South Africa)')
,('ar','Arabic')
,('ar-AE','Arabic (U.A.E.)')
,('ar-BH','Arabic (Bahrain)')
,('ar-DZ','Arabic (Algeria)')
,('ar-EG','Arabic (Egypt)')
,('ar-IQ','Arabic (Iraq)')
,('ar-JO','Arabic (Jordan)')
,('ar-KW','Arabic (Kuwait)')
;
INSERT INTO public.codelang (code,country) VALUES
('ar-LB','Arabic (Lebanon)')
,('ar-LY','Arabic (Libya)')
,('ar-MA','Arabic (Morocco)')
,('ar-OM','Arabic (Oman)')
,('ar-QA','Arabic (Qatar)')
,('ar-SA','Arabic (Saudi Arabia)')
,('ar-SY','Arabic (Syria)')
,('ar-TN','Arabic (Tunisia)')
,('ar-YE','Arabic (Yemen)')
,('az','Azeri (Latin)')
;
INSERT INTO public.codelang (code,country) VALUES
('az-AZ','Azeri (Latin) (Azerbaijan)')
,('az-AZ','Azeri (Cyrillic) (Azerbaijan)')
,('be','Belarusian')
,('be-BY','Belarusian (Belarus)')
,('bg','Bulgarian')
,('bg-BG','Bulgarian (Bulgaria)')
,('bs-BA','Bosnian (Bosnia and Herzegovina)')
,('ca','Catalan')
,('ca-ES','Catalan (Spain)')
,('cs','Czech')
;
INSERT INTO public.codelang (code,country) VALUES
('cs-CZ','Czech (Czech Republic)')
,('cy','Welsh')
,('cy-GB','Welsh (United Kingdom)')
,('da','Danish')
,('da-DK','Danish (Denmark)')
,('de','German')
,('de-AT','German (Austria)')
,('de-CH','German (Switzerland)')
,('de-DE','German (Germany)')
,('de-LI','German (Liechtenstein)')
;
INSERT INTO public.codelang (code,country) VALUES
('de-LU','German (Luxembourg)')
,('dv','Divehi')
,('dv-MV','Divehi (Maldives)')
,('el','Greek')
,('el-GR','Greek (Greece)')
,('en','English')
,('en-AU','English (Australia)')
,('en-BZ','English (Belize)')
,('en-CA','English (Canada)')
,('en-CB','English (Caribbean)')
;
INSERT INTO public.codelang (code,country) VALUES
('en-GB','English (United Kingdom)')
,('en-IE','English (Ireland)')
,('en-JM','English (Jamaica)')
,('en-NZ','English (New Zealand)')
,('en-PH','English (Republic of the Philippines)')
,('en-TT','English (Trinidad and Tobago)')
,('en-US','English (United States)')
,('en-ZA','English (South Africa)')
,('en-ZW','English (Zimbabwe)')
,('eo','Esperanto')
;
INSERT INTO public.codelang (code,country) VALUES
('es','Spanish')
,('es-AR','Spanish (Argentina)')
,('es-BO','Spanish (Bolivia)')
,('es-CL','Spanish (Chile)')
,('es-CO','Spanish (Colombia)')
,('es-CR','Spanish (Costa Rica)')
,('es-DO','Spanish (Dominican Republic)')
,('es-EC','Spanish (Ecuador)')
,('es-ES','Spanish (Castilian)')
,('es-ES','Spanish (Spain)')
;
INSERT INTO public.codelang (code,country) VALUES
('es-GT','Spanish (Guatemala)')
,('es-HN','Spanish (Honduras)')
,('es-MX','Spanish (Mexico)')
,('es-NI','Spanish (Nicaragua)')
,('es-PA','Spanish (Panama)')
,('es-PE','Spanish (Peru)')
,('es-PR','Spanish (Puerto Rico)')
,('es-PY','Spanish (Paraguay)')
,('es-SV','Spanish (El Salvador)')
,('es-UY','Spanish (Uruguay)')
;
INSERT INTO public.codelang (code,country) VALUES
('es-VE','Spanish (Venezuela)')
,('et','Estonian')
,('et-EE','Estonian (Estonia)')
,('eu','Basque')
,('eu-ES','Basque (Spain)')
,('fa','Farsi')
,('fa-IR','Farsi (Iran)')
,('fi','Finnish')
,('fi-FI','Finnish (Finland)')
,('fo','Faroese')
;
INSERT INTO public.codelang (code,country) VALUES
('fo-FO','Faroese (Faroe Islands)')
,('fr','French')
,('fr-BE','French (Belgium)')
,('fr-CA','French (Canada)')
,('fr-CH','French (Switzerland)')
,('fr-FR','French (France)')
,('fr-LU','French (Luxembourg)')
,('fr-MC','French (Principality of Monaco)')
,('gl','Galician')
,('gl-ES','Galician (Spain)')
;
INSERT INTO public.codelang (code,country) VALUES
('gu','Gujarati')
,('gu-IN','Gujarati (India)')
,('he','Hebrew')
,('he-IL','Hebrew (Israel)')
,('hi','Hindi')
,('hi-IN','Hindi (India)')
,('hr','Croatian')
,('hr-BA','Croatian (Bosnia and Herzegovina)')
,('hr-HR','Croatian (Croatia)')
,('hu','Hungarian')
;
INSERT INTO public.codelang (code,country) VALUES
('hu-HU','Hungarian (Hungary)')
,('hy','Armenian')
,('hy-AM','Armenian (Armenia)')
,('id','Indonesian')
,('id-ID','Indonesian (Indonesia)')
,('is','Icelandic')
,('is-IS','Icelandic (Iceland)')
,('it','Italian')
,('it-CH','Italian (Switzerland)')
,('it-IT','Italian (Italy)')
;
INSERT INTO public.codelang (code,country) VALUES
('ja','Japanese')
,('ja-JP','Japanese (Japan)')
,('ka','Georgian')
,('ka-GE','Georgian (Georgia)')
,('kk','Kazakh')
,('kk-KZ','Kazakh (Kazakhstan)')
,('kn','Kannada')
,('kn-IN','Kannada (India)')
,('ko','Korean')
,('ko-KR','Korean (Korea)')
;
INSERT INTO public.codelang (code,country) VALUES
('kok','Konkani')
,('kok-IN','Konkani (India)')
,('ky','Kyrgyz')
,('ky-KG','Kyrgyz (Kyrgyzstan)')
,('lt','Lithuanian')
,('lt-LT','Lithuanian (Lithuania)')
,('lv','Latvian')
,('lv-LV','Latvian (Latvia)')
,('mi','Maori')
,('mi-NZ','Maori (New Zealand)')
;
INSERT INTO public.codelang (code,country) VALUES
('mk','FYRO Macedonian')
,('mk-MK','FYRO Macedonian (Former Yugoslav Republic of Macedonia)')
,('mn','Mongolian')
,('mn-MN','Mongolian (Mongolia)')
,('mr','Marathi')
,('mr-IN','Marathi (India)')
,('ms','Malay')
,('ms-BN','Malay (Brunei Darussalam)')
,('ms-MY','Malay (Malaysia)')
,('mt','Maltese')
;
INSERT INTO public.codelang (code,country) VALUES
('mt-MT','Maltese (Malta)')
,('nb','Norwegian (Bokm?l)')
,('nb-NO','Norwegian (Bokm?l) (Norway)')
,('nl','Dutch')
,('nl-BE','Dutch (Belgium)')
,('nl-NL','Dutch (Netherlands)')
,('nn-NO','Norwegian (Nynorsk) (Norway)')
,('ns','Northern Sotho')
,('ns-ZA','Northern Sotho (South Africa)')
,('pa','Punjabi')
;
INSERT INTO public.codelang (code,country) VALUES
('pa-IN','Punjabi (India)')
,('pl','Polish')
,('pl-PL','Polish (Poland)')
,('ps','Pashto')
,('ps-AR','Pashto (Afghanistan)')
,('pt','Portuguese')
,('pt-BR','Portuguese (Brazil)')
,('pt-PT','Portuguese (Portugal)')
,('qu','Quechua')
,('qu-BO','Quechua (Bolivia)')
;
INSERT INTO public.codelang (code,country) VALUES
('qu-EC','Quechua (Ecuador)')
,('qu-PE','Quechua (Peru)')
,('ro','Romanian')
,('ro-RO','Romanian (Romania)')
,('ru','Russian')
,('ru-RU','Russian (Russia)')
,('sa','Sanskrit')
,('sa-IN','Sanskrit (India)')
,('se','Sami (Northern)')
,('se-FI','Sami (Northern) (Finland)')
;
INSERT INTO public.codelang (code,country) VALUES
('se-FI','Sami (Skolt) (Finland)')
,('se-FI','Sami (Inari) (Finland)')
,('se-NO','Sami (Northern) (Norway)')
,('se-NO','Sami (Lule) (Norway)')
,('se-NO','Sami (Southern) (Norway)')
,('se-SE','Sami (Northern) (Sweden)')
,('se-SE','Sami (Lule) (Sweden)')
,('se-SE','Sami (Southern) (Sweden)')
,('sk','Slovak')
,('sk-SK','Slovak (Slovakia)')
;
INSERT INTO public.codelang (code,country) VALUES
('sl','Slovenian')
,('sl-SI','Slovenian (Slovenia)')
,('sq','Albanian')
,('sq-AL','Albanian (Albania)')
,('sr-BA','Serbian (Latin) (Bosnia and Herzegovina)')
,('sr-BA','Serbian (Cyrillic) (Bosnia and Herzegovina)')
,('sr-SP','Serbian (Latin) (Serbia and Montenegro)')
,('sr-SP','Serbian (Cyrillic) (Serbia and Montenegro)')
,('sv','Swedish')
,('sv-FI','Swedish (Finland)')
;
INSERT INTO public.codelang (code,country) VALUES
('sv-SE','Swedish (Sweden)')
,('sw','Swahili')
,('sw-KE','Swahili (Kenya)')
,('syr','Syriac')
,('syr-SY','Syriac (Syria)')
,('ta','Tamil')
,('ta-IN','Tamil (India)')
,('te','Telugu')
,('te-IN','Telugu (India)')
,('th','Thai')
;
INSERT INTO public.codelang (code,country) VALUES
('th-TH','Thai (Thailand)')
,('tl','Tagalog')
,('tl-PH','Tagalog (Philippines)')
,('tn','Tswana')
,('tn-ZA','Tswana (South Africa)')
,('tr','Turkish')
,('tr-TR','Turkish (Turkey)')
,('tt','Tatar')
,('tt-RU','Tatar (Russia)')
,('ts','Tsonga')
;
INSERT INTO public.codelang (code,country) VALUES
('uk','Ukrainian')
,('uk-UA','Ukrainian (Ukraine)')
,('ur','Urdu')
,('ur-PK','Urdu (Islamic Republic of Pakistan)')
,('uz','Uzbek (Latin)')
,('uz-UZ','Uzbek (Latin) (Uzbekistan)')
,('uz-UZ','Uzbek (Cyrillic) (Uzbekistan)')
,('vi','Vietnamese')
,('vi-VN','Vietnamese (Viet Nam)')
,('xh','Xhosa')
;
INSERT INTO public.codelang (code,country) VALUES
('xh-ZA','Xhosa (South Africa)')
,('zh','Chinese')
,('zh-CN','Chinese (S)')
,('zh-HK','Chinese (Hong Kong)')
,('zh-MO','Chinese (Macau)')
,('zh-SG','Chinese (Singapore)')
,('zh-TW','Chinese (T)')
,('zu','Zulu')
,('zu-ZA','Zulu (South Africa)')
;
/***************************/
-- Manual migrate
CREATE TABLE public.country_code (
code varchar(100) NULL,
country varchar(10000) NULL
);
insert into country_code(code, country)
select distinct
t.code,
coalesce(
case when length(t.country_name2) = 1 then null else t.country_name2 end,
case when length(t.contry_name1) = 1 then null else t.contry_name1 end,
t.country
) as country
from
(
select trim(c.code) as code,
substring(trim(c.country) from '\((.+)\)') as contry_name1,
substring(
substring(trim(c.country) from '\((.+)\)')
from '\((.*)$') as country_name2,
trim(c.country) as country
from codelang as c
) t;
commit;
--delete from location_country as lc
INSERT INTO public.location_country
(code, "name", low_price, high_price, created, modified)
select
lpad((row_number() over (order by t.country asc))::text, 3, '0') as code,
jsonb_build_object('en-GB', t.country),
0 as low_price,
100 as high_price,
now() as created,
now() as modified
from
(
select
distinct c.country
from country_code c
) t
;
commit;
--delete from translation_language as tl;
INSERT INTO public.translation_language
(title, locale)
select
t.country as title,
t.code as locale
from
(
select
distinct c.country, c.code
from country_code c
) t
;
commit;
--delete from location_country_languages
INSERT INTO public.location_country_languages
(country_id, language_id)
select lc.id as country_id,
l.id as language_id
from location_country as lc
join (
select tl.*, '"'||tl.title||'"' as country
from translation_language as tl
) l on l.country = (lc."name"::json->'en-GB')::text
;
commit;
drop table country_code;
drop table codelang;
commit;

View File

@ -0,0 +1,394 @@
CREATE TABLE public.codelang (
code varchar(100) NULL,
country varchar(10000) NULL
);
-- Permissions
ALTER TABLE public.codelang OWNER TO postgres;
GRANT ALL ON TABLE public.codelang TO postgres;
INSERT INTO public.codelang (code,country) VALUES
('af','Afrikaans')
,('af-ZA','Afrikaans (South Africa)')
,('ar','Arabic')
,('ar-AE','Arabic (U.A.E.)')
,('ar-BH','Arabic (Bahrain)')
,('ar-DZ','Arabic (Algeria)')
,('ar-EG','Arabic (Egypt)')
,('ar-IQ','Arabic (Iraq)')
,('ar-JO','Arabic (Jordan)')
,('ar-KW','Arabic (Kuwait)')
;
INSERT INTO public.codelang (code,country) VALUES
('ar-LB','Arabic (Lebanon)')
,('ar-LY','Arabic (Libya)')
,('ar-MA','Arabic (Morocco)')
,('ar-OM','Arabic (Oman)')
,('ar-QA','Arabic (Qatar)')
,('ar-SA','Arabic (Saudi Arabia)')
,('ar-SY','Arabic (Syria)')
,('ar-TN','Arabic (Tunisia)')
,('ar-YE','Arabic (Yemen)')
,('az','Azeri (Latin)')
;
INSERT INTO public.codelang (code,country) VALUES
('az-AZ','Azeri (Latin) (Azerbaijan)')
,('az-AZ','Azeri (Cyrillic) (Azerbaijan)')
,('be','Belarusian')
,('be-BY','Belarusian (Belarus)')
,('bg','Bulgarian')
,('bg-BG','Bulgarian (Bulgaria)')
,('bs-BA','Bosnian (Bosnia and Herzegovina)')
,('ca','Catalan')
,('ca-ES','Catalan (Spain)')
,('cs','Czech')
;
INSERT INTO public.codelang (code,country) VALUES
('cs-CZ','Czech (Czech Republic)')
,('cy','Welsh')
,('cy-GB','Welsh (United Kingdom)')
,('da','Danish')
,('da-DK','Danish (Denmark)')
,('de','German')
,('de-AT','German (Austria)')
,('de-CH','German (Switzerland)')
,('de-DE','German (Germany)')
,('de-LI','German (Liechtenstein)')
;
INSERT INTO public.codelang (code,country) VALUES
('de-LU','German (Luxembourg)')
,('dv','Divehi')
,('dv-MV','Divehi (Maldives)')
,('el','Greek')
,('el-GR','Greek (Greece)')
,('en','English')
,('en-AU','English (Australia)')
,('en-BZ','English (Belize)')
,('en-CA','English (Canada)')
,('en-CB','English (Caribbean)')
;
INSERT INTO public.codelang (code,country) VALUES
('en-GB','English (United Kingdom)')
,('en-IE','English (Ireland)')
,('en-JM','English (Jamaica)')
,('en-NZ','English (New Zealand)')
,('en-PH','English (Republic of the Philippines)')
,('en-TT','English (Trinidad and Tobago)')
,('en-US','English (United States)')
,('en-ZA','English (South Africa)')
,('en-ZW','English (Zimbabwe)')
,('eo','Esperanto')
;
INSERT INTO public.codelang (code,country) VALUES
('es','Spanish')
,('es-AR','Spanish (Argentina)')
,('es-BO','Spanish (Bolivia)')
,('es-CL','Spanish (Chile)')
,('es-CO','Spanish (Colombia)')
,('es-CR','Spanish (Costa Rica)')
,('es-DO','Spanish (Dominican Republic)')
,('es-EC','Spanish (Ecuador)')
,('es-ES','Spanish (Castilian)')
,('es-ES','Spanish (Spain)')
;
INSERT INTO public.codelang (code,country) VALUES
('es-GT','Spanish (Guatemala)')
,('es-HN','Spanish (Honduras)')
,('es-MX','Spanish (Mexico)')
,('es-NI','Spanish (Nicaragua)')
,('es-PA','Spanish (Panama)')
,('es-PE','Spanish (Peru)')
,('es-PR','Spanish (Puerto Rico)')
,('es-PY','Spanish (Paraguay)')
,('es-SV','Spanish (El Salvador)')
,('es-UY','Spanish (Uruguay)')
;
INSERT INTO public.codelang (code,country) VALUES
('es-VE','Spanish (Venezuela)')
,('et','Estonian')
,('et-EE','Estonian (Estonia)')
,('eu','Basque')
,('eu-ES','Basque (Spain)')
,('fa','Farsi')
,('fa-IR','Farsi (Iran)')
,('fi','Finnish')
,('fi-FI','Finnish (Finland)')
,('fo','Faroese')
;
INSERT INTO public.codelang (code,country) VALUES
('fo-FO','Faroese (Faroe Islands)')
,('fr','French')
,('fr-BE','French (Belgium)')
,('fr-CA','French (Canada)')
,('fr-CH','French (Switzerland)')
,('fr-FR','French (France)')
,('fr-LU','French (Luxembourg)')
,('fr-MC','French (Principality of Monaco)')
,('gl','Galician')
,('gl-ES','Galician (Spain)')
;
INSERT INTO public.codelang (code,country) VALUES
('gu','Gujarati')
,('gu-IN','Gujarati (India)')
,('he','Hebrew')
,('he-IL','Hebrew (Israel)')
,('hi','Hindi')
,('hi-IN','Hindi (India)')
,('hr','Croatian')
,('hr-BA','Croatian (Bosnia and Herzegovina)')
,('hr-HR','Croatian (Croatia)')
,('hu','Hungarian')
;
INSERT INTO public.codelang (code,country) VALUES
('hu-HU','Hungarian (Hungary)')
,('hy','Armenian')
,('hy-AM','Armenian (Armenia)')
,('id','Indonesian')
,('id-ID','Indonesian (Indonesia)')
,('is','Icelandic')
,('is-IS','Icelandic (Iceland)')
,('it','Italian')
,('it-CH','Italian (Switzerland)')
,('it-IT','Italian (Italy)')
;
INSERT INTO public.codelang (code,country) VALUES
('ja','Japanese')
,('ja-JP','Japanese (Japan)')
,('ka','Georgian')
,('ka-GE','Georgian (Georgia)')
,('kk','Kazakh')
,('kk-KZ','Kazakh (Kazakhstan)')
,('kn','Kannada')
,('kn-IN','Kannada (India)')
,('ko','Korean')
,('ko-KR','Korean (Korea)')
;
INSERT INTO public.codelang (code,country) VALUES
('kok','Konkani')
,('kok-IN','Konkani (India)')
,('ky','Kyrgyz')
,('ky-KG','Kyrgyz (Kyrgyzstan)')
,('lt','Lithuanian')
,('lt-LT','Lithuanian (Lithuania)')
,('lv','Latvian')
,('lv-LV','Latvian (Latvia)')
,('mi','Maori')
,('mi-NZ','Maori (New Zealand)')
;
INSERT INTO public.codelang (code,country) VALUES
('mk','FYRO Macedonian')
,('mk-MK','FYRO Macedonian (Former Yugoslav Republic of Macedonia)')
,('mn','Mongolian')
,('mn-MN','Mongolian (Mongolia)')
,('mr','Marathi')
,('mr-IN','Marathi (India)')
,('ms','Malay')
,('ms-BN','Malay (Brunei Darussalam)')
,('ms-MY','Malay (Malaysia)')
,('mt','Maltese')
;
INSERT INTO public.codelang (code,country) VALUES
('mt-MT','Maltese (Malta)')
,('nb','Norwegian (Bokm?l)')
,('nb-NO','Norwegian (Bokm?l) (Norway)')
,('nl','Dutch')
,('nl-BE','Dutch (Belgium)')
,('nl-NL','Dutch (Netherlands)')
,('nn-NO','Norwegian (Nynorsk) (Norway)')
,('ns','Northern Sotho')
,('ns-ZA','Northern Sotho (South Africa)')
,('pa','Punjabi')
;
INSERT INTO public.codelang (code,country) VALUES
('pa-IN','Punjabi (India)')
,('pl','Polish')
,('pl-PL','Polish (Poland)')
,('ps','Pashto')
,('ps-AR','Pashto (Afghanistan)')
,('pt','Portuguese')
,('pt-BR','Portuguese (Brazil)')
,('pt-PT','Portuguese (Portugal)')
,('qu','Quechua')
,('qu-BO','Quechua (Bolivia)')
;
INSERT INTO public.codelang (code,country) VALUES
('qu-EC','Quechua (Ecuador)')
,('qu-PE','Quechua (Peru)')
,('ro','Romanian')
,('ro-RO','Romanian (Romania)')
,('ru','Russian')
,('ru-RU','Russian (Russia)')
,('sa','Sanskrit')
,('sa-IN','Sanskrit (India)')
,('se','Sami (Northern)')
,('se-FI','Sami (Northern) (Finland)')
;
INSERT INTO public.codelang (code,country) VALUES
('se-FI','Sami (Skolt) (Finland)')
,('se-FI','Sami (Inari) (Finland)')
,('se-NO','Sami (Northern) (Norway)')
,('se-NO','Sami (Lule) (Norway)')
,('se-NO','Sami (Southern) (Norway)')
,('se-SE','Sami (Northern) (Sweden)')
,('se-SE','Sami (Lule) (Sweden)')
,('se-SE','Sami (Southern) (Sweden)')
,('sk','Slovak')
,('sk-SK','Slovak (Slovakia)')
;
INSERT INTO public.codelang (code,country) VALUES
('sl','Slovenian')
,('sl-SI','Slovenian (Slovenia)')
,('sq','Albanian')
,('sq-AL','Albanian (Albania)')
,('sr-BA','Serbian (Latin) (Bosnia and Herzegovina)')
,('sr-BA','Serbian (Cyrillic) (Bosnia and Herzegovina)')
,('sr-SP','Serbian (Latin) (Serbia and Montenegro)')
,('sr-SP','Serbian (Cyrillic) (Serbia and Montenegro)')
,('sv','Swedish')
,('sv-FI','Swedish (Finland)')
;
INSERT INTO public.codelang (code,country) VALUES
('sv-SE','Swedish (Sweden)')
,('sw','Swahili')
,('sw-KE','Swahili (Kenya)')
,('syr','Syriac')
,('syr-SY','Syriac (Syria)')
,('ta','Tamil')
,('ta-IN','Tamil (India)')
,('te','Telugu')
,('te-IN','Telugu (India)')
,('th','Thai')
;
INSERT INTO public.codelang (code,country) VALUES
('th-TH','Thai (Thailand)')
,('tl','Tagalog')
,('tl-PH','Tagalog (Philippines)')
,('tn','Tswana')
,('tn-ZA','Tswana (South Africa)')
,('tr','Turkish')
,('tr-TR','Turkish (Turkey)')
,('tt','Tatar')
,('tt-RU','Tatar (Russia)')
,('ts','Tsonga')
;
INSERT INTO public.codelang (code,country) VALUES
('uk','Ukrainian')
,('uk-UA','Ukrainian (Ukraine)')
,('ur','Urdu')
,('ur-PK','Urdu (Islamic Republic of Pakistan)')
,('uz','Uzbek (Latin)')
,('uz-UZ','Uzbek (Latin) (Uzbekistan)')
,('uz-UZ','Uzbek (Cyrillic) (Uzbekistan)')
,('vi','Vietnamese')
,('vi-VN','Vietnamese (Viet Nam)')
,('xh','Xhosa')
;
INSERT INTO public.codelang (code,country) VALUES
('xh-ZA','Xhosa (South Africa)')
,('zh','Chinese')
,('zh-CN','Chinese (S)')
,('zh-HK','Chinese (Hong Kong)')
,('zh-MO','Chinese (Macau)')
,('zh-SG','Chinese (Singapore)')
,('zh-TW','Chinese (T)')
,('zu','Zulu')
,('zu-ZA','Zulu (South Africa)')
;
/***************************/
-- Manual migrate
CREATE TABLE public.country_code (
code varchar(100) NULL,
country varchar(10000) NULL
);
insert into country_code(code, country)
select distinct
t.code,
coalesce(
case when length(t.country_name2) = 1 then null else t.country_name2 end,
case when length(t.contry_name1) = 1 then null else t.contry_name1 end,
t.country
) as country
from
(
select trim(c.code) as code,
substring(trim(c.country) from '\((.+)\)') as contry_name1,
substring(
substring(trim(c.country) from '\((.+)\)')
from '\((.*)$') as country_name2,
trim(c.country) as country
from codelang as c
) t;
commit;
delete from location_country_languages as lcl
where lcl.country_id in
(
select
lc.id
from
(
select
lpad((row_number() over (order by t.country asc))::text, 3, '0') as code,
jsonb_build_object('en-GB', t.country) as "name"
from
(
select
distinct c.country
from country_code c
) t
) d
join location_country lc on lc.code = d.code and d."name"=lc."name"
)
;
commit;
delete from location_country as lcl
where lcl.id in
(
select
lc.id
from
(
select
lpad((row_number() over (order by t.country asc))::text, 3, '0') as code,
jsonb_build_object('en-GB', t.country) as "name"
from
(
select
distinct c.country
from country_code c
) t
) d
join location_country lc on lc.code = d.code and d."name"=lc."name"
)
;
commit;
delete from translation_language tl
where tl.id in
(
SELECT tl.id
FROM
(
select
distinct c.country, c.code
from country_code c
) t
JOIN translation_language tl ON tl.locale = t.code and tl.title = t.country
);
commit;
drop table country_code;
drop table codelang;
commit;

View File

@ -6,6 +6,7 @@ from django.db.transaction import on_commit
from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _
from utils.models import ProjectBaseMixin, SVGImageMixin, TranslatedFieldsMixin, TJSONField
from translation.models import Language
class Country(TranslatedFieldsMixin, SVGImageMixin, ProjectBaseMixin):
@ -18,6 +19,7 @@ class Country(TranslatedFieldsMixin, SVGImageMixin, ProjectBaseMixin):
code = models.CharField(max_length=255, unique=True, verbose_name=_('Code'))
low_price = models.IntegerField(default=25, verbose_name=_('Low price'))
high_price = models.IntegerField(default=50, verbose_name=_('High price'))
languages = models.ManyToManyField(Language, verbose_name=_('Languages'))
class Meta:
"""Meta class."""

View File

@ -7,5 +7,7 @@ urlpatterns = [
namespace='gallery')),
path('establishments/', include('establishment.urls.back')),
path('location/', include('location.urls.back')),
path('news/', include('news.urls.back'))
path('news/', include('news.urls.back')),
path('account/', include('account.urls.back')),
path('comment/', include('comment.urls.back')),
]