This commit is contained in:
xoliqberdiyev
2026-04-18 16:48:32 +05:00
parent 965328edd4
commit 182b2483bf
9 changed files with 23124 additions and 22 deletions

View File

@@ -0,0 +1,144 @@
import json
import os
from django.core.management.base import BaseCommand
from django.db import transaction
from core.apps.shared.models import RegionModel, DistrictModel, VillageModel
class Command(BaseCommand):
help = "Import regions, districts, and neighborhoods from JSON files."
def add_arguments(self, parser):
parser.add_argument('--path', type=str, default='JSON/', help='Path to JSON files directory')
def transliterate_uz_to_en(self, text):
"""Simple transliteration for English names"""
if not text:
return ""
mapping = {
"o'": "o", "O'": "O",
"g'": "g", "G'": "G",
"sh": "sh", "Sh": "Sh",
"ch": "ch", "Ch": "Ch",
"ng": "ng", "Ng": "Ng",
"q": "q", "Q": "Q",
"yo": "yo", "Yo": "Yo",
"yu": "yu", "Yu": "Yu",
"ya": "ya", "Ya": "Ya",
"ye": "ye", "Ye": "Ye",
"o": "o", "O": "O",
"g": "g", "G": "G",
}
res = text
for k, v in mapping.items():
res = res.replace(k, v)
replacements = {
"viloyati": "Region",
"viloyat": "Region",
"tumani": "District",
"tuman": "District",
"shahri": "City",
"shahar": "City",
"Respublikasi": "Republic",
}
for k, v in replacements.items():
res = res.replace(k, v)
res = res.replace(k.capitalize(), v)
return res.strip()
def handle(self, *args, **options):
path = options['path']
regions_file = os.path.join(path, 'regions.json')
districts_file = os.path.join(path, 'districts.json')
villages_file = os.path.join(path, 'villages.json')
try:
with transaction.atomic():
# 1. Import Regions
self.stdout.write("Importing Regions...")
if os.path.exists(regions_file):
with open(regions_file, 'r', encoding='utf-8-sig') as f:
regions_data = json.load(f)
for item in regions_data:
name_uz = item.get('name_uz', '')
name_ru = item.get('name_ru', '') or name_uz
name_en = self.transliterate_uz_to_en(name_uz)
# Use get_or_create to avoid duplicates if ID matches or name matches
# Actually, it's better to use our own internal IDs if we want to link them
# But since many JSON files use these IDs, we'll store them as a reference or use them directly if we reset the DB
region, created = RegionModel.objects.update_or_create(
id=item['id'],
defaults={
'name_uz': name_uz,
'name_ru': name_ru,
'name_en': name_en,
}
)
# 2. Import Districts
self.stdout.write("Importing Districts...")
if os.path.exists(districts_file):
with open(districts_file, 'r', encoding='utf-8-sig') as f:
districts_data = json.load(f)
for item in districts_data:
name_uz = item.get('name_uz', '')
name_ru = item.get('name_ru', '') or name_uz
name_en = self.transliterate_uz_to_en(name_uz)
region_id = item.get('region_id')
if not RegionModel.objects.filter(id=region_id).exists():
self.stdout.write(self.style.WARNING(f"Region {region_id} not found for district {name_uz}"))
continue
DistrictModel.objects.update_or_create(
id=item['id'],
defaults={
'region_id': region_id,
'name_uz': name_uz,
'name_ru': name_ru,
'name_en': name_en,
}
)
# 3. Import Neighborhoods (Villages)
self.stdout.write("Importing Neighborhoods (Villages)...")
if os.path.exists(villages_file):
with open(villages_file, 'r', encoding='utf-8-sig') as f:
villages_data = json.load(f)
count = 0
total = len(villages_data)
for item in villages_data:
name_uz = item.get('name_uz', '')
name_ru = item.get('name_ru', '') or name_uz
name_en = self.transliterate_uz_to_en(name_uz)
district_id = item.get('district_id')
if not DistrictModel.objects.filter(id=district_id).exists():
continue
NeighborhoodModel.objects.update_or_create(
id=item['id'],
defaults={
'district_id': district_id,
'name_uz': name_uz,
'name_ru': name_ru,
'name_en': name_en,
}
)
count += 1
if count % 1000 == 0:
self.stdout.write(f"Processed {count}/{total} neighborhoods...")
self.stdout.write(self.style.SUCCESS("Import completed successfully!"))
except Exception as e:
self.stdout.write(self.style.ERROR(f"Error: {str(e)}"))

View File

@@ -1,28 +1,28 @@
# from django.db import models
# from django_core.models import AbstractBaseModel
from django.db import models
from django_core.models import AbstractBaseModel
# class RegionModel(AbstractBaseModel):
# name = models.CharField(max_length=255, unique=True)
class RegionModel(AbstractBaseModel):
name = models.CharField(max_length=255, unique=True)
# class Meta:
# verbose_name = "Region"
# verbose_name_plural = "Regions"
class Meta:
verbose_name = "Region"
verbose_name_plural = "Regions"
# class DistrictModel(AbstractBaseModel):
# name = models.CharField(max_length=255, unique=True)
# region = models.ForeignKey(RegionModel, on_delete=models.CASCADE, related_name='districts')
class DistrictModel(AbstractBaseModel):
name = models.CharField(max_length=255, unique=True)
region = models.ForeignKey(RegionModel, on_delete=models.CASCADE, related_name='districts')
# class Meta:
# verbose_name = "District"
# verbose_name_plural = "Districts"
class Meta:
verbose_name = "District"
verbose_name_plural = "Districts"
# class VillageModel(AbstractBaseModel):
# name = models.CharField(max_length=255, unique=True)
# district = models.ForeignKey(DistrictModel, on_delete=models.CASCADE, related_name='villages')
class VillageModel(AbstractBaseModel):
name = models.CharField(max_length=255, unique=True)
district = models.ForeignKey(DistrictModel, on_delete=models.CASCADE, related_name='villages')
# class Meta:
# verbose_name = "Village"
# verbose_name_plural = "Villages"
class Meta:
verbose_name = "Village"
verbose_name_plural = "Villages"

View File

@@ -6,15 +6,16 @@ from core.apps.shared.models import RegionModel, VillageModel, DistrictModel
class DistrictSerializer(serializers.ModelSerializer):
class Meta:
model = DistrictModel
fields = ('id', 'name', 'code', 'region')
fields = ('id', 'name')
class VillageSerializer(serializers.ModelSerializer):
class Meta:
model = VillageModel
fields = ('id', 'name', 'code', 'district')
fields = ('id', 'name')
class RegionSerializer(serializers.ModelSerializer):
class Meta:
model = RegionModel
fields = ('id', 'name', 'code')
fields = ('id', 'name')

View File

@@ -1,6 +1,7 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import SettingsView
from .views.region.region import RegionListCreateView, DistrictListCreateView, VillageListCreateView
router = DefaultRouter()
router.register("settings", SettingsView, basename="settings")
@@ -8,4 +9,7 @@ router.register("settings", SettingsView, basename="settings")
urlpatterns = [
path("", include(router.urls)),
path("region/", RegionListCreateView.as_view(), name="region-list-create"),
path("district/", DistrictListCreateView.as_view(), name="district-list-create"),
path("village/", VillageListCreateView.as_view(), name="village-list-create"),
]

View File

@@ -0,0 +1,41 @@
from rest_framework import generics
from rest_framework.permissions import IsAuthenticated
from core.apps.shared.serializers.region.district import DistrictSerializer, VillageSerializer, RegionSerializer
from core.apps.shared.models import RegionModel, VillageModel, DistrictModel
class DistrictListCreateView(generics.ListCreateAPIView):
permission_classes = [IsAuthenticated]
serializer_class = DistrictSerializer
queryset = DistrictModel.objects.all()
def get_queryset(self):
region = self.request.query_params.get('region')
name = self.request.query_params.get('name')
if name:
return self.queryset.filter(name__icontains=name)
if region:
return self.queryset.filter(region=region)
return super().get_queryset()
class VillageListCreateView(generics.ListCreateAPIView):
permission_classes = [IsAuthenticated]
serializer_class = VillageSerializer
queryset = VillageModel.objects.all()
def get_queryset(self):
district = self.request.query_params.get('district')
name = self.request.query_params.get('name')
if district:
return self.queryset.filter(district=district)
if name:
return self.queryset.filter(name__icontains=name)
return super().get_queryset()
class RegionListCreateView(generics.ListCreateAPIView):
permission_classes = [IsAuthenticated]
serializer_class = RegionSerializer
queryset = RegionModel.objects.all()

1682
resources/json/district.json Normal file

File diff suppressed because it is too large Load Diff

100
resources/json/region.json Normal file
View File

@@ -0,0 +1,100 @@
[
{
"id": 2,
"soato_id": 1703,
"name_uz": "Andijon viloyati",
"name_oz": "Андижон вилояти",
"name_ru": "Андижанская область"
},
{
"id": 3,
"soato_id": 1706,
"name_uz": "Buxoro viloyati",
"name_oz": "Бухоро вилояти",
"name_ru": "Бухарская область"
},
{
"id": 4,
"soato_id": 1708,
"name_uz": "Jizzax viloyati",
"name_oz": "Жиззах вилояти",
"name_ru": "Джизакская область"
},
{
"id": 5,
"soato_id": 1710,
"name_uz": "Qashqadaryo viloyati",
"name_oz": "Қашқадарё вилояти",
"name_ru": "Кашкадарьинская область"
},
{
"id": 6,
"soato_id": 1712,
"name_uz": "Navoiy viloyati",
"name_oz": "Навоий вилояти",
"name_ru": "Навоийская область"
},
{
"id": 7,
"soato_id": 1714,
"name_uz": "Namangan viloyati",
"name_oz": "Наманган вилояти",
"name_ru": "Наманганская область"
},
{
"id": 8,
"soato_id": 1718,
"name_uz": "Samarqand viloyati",
"name_oz": "Самарқанд вилояти",
"name_ru": "Самаркандская область"
},
{
"id": 10,
"soato_id": 1724,
"name_uz": "Sirdaryo viloyati",
"name_oz": "Сирдарё вилояти",
"name_ru": "Сырдарьинская область"
},
{
"id": 11,
"soato_id": 1726,
"name_uz": "Toshkent shahri",
"name_oz": "Тошкент шаҳри",
"name_ru": "город Ташкент"
},
{
"id": 12,
"soato_id": 1727,
"name_uz": "Toshkent viloyati",
"name_oz": "Тошкент вилояти",
"name_ru": "Ташкентская область"
},
{
"id": 13,
"soato_id": 1730,
"name_uz": "Farg'ona viloyati",
"name_oz": "Фарғона вилояти",
"name_ru": "Ферганская область"
},
{
"id": 14,
"soato_id": 1733,
"name_uz": "Xorazm viloyati",
"name_oz": "Хоразм вилояти",
"name_ru": "Хорезмская область"
},
{
"id": 15,
"soato_id": 1735,
"name_uz": "Qoraqalpog'iston Respublikasi",
"name_oz": "Қорақалпоғистон Республикаси",
"name_ru": "Республика Каракалпакстан"
},
{
"id": 5723,
"soato_id": 1722,
"name_uz": "Surxondaryo viloyati",
"name_oz": "Сурхондарё вилояти",
"name_ru": "Сурхандарьинская область"
}
]

21130
resources/json/village.json Normal file

File diff suppressed because it is too large Load Diff