gealogiuya
Some checks failed
Deploy Django Application to Server / deploy (push) Failing after 19s
Telegram Notifications / Telegram Gate (push) Failing after 5s

This commit is contained in:
2026-02-27 14:56:23 +05:00
commit 0229a0595c
118 changed files with 33948 additions and 0 deletions

0
apps/geology/__init__.py Normal file
View File

View File

@@ -0,0 +1,4 @@
from .category import * # noqa
from .gallery import * # noqa
from .geology import * # noqa
from .photo import * # noqa

View File

@@ -0,0 +1,12 @@
from django.contrib import admin
from unfold.admin import ModelAdmin # noqa
from apps.geology.models import Category
@admin.register(Category)
class CategoryAdmin(ModelAdmin):
list_display = ("name", "created_at", "updated_at")
search_fields = ("name",)
list_filter = ("created_at", "updated_at")
readonly_fields = ("created_at", "updated_at")

View File

@@ -0,0 +1,21 @@
from django.contrib import admin
from unfold.admin import ModelAdmin
from apps.geology.models import GalleryCategory, Gallery
@admin.register(GalleryCategory)
class GalleryCategoryAdmin(ModelAdmin):
list_display = ("id", "name", "created_at", "updated_at")
search_fields = ("name",)
filter_horizontal = ("gallery",)
list_filter = ("created_at", "updated_at")
exclude = ("count",)
@admin.register(Gallery)
class GalleryAdmin(ModelAdmin):
list_display = ("id", "name", "created_at", "updated_at")
search_fields = ("name",)
list_filter = ("created_at", "updated_at")
exclude = ("type", "created_at", "updated_at", "name", "size")

View File

@@ -0,0 +1,48 @@
from django.contrib import admin
from unfold.admin import ModelAdmin # noqa
from apps.geology.models import Geology
@admin.register(Geology)
class GeologyAdmin(ModelAdmin):
list_display = ("name", "category", "created_at", "updated_at")
search_fields = ("name", "title", "body1", "body2", "body3")
list_filter = ("category", "created_at", "updated_at")
filter_horizontal = ("photos1", "photos2")
readonly_fields = ("created_at", "updated_at")
autocomplete_fields = ("category",)
fieldsets = (
(
"Asosiy ma'lumotlar",
{
"fields": (
"category",
"banner_title",
"banner",
"name",
"title",
"body1",
"address",
"image",
"location",
"composition",
"isp",
"analysis",
"body2",
"photos1",
"body3",
"photos2",
)
},
),
(
"Qo'shimcha ma'lumotlar",
{
"fields": (
"created_at",
"updated_at",
)
},
),
)

View File

@@ -0,0 +1,12 @@
from django.contrib import admin
from unfold.admin import ModelAdmin # noqa
from apps.geology.models import Photo
@admin.register(Photo)
class PhotoAdmin(ModelAdmin):
list_display = ("name", "description", "type", "size", "image", "created_at")
search_fields = ("name", "description", "type", "size", "image")
list_filter = ("type",)
exclude = ("created_at", "updated_at", "type", "size", "name")

9
apps/geology/apps.py Normal file
View File

@@ -0,0 +1,9 @@
from django.apps import AppConfig
class GeologyConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "apps.geology"
def ready(self):
import apps.geology.signals # noqa

View File

@@ -0,0 +1,143 @@
# Generated by Django 5.0.8 on 2024-10-22 12:10
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name="Category",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
("name", models.CharField(max_length=255, verbose_name="Nomi")),
],
options={
"verbose_name": "Kategoriya",
"verbose_name_plural": "Kategoriyalar",
},
),
migrations.CreateModel(
name="Photo",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"name",
models.CharField(
blank=True, max_length=255, null=True, verbose_name="Nomi"
),
),
(
"description",
models.TextField(blank=True, null=True, verbose_name="Tavsif"),
),
("image", models.FileField(upload_to="media/", verbose_name="Fayl")),
(
"type",
models.CharField(
blank=True, max_length=255, null=True, verbose_name="Fayl turi"
),
),
(
"size",
models.BigIntegerField(
blank=True, default=0, null=True, verbose_name="Hajmi"
),
),
],
options={
"verbose_name": "Foto",
"verbose_name_plural": "Fotolar",
},
),
migrations.CreateModel(
name="Geology",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
("name", models.CharField(max_length=255, verbose_name="Nomi")),
("title", models.CharField(max_length=255, verbose_name="Sarlavha")),
("body1", models.TextField(verbose_name="Tavsif1")),
("body2", models.TextField(verbose_name="Tavsif2")),
("body3", models.TextField(verbose_name="Tavsif3")),
(
"banner",
models.ImageField(
blank=True,
null=True,
upload_to="banners/",
verbose_name="Banner",
),
),
("address", models.CharField(max_length=255, verbose_name="Manzil")),
("longitude", models.FloatField(verbose_name="Boylam")),
("latitude", models.FloatField(verbose_name="Kenglik")),
("composition", models.TextField(verbose_name="Tarkib")),
("isp", models.TextField(verbose_name="ISP")),
("analysis", models.TextField(verbose_name="Analiz")),
(
"category",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="cultures",
to="geology.category",
verbose_name="Kategoriya",
),
),
(
"photos1",
models.ManyToManyField(
related_name="geology_photos1",
to="geology.photo",
verbose_name="Fotolavhalar",
),
),
(
"photos2",
models.ManyToManyField(
related_name="geology_photos2",
to="geology.photo",
verbose_name="Fotolavhalar",
),
),
],
options={
"verbose_name": "Madan",
"verbose_name_plural": "Madanlar",
},
),
]

View File

@@ -0,0 +1,42 @@
# Generated by Django 5.0.8 on 2024-10-26 07:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("geology", "0001_initial"),
]
operations = [
migrations.AlterModelOptions(
name="category",
options={
"ordering": ["-created_at"],
"verbose_name": "Kategoriya",
"verbose_name_plural": "Kategoriyalar",
},
),
migrations.AlterModelOptions(
name="geology",
options={
"ordering": ["-created_at"],
"verbose_name": "Madan",
"verbose_name_plural": "Madanlar",
},
),
migrations.AlterModelOptions(
name="photo",
options={
"ordering": ["-created_at"],
"verbose_name": "Foto",
"verbose_name_plural": "Fotolar",
},
),
migrations.AlterField(
model_name="photo",
name="image",
field=models.ImageField(upload_to="media/", verbose_name="Fayl"),
),
]

View File

@@ -0,0 +1,20 @@
# Generated by Django 5.0.8 on 2024-10-26 07:49
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("geology", "0002_alter_category_options_alter_geology_options_and_more"),
]
operations = [
migrations.AddField(
model_name="geology",
name="banner_title",
field=models.CharField(
blank=True, max_length=255, null=True, verbose_name="Banner sarlavhasi"
),
),
]

View File

@@ -0,0 +1,87 @@
# Generated by Django 5.0.8 on 2024-10-26 10:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("geology", "0003_geology_banner_title"),
]
operations = [
migrations.CreateModel(
name="Gallery",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"name",
models.CharField(
blank=True, max_length=255, null=True, verbose_name="Nomi"
),
),
(
"description",
models.TextField(blank=True, null=True, verbose_name="Tavsif"),
),
("image", models.ImageField(upload_to="media/", verbose_name="Fayl")),
(
"type",
models.CharField(
blank=True, max_length=255, null=True, verbose_name="Fayl turi"
),
),
(
"size",
models.BigIntegerField(
blank=True, default=0, null=True, verbose_name="Hajmi"
),
),
],
options={
"verbose_name": "Galereya",
"verbose_name_plural": "Galereya",
"ordering": ["-created_at"],
},
),
migrations.CreateModel(
name="GalleryCategory",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
("name", models.CharField(max_length=255, verbose_name="Nomi")),
(
"gallery",
models.ManyToManyField(
related_name="gallery_category",
to="geology.gallery",
verbose_name="Galereya",
),
),
],
options={
"verbose_name": "Galereya kategoriya",
"verbose_name_plural": "Galereya kategoriyalar",
"ordering": ["-created_at"],
},
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.0.8 on 2024-10-26 10:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("geology", "0004_gallery_gallerycategory"),
]
operations = [
migrations.AddField(
model_name="gallerycategory",
name="count",
field=models.BigIntegerField(default=0, verbose_name="Soni"),
),
]

View File

@@ -0,0 +1,94 @@
# Generated by Django 5.0.8 on 2024-11-02 04:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("geology", "0005_gallerycategory_count"),
]
operations = [
migrations.AlterField(
model_name="geology",
name="address",
field=models.CharField(max_length=255, verbose_name="Олинган жойи"),
),
migrations.AlterField(
model_name="geology",
name="analysis",
field=models.TextField(
verbose_name="Тоғ жинсининг спектрал тахлил натижаси (%)"
),
),
migrations.AlterField(
model_name="geology",
name="body1",
field=models.TextField(verbose_name="Tavsif"),
),
migrations.AlterField(
model_name="geology",
name="body2",
field=models.TextField(
verbose_name="Тоғ жинсининг шаффоф шакилда кўриниши"
),
),
migrations.AlterField(
model_name="geology",
name="body3",
field=models.TextField(verbose_name="Тоғ жинсининг аншлифда кўриниши"),
),
migrations.AlterField(
model_name="geology",
name="composition",
field=models.TextField(verbose_name="Тог жинсининг кимёвий таркиби (%)"),
),
migrations.AlterField(
model_name="geology",
name="isp",
field=models.TextField(
verbose_name="Тоғ жинсининг ISP - масс-спектрометрик"
),
),
migrations.AlterField(
model_name="geology",
name="latitude",
field=models.FloatField(verbose_name="Kenglik (Координаталари)"),
),
migrations.AlterField(
model_name="geology",
name="longitude",
field=models.FloatField(verbose_name="Boylam (Координаталари)"),
),
migrations.AlterField(
model_name="geology",
name="name",
field=models.CharField(
max_length=255, verbose_name="Nomi (Пироксенли скарн)"
),
),
migrations.AlterField(
model_name="geology",
name="photos1",
field=models.ManyToManyField(
related_name="geology_photos1",
to="geology.photo",
verbose_name="Барча кўрнишлар",
),
),
migrations.AlterField(
model_name="geology",
name="photos2",
field=models.ManyToManyField(
related_name="geology_photos2",
to="geology.photo",
verbose_name="Барча кўрнишлар",
),
),
migrations.AlterField(
model_name="geology",
name="title",
field=models.CharField(max_length=255, verbose_name="Sarlavha (Dr-1)"),
),
]

View File

@@ -0,0 +1,21 @@
# Generated by Django 5.0.8 on 2024-11-02 04:51
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("geology", "0006_alter_geology_address_alter_geology_analysis_and_more"),
]
operations = [
migrations.AlterModelOptions(
name="photo",
options={
"ordering": ["-created_at"],
"verbose_name": "Барча кўрнишлар",
"verbose_name_plural": "Барча кўрнишлар",
},
),
]

View File

@@ -0,0 +1,23 @@
# Generated by Django 5.0.8 on 2024-11-02 05:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("geology", "0007_alter_photo_options"),
]
operations = [
migrations.AddField(
model_name="geology",
name="image",
field=models.ImageField(
blank=True,
null=True,
upload_to="images/",
verbose_name="Олинган жойи сурати",
),
),
]

View File

@@ -0,0 +1,95 @@
# Generated by Django 5.0.8 on 2024-11-06 12:18
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("geology", "0008_geology_image"),
]
operations = [
migrations.RemoveField(
model_name="geology",
name="latitude",
),
migrations.RemoveField(
model_name="geology",
name="longitude",
),
migrations.AddField(
model_name="geology",
name="location",
field=models.CharField(
blank=True, max_length=255, null=True, verbose_name="Кординаталар"
),
),
migrations.AlterField(
model_name="geology",
name="address",
field=models.CharField(
blank=True, max_length=255, null=True, verbose_name="Олинган жойи"
),
),
migrations.AlterField(
model_name="geology",
name="analysis",
field=models.TextField(
blank=True,
null=True,
verbose_name="Тоғ жинсининг спектрал тахлил натижаси (%)",
),
),
migrations.AlterField(
model_name="geology",
name="body1",
field=models.TextField(
blank=True, null=True, verbose_name="Тог жинсининг макроскопик таснифи"
),
),
migrations.AlterField(
model_name="geology",
name="body2",
field=models.TextField(
blank=True,
null=True,
verbose_name="Тоғ жинсининг шаффоф шлифда кўриниши",
),
),
migrations.AlterField(
model_name="geology",
name="body3",
field=models.TextField(
blank=True, null=True, verbose_name="Тоғ жинсининг аншлифда кўриниши"
),
),
migrations.AlterField(
model_name="geology",
name="composition",
field=models.TextField(
blank=True, null=True, verbose_name="Тог жинсининг кимёвий таркиби (%)"
),
),
migrations.AlterField(
model_name="geology",
name="isp",
field=models.TextField(
blank=True,
null=True,
verbose_name="Тоғ жинсининг ISP - масс-спектрометрик тахлил натижаси (г/т)",
),
),
migrations.AlterField(
model_name="geology",
name="name",
field=models.CharField(max_length=255, verbose_name="Тог жинси номи"),
),
migrations.AlterField(
model_name="geology",
name="title",
field=models.CharField(
max_length=255, verbose_name="Тог жинсининг геологик раками"
),
),
]

View File

@@ -0,0 +1,33 @@
# Generated by Django 5.0.8 on 2024-11-20 07:05
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("geology", "0009_remove_geology_latitude_remove_geology_longitude_and_more"),
]
operations = [
migrations.AlterField(
model_name="geology",
name="photos1",
field=models.ManyToManyField(
blank=True,
related_name="geology_photos1",
to="geology.photo",
verbose_name="Барча кўрнишлар",
),
),
migrations.AlterField(
model_name="geology",
name="photos2",
field=models.ManyToManyField(
blank=True,
related_name="geology_photos2",
to="geology.photo",
verbose_name="Барча кўрнишлар",
),
),
]

View File

View File

@@ -0,0 +1,4 @@
from .category import * # noqa
from .gallery import * # noqa
from .geology import * # noqa
from .photo import * # noqa

View File

@@ -0,0 +1,16 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from apps.shared.models import AbstractBaseModel
class Category(AbstractBaseModel):
name = models.CharField(max_length=255, verbose_name=_("Nomi"))
class Meta:
verbose_name = _("Kategoriya")
verbose_name_plural = _("Kategoriyalar")
ordering = ["-created_at"]
def __str__(self) -> str:
return self.name

View File

@@ -0,0 +1,20 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from apps.shared.models import AbstractBaseModel
class GalleryCategory(AbstractBaseModel):
name = models.CharField(max_length=255, verbose_name=_("Nomi"))
count = models.BigIntegerField(default=0, verbose_name=_("Soni"))
gallery = models.ManyToManyField(
"Gallery", related_name="gallery_category", verbose_name=_("Galereya")
)
class Meta:
verbose_name = _("Galereya kategoriya")
verbose_name_plural = _("Galereya kategoriyalar")
ordering = ["-created_at"]
def __str__(self) -> str:
return self.name

View File

@@ -0,0 +1,47 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from apps.shared.models import AbstractBaseModel
class Geology(AbstractBaseModel):
category = models.ForeignKey(
"Category",
on_delete=models.CASCADE,
related_name="cultures",
verbose_name=_("Kategoriya"),
)
banner_title = models.CharField(
max_length=255, verbose_name=_("Banner sarlavhasi"), null=True, blank=True
)
banner = models.ImageField(
upload_to="banners/", verbose_name=_("Banner"), null=True, blank=True
)
name = models.CharField(max_length=255, verbose_name=_("Тог жинси номи"))
title = models.CharField(max_length=255, verbose_name=_("Тог жинсининг геологик раками"))
body1 = models.TextField(verbose_name=_("Тог жинсининг макроскопик таснифи"), null=True, blank=True)
address = models.CharField(max_length=255, verbose_name=_("Олинган жойи"), null=True, blank=True)
image = models.ImageField(upload_to="images/", verbose_name=_("Олинган жойи сурати"), null=True, blank=True)
location = models.CharField(max_length=255, verbose_name=_("Кординаталар"), null=True, blank=True)
composition = models.TextField(verbose_name=_("Тог жинсининг кимёвий таркиби (%)"), null=True, blank=True)
isp = models.TextField(verbose_name=_("Тоғ жинсининг ISP - масс-спектрометрик тахлил натижаси (г/т)"), null=True,
blank=True)
analysis = models.TextField(
verbose_name=_("Тоғ жинсининг спектрал тахлил натижаси (%)"), null=True, blank=True
)
body2 = models.TextField(verbose_name=_("Тоғ жинсининг шаффоф шлифда кўриниши"), null=True, blank=True)
photos1 = models.ManyToManyField(
"Photo", verbose_name=_("Барча кўрнишлар"), related_name="geology_photos1", blank=True
)
body3 = models.TextField(verbose_name=_("Тоғ жинсининг аншлифда кўриниши"), null=True, blank=True)
photos2 = models.ManyToManyField(
"Photo", verbose_name=_("Барча кўрнишлар"), related_name="geology_photos2", blank=True
)
class Meta:
verbose_name = _("Madan")
verbose_name_plural = _("Madanlar")
ordering = ["-created_at"]
def __str__(self) -> str:
return self.name

View File

@@ -0,0 +1,66 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from apps.shared.models import AbstractBaseModel
class Photo(AbstractBaseModel):
name = models.CharField(
max_length=255, blank=True, null=True, verbose_name=_("Nomi")
)
description = models.TextField(blank=True, null=True, verbose_name=_("Tavsif"))
image = models.ImageField(upload_to="media/", verbose_name=_("Fayl"))
type = models.CharField(
max_length=255, blank=True, null=True, verbose_name=_("Fayl turi")
)
size = models.BigIntegerField(
blank=True, null=True, default=0, verbose_name=_("Hajmi")
)
def save(self, *args, **kwargs):
self.type = self.image.name.split(".")[-1]
self.size = self.image.size
if self.name is None:
self.name = (
self.image.name if self.image.name is not None else f"Media {self.id}"
)
super().save(*args, **kwargs)
class Meta:
verbose_name = _("Барча кўрнишлар")
verbose_name_plural = _("Барча кўрнишлар")
ordering = ["-created_at"]
def __str__(self) -> str:
return str(self.description) if str(self.description) else f"Photo {self.id}"
class Gallery(AbstractBaseModel):
name = models.CharField(
max_length=255, blank=True, null=True, verbose_name=_("Nomi")
)
description = models.TextField(blank=True, null=True, verbose_name=_("Tavsif"))
image = models.ImageField(upload_to="media/", verbose_name=_("Fayl"))
type = models.CharField(
max_length=255, blank=True, null=True, verbose_name=_("Fayl turi")
)
size = models.BigIntegerField(
blank=True, null=True, default=0, verbose_name=_("Hajmi")
)
def save(self, *args, **kwargs):
self.type = self.image.name.split(".")[-1]
self.size = self.image.size
if self.name is None:
self.name = (
self.image.name if self.image.name is not None else f"Media {self.id}"
)
super().save(*args, **kwargs)
class Meta:
verbose_name = _("Galereya")
verbose_name_plural = _("Galereya")
ordering = ["-created_at"]
def __str__(self) -> str:
return str(self.description) if str(self.description) else f"Gallery {self.id}"

View File

@@ -0,0 +1,4 @@
from .category import * # noqa
from .gallery import * # noqa
from .geology import * # noqa
from .photo import * # noqa

View File

@@ -0,0 +1,16 @@
from typing import Type
from rest_framework import serializers
from apps.geology.models import Category, Geology
class CategorySerializer(serializers.ModelSerializer):
count = serializers.SerializerMethodField()
class Meta:
model: Type[Category] = Category
fields: str = ("id", "count", "name", "created_at", "updated_at")
def get_count(self, obj):
return Geology.objects.filter(category=obj).count()

View File

@@ -0,0 +1,17 @@
from rest_framework import serializers
from apps.geology.models import Gallery, GalleryCategory
class GallerySerializer(serializers.ModelSerializer):
class Meta:
model = Gallery
fields = "__all__"
class GalleryCategorySerializer(serializers.ModelSerializer):
gallery = GallerySerializer(many=True, read_only=True)
class Meta:
model = GalleryCategory
fields = ("id", "name", "count", "gallery", "created_at", "updated_at")

View File

@@ -0,0 +1,161 @@
import logging
from urllib.parse import urlparse
from drf_spectacular.utils import extend_schema_field
from rest_framework import exceptions, status
from rest_framework import serializers
from rest_framework.response import Response
from apps.geology.models import Geology, Photo
class GeologySerializer(serializers.ModelSerializer):
class Meta:
model = Geology
fields = (
"id",
"name",
"title",
"body1",
"body2",
"body3",
"banner_title",
"banner",
"address",
"image",
"location",
"composition",
"isp",
"analysis",
"category",
"created_at",
"updated_at",
)
def create(self, validated_data):
try:
request = self.context.get("request")
photo_data1 = []
photo_data2 = []
for key in request.data:
if key.startswith("description1[") and key.endswith("]"):
index = key[len("description1[") : -1]
file_key = f"image1[{index}]"
photo_desc = request.data.get(key)
photo_file = request.FILES.get(file_key)
if not photo_file:
return Response(
{
"error": f"File is required for photo item {index} in photos1"
},
status=status.HTTP_400_BAD_REQUEST,
)
if not photo_desc:
photo_desc = photo_file.name
photo_data1.append({"image": photo_file, "description": photo_desc})
if key.startswith("description2[") and key.endswith("]"):
index = key[len("description2[") : -1]
file_key = f"image2[{index}]"
photo_desc = request.data.get(key)
photo_file = request.FILES.get(file_key)
if not photo_file:
return Response(
{
"error": f"File is required for photo item {index} in photos2"
},
status=status.HTTP_400_BAD_REQUEST,
)
if not photo_desc:
photo_desc = photo_file.name
photo_data2.append({"image": photo_file, "description": photo_desc})
geology = Geology.objects.create(
name=validated_data.get("name"),
title=validated_data.get("title"),
body1=validated_data.get("body1"),
body2=validated_data.get("body2"),
body3=validated_data.get("body3"),
banner_title=validated_data.get("banner_title"),
banner=validated_data.get("banner"),
address=validated_data.get("address"),
location=validated_data.get("location"),
composition=validated_data.get("composition"),
isp=validated_data.get("isp"),
analysis=validated_data.get("analysis"),
category=validated_data.get("category"),
)
for photo in photo_data1:
photo_instance = Photo.objects.create(
image=photo["image"], description=photo["description"]
)
geology.photos1.add(photo_instance)
for photo in photo_data2:
photo_instance = Photo.objects.create(
image=photo["image"], description=photo["description"]
)
geology.photos2.add(photo_instance)
return geology
except Exception as e:
logging.error(f"Error in create method: {str(e)}")
raise exceptions.ValidationError({"detail": str(e)})
class GeologyDetailSerializer(serializers.ModelSerializer):
category = serializers.SerializerMethodField()
photos1 = serializers.SerializerMethodField()
photos2 = serializers.SerializerMethodField()
class Meta:
model = Geology
fields = (
"id",
"category",
"banner_title",
"banner",
"name",
"title",
"body1",
"address",
"image",
"location",
"composition",
"isp",
"analysis",
"body2",
"photos1",
"body3",
"photos2",
"created_at",
"updated_at",
)
def to_representation(self, instance):
representation = super().to_representation(instance)
if representation.get("banner"):
parsed_url = urlparse(representation["banner"])
representation["banner"] = parsed_url.path
return representation
@extend_schema_field(serializers.DictField())
def get_category(self, obj):
from apps.geology.serializers.category import CategorySerializer
return CategorySerializer(obj.category).data
@extend_schema_field(serializers.ListField(child=serializers.DictField()))
def get_photos1(self, obj):
from apps.geology.serializers.photo import PhotoSerializer
return PhotoSerializer(obj.photos1.all(), many=True).data
@extend_schema_field(serializers.ListField(child=serializers.DictField()))
def get_photos2(self, obj):
from apps.geology.serializers.photo import PhotoSerializer
return PhotoSerializer(obj.photos2.all(), many=True).data

View File

@@ -0,0 +1,11 @@
from typing import Type
from rest_framework import serializers
from apps.geology.models import Photo
class PhotoSerializer(serializers.ModelSerializer):
class Meta:
model: Type[Photo] = Photo
fields: str = "__all__"

View File

@@ -0,0 +1 @@
from .gallery import * # noqa

View File

@@ -0,0 +1,12 @@
from django.db.models.signals import m2m_changed
from django.dispatch import receiver
from apps.geology.models import GalleryCategory
@receiver(m2m_changed, sender=GalleryCategory.gallery.through)
def gallery_category_m2m_changed(sender, instance, action, **kwargs):
if action in ["post_add", "post_remove", "post_clear"]:
instance.count = instance.gallery.count()
print(instance.count)
instance.save()

View File

12
apps/geology/urls.py Normal file
View File

@@ -0,0 +1,12 @@
from typing import List
from django.urls import path
from django.urls.resolvers import URLPattern
from apps.geology.views import GeologyView, CategoryView, GalleryCategoryView
urlpatterns: List[URLPattern] = [
path("geology/", GeologyView.as_view(), name="geology"),
path("category/", CategoryView.as_view(), name="category"),
path("gallery/", GalleryCategoryView.as_view(), name="gallery"),
]

View File

@@ -0,0 +1,3 @@
from .category import * # noqa
from .gallery import * # noqa
from .geology import * # noqa

View File

@@ -0,0 +1,24 @@
from typing import Type
from django.db.models import QuerySet
from rest_framework.generics import GenericAPIView
from rest_framework.permissions import AllowAny
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import Serializer
from apps.geology.models import Category
from apps.geology.serializers import CategorySerializer
class CategoryView(GenericAPIView):
permission_classes = [AllowAny]
serializer_class: Type[Serializer] = CategorySerializer
def get_queryset(self) -> QuerySet[Category]:
return Category.objects.all()
def get(self, request: Request) -> Response:
categories = self.get_queryset()
serializer = self.serializer_class(categories, many=True)
return Response(serializer.data)

View File

@@ -0,0 +1,24 @@
from typing import Type
from django.db.models import QuerySet
from rest_framework.generics import GenericAPIView
from rest_framework.permissions import AllowAny
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import Serializer
from apps.geology.models import GalleryCategory
from apps.geology.serializers import GalleryCategorySerializer
class GalleryCategoryView(GenericAPIView):
permission_classes = [AllowAny]
serializer_class: Type[Serializer] = GalleryCategorySerializer
def get_queryset(self) -> QuerySet[GalleryCategory]:
return GalleryCategory.objects.all()
def get(self, request: Request) -> Response:
categories = self.get_queryset()
serializer = self.serializer_class(categories, many=True)
return Response(serializer.data)

View File

@@ -0,0 +1,45 @@
from typing import Type
from django.db.models import QuerySet
from rest_framework import status
from rest_framework.generics import GenericAPIView
from rest_framework.permissions import AllowAny
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import Serializer
from apps.geology.models import Geology
from apps.geology.serializers import GeologySerializer, GeologyDetailSerializer
class GeologyView(GenericAPIView):
permission_classes = [AllowAny]
def get_serializer_class(self) -> Type[Serializer]:
if self.request.method == "POST":
return GeologySerializer
return GeologyDetailSerializer
def get_queryset(self) -> QuerySet[Geology]:
return Geology.objects.all().select_related()
def get(self, request: Request) -> Response:
geology_id = request.query_params.get("id")
category_id = request.query_params.get("category")
if geology_id:
geologies = Geology.objects.filter(id=geology_id)
elif category_id:
geologies = Geology.objects.filter(category_id=category_id)
else:
geologies = self.get_queryset()
serializer = self.get_serializer(geologies, many=True)
return Response(serializer.data)
def post(self, request: Request) -> Response:
serializer = self.get_serializer(
data=request.data, context={"request": request}
)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)