gold eggs backend
Some checks failed
Build and Push to Docker Hub / build-test-push (push) Failing after 1m55s

This commit is contained in:
2026-04-15 08:59:36 +02:00
commit ab73d05ecc
359 changed files with 14415 additions and 0 deletions

6
core/http/__init__.py Executable file
View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class HttpConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "core.http"

View File

@@ -0,0 +1,3 @@
from .core import * # noqa
from .another import * # noqa
from .user import * # noqa

View File

@@ -0,0 +1,66 @@
from django.contrib import admin
from django.db import models as db_model
from django_select2 import forms as django_select2
from import_export import admin as import_export
from modeltranslation import admin as modeltranslation
from core.http import forms, models
class PostInline(admin.TabularInline):
model = models.Post.comments.through
fields = ["comment"]
extra = 1
class TagsInline(admin.TabularInline):
model = models.Post.tags.through
extra = 1
class PostAdmin(
modeltranslation.TabbedTranslationAdmin,
import_export.ImportExportModelAdmin,
): # noqa
fields: tuple = ("title", "desc", "image", "tags")
search_fields: list = ["title", "desc"]
list_filter = ["title"]
required_languages: tuple = ("uz",)
form = forms.PostAdminForm
inlines = [PostInline]
formfield_overrides = {
db_model.ManyToManyField: {
"widget": django_select2.Select2MultipleWidget
}
}
class TagsAdmin(import_export.ImportExportModelAdmin):
fields: tuple = ("name",)
search_fields: list = ["name"]
class FrontendInline(admin.TabularInline):
model = models.FrontendTranslation.comments.through
fields = ["comment"]
extra = 1
class FrontendTranslationAdmin(
modeltranslation.TabbedTranslationAdmin,
import_export.ImportExportModelAdmin,
): # noqa
fields: tuple = ("key", "value")
required_languages: tuple = ("uz",)
list_display = ["key", "value"]
inlines = [FrontendInline]
class SmsConfirmAdmin(admin.ModelAdmin):
list_display = ["phone", "code", "resend_count", "try_count"]
search_fields = ["phone", "code"]
class CommentAdmin(import_export.ImportExportModelAdmin):
list_display = ["text"]
search_fields = ["text"]

22
core/http/admin/core.py Normal file
View File

@@ -0,0 +1,22 @@
"""
Admin panel register
"""
from django.contrib import admin
from django.contrib.auth import models as db_models
from core.http import models
from core.http.admin import user
from core.http.admin import another
admin.site.unregister(db_models.Group)
admin.site.register(db_models.Group, user.GroupAdmin)
admin.site.register(models.Tags, another.TagsAdmin)
admin.site.register(models.Post, another.PostAdmin)
admin.site.register(models.User, user.CustomUserAdmin)
admin.site.register(models.Comment, another.CommentAdmin)
admin.site.register(models.SmsConfirm, another.SmsConfirmAdmin)
admin.site.register(
models.FrontendTranslation, another.FrontendTranslationAdmin
) # noqa

47
core/http/admin/user.py Normal file
View File

@@ -0,0 +1,47 @@
from django.contrib.auth import admin
from import_export import admin as import_export
from import_export.admin import ImportExportModelAdmin
from core.http.forms import CustomUserCreationForm
class CustomUserAdmin(admin.UserAdmin, ImportExportModelAdmin):
add_form = CustomUserCreationForm
list_display = ["id", "phone", "first_name", "last_name", "role"]
search_fields = ["phone", "first_name", "last_name"]
list_filter = ["role"]
fieldsets = (
(None, {"fields": ("username", "phone", "password")}),
(
"Personal info",
{"fields": ("first_name", "last_name", "email", "role", "avatar", "fcm_token")},
),
(
"Permissions",
{
"fields": (
"is_active",
"is_staff",
"is_superuser",
"groups",
"user_permissions",
)
},
),
("Important dates", {"fields": ("last_login", "date_joined")}),
)
add_fieldsets = (
(
None,
{
"classes": ("wide",),
"fields": ("phone", "password1", "password2"),
},
),
)
class GroupAdmin(import_export.ImportExportModelAdmin):
list_display = ["name"]
search_fields = ["name"]
filter_horizontal = ("permissions",)

0
core/http/database/__init__.py Executable file
View File

View File

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

View File

@@ -0,0 +1,31 @@
"""
Create a new fake User/Post
"""
from core.http import models
from core.utils import factory
class UserFactory(factory.BaseFaker):
model = models.User
def handle(self):
"""
Factory method
"""
return {
"first_name": self.faker.first_name(),
"username": self.faker.user_name(),
"phone": self.faker.phone_number(),
}
class PostFactory(factory.BaseFaker):
model = models.Post
def handle(self):
return {
"title": self.faker.name(),
"desc": self.faker.text(),
"image": self.faker.image_url(),
}

View File

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

View File

@@ -0,0 +1,11 @@
"""
Create a new user/superuser
"""
from core.http import models
class UserSeeder:
def run(self):
models.User.objects.create_user("998943990509", "2309")
models.User.objects.create_superuser("998888112309", "2309")

View File

@@ -0,0 +1,2 @@
from .another import * # noqa
from .user import * # noqa

View File

@@ -0,0 +1,17 @@
"""
Project base forms
"""
from django import forms
from django_ckeditor_5 import widgets
from core.http import models
class PostAdminForm(forms.ModelForm):
class Meta:
model = models.Post
widgets = {
"desc": widgets.CKEditor5Widget(),
}
fields = "__all__"

8
core/http/forms/user.py Normal file
View File

@@ -0,0 +1,8 @@
from django.contrib.auth.forms import UserCreationForm
from core.http.models import User
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = User
fields = ("id", "phone")

View File

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

View File

View File

@@ -0,0 +1,16 @@
"""
Clear cache command
"""
from django.core.cache import cache
from django.core.management import BaseCommand
from core.utils import console
class Command(BaseCommand):
help = "Clear all caches"
def handle(self, *args, **options):
cache.clear()
console.Console.success("Cache cleared successfully")

10
core/http/management/core.py Executable file
View File

@@ -0,0 +1,10 @@
from django.db.models.manager import BaseManager as BManager
from django.db.models.query import QuerySet
class BaseQuerySet(QuerySet):
pass
class BaseManager(BManager):
pass

View File

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

View File

@@ -0,0 +1,24 @@
from django.contrib.auth import base_user
class UserManager(base_user.BaseUserManager):
def create_user(self, phone, password=None, **extra_fields):
if not phone:
raise ValueError("The phone number must be set")
user = self.model(phone=phone, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, phone, password=None, **extra_fields):
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
if extra_fields.get("is_staff") is not True:
raise ValueError("Superuser must have is_staff=True.")
if extra_fields.get("is_superuser") is not True:
raise ValueError("Superuser must have is_superuser=True.")
return self.create_user(phone, password, **extra_fields)

View File

@@ -0,0 +1,276 @@
# Generated by Django 5.0.4 on 2024-04-22 11:17
import django.db.models.deletion
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
("auth", "0012_alter_user_first_name_max_length"),
("contenttypes", "0002_remove_content_type_name"),
]
operations = [
migrations.CreateModel(
name="BaseComment",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"polymorphic_ctype",
models.ForeignKey(
editable=False,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="polymorphic_%(app_label)s.%(class)s_set+",
to="contenttypes.contenttype",
),
),
],
options={
"abstract": False,
"base_manager_name": "objects",
},
),
migrations.CreateModel(
name="Comment",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("text", models.CharField(max_length=255)),
],
),
migrations.CreateModel(
name="SmsConfirm",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("code", models.IntegerField()),
("try_count", models.IntegerField(default=0)),
("resend_count", models.IntegerField(default=0)),
("phone", models.CharField(max_length=20)),
("expire_time", models.DateTimeField(blank=True, null=True)),
("unlock_time", models.DateTimeField(blank=True, null=True)),
(
"resend_unlock_time",
models.DateTimeField(blank=True, null=True),
),
],
),
migrations.CreateModel(
name="Tags",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=255)),
],
options={
"verbose_name": "Tag",
"verbose_name_plural": "Tags",
},
),
migrations.CreateModel(
name="User",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"password",
models.CharField(max_length=128, verbose_name="password"),
),
(
"last_login",
models.DateTimeField(
blank=True, null=True, verbose_name="last login"
),
),
(
"is_superuser",
models.BooleanField(
default=False,
help_text="Designates that this user has all permissions without explicitly assigning them.",
verbose_name="superuser status",
),
),
(
"first_name",
models.CharField(
blank=True, max_length=150, verbose_name="first name"
),
),
(
"last_name",
models.CharField(
blank=True, max_length=150, verbose_name="last name"
),
),
(
"email",
models.EmailField(
blank=True,
max_length=254,
verbose_name="email address",
),
),
(
"is_staff",
models.BooleanField(
default=False,
help_text="Designates whether the user can log into this admin site.",
verbose_name="staff status",
),
),
(
"is_active",
models.BooleanField(
default=True,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
verbose_name="active",
),
),
(
"date_joined",
models.DateTimeField(
default=django.utils.timezone.now,
verbose_name="date joined",
),
),
("phone", models.CharField(max_length=255, unique=True)),
(
"username",
models.CharField(blank=True, max_length=255, null=True),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
("validated_at", models.DateTimeField(blank=True, null=True)),
(
"groups",
models.ManyToManyField(
blank=True,
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
related_name="user_set",
related_query_name="user",
to="auth.group",
verbose_name="groups",
),
),
(
"user_permissions",
models.ManyToManyField(
blank=True,
help_text="Specific permissions for this user.",
related_name="user_set",
related_query_name="user",
to="auth.permission",
verbose_name="user permissions",
),
),
],
options={
"verbose_name": "user",
"verbose_name_plural": "users",
"abstract": False,
},
),
migrations.CreateModel(
name="FrontendTranslation",
fields=[
(
"basecomment_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="http.basecomment",
),
),
("key", models.CharField(max_length=255, unique=True)),
("value", models.TextField()),
("value_uz", models.TextField(null=True)),
("value_ru", models.TextField(null=True)),
("value_en", models.TextField(null=True)),
],
options={
"verbose_name": "Frontend Translation",
"verbose_name_plural": "Frontend Translations",
},
bases=("http.basecomment",),
),
migrations.AddField(
model_name="basecomment",
name="comments",
field=models.ManyToManyField(to="http.comment"),
),
migrations.CreateModel(
name="Post",
fields=[
(
"basecomment_ptr",
models.OneToOneField(
auto_created=True,
on_delete=django.db.models.deletion.CASCADE,
parent_link=True,
primary_key=True,
serialize=False,
to="http.basecomment",
),
),
("title", models.CharField(max_length=255)),
("title_uz", models.CharField(max_length=255, null=True)),
("title_ru", models.CharField(max_length=255, null=True)),
("title_en", models.CharField(max_length=255, null=True)),
("desc", models.TextField()),
("desc_uz", models.TextField(null=True)),
("desc_ru", models.TextField(null=True)),
("desc_en", models.TextField(null=True)),
("image", models.ImageField(blank=True, upload_to="posts/")),
("tags", models.ManyToManyField(to="http.tags")),
],
options={
"abstract": False,
"base_manager_name": "objects",
},
bases=("http.basecomment",),
),
]

View File

@@ -0,0 +1,34 @@
# Generated by Django 5.0.4 on 2024-04-23 10:55
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("http", "0001_initial"),
]
operations = [
migrations.AddField(
model_name="user",
name="avatar",
field=models.ImageField(
blank=True, null=True, upload_to="avatars/"
),
),
migrations.AddField(
model_name="user",
name="role",
field=models.CharField(
choices=[
("admin", "Admin"),
("market", "Market"),
("courier", "Courier"),
("sklad", "Sklad"),
],
default="market",
max_length=10,
),
),
]

View File

@@ -0,0 +1,27 @@
# Generated by Django 5.0.4 on 2024-04-23 11:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("http", "0002_user_avatar_user_role"),
]
operations = [
migrations.AlterField(
model_name="user",
name="role",
field=models.CharField(
choices=[
("admin", "Admin"),
("market", "Market"),
("courier", "Courier"),
("sklad", "Sklad"),
],
default="admin",
max_length=10,
),
),
]

View File

@@ -0,0 +1,23 @@
# Generated by Django 5.0.7 on 2024-07-22 13:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("http", "0003_alter_user_role"),
]
operations = [
migrations.AlterField(
model_name="user",
name="avatar",
field=models.ImageField(
blank=True,
default="avatars/golden_eggs.png",
null=True,
upload_to="avatars/",
),
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.0.8 on 2024-08-29 08:57
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("http", "0004_alter_user_avatar"),
]
operations = [
migrations.AddField(
model_name="user",
name="fcm_token",
field=models.CharField(blank=True, max_length=255, null=True),
),
]

View File

View File

@@ -0,0 +1,3 @@
from .another import * # noqa
from .base import * # noqa
from .user import * # noqa

View File

@@ -0,0 +1,47 @@
from django.db import models
from polymorphic import models as polymorphic
from django.utils.translation import gettext as _
class Tags(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Meta:
verbose_name = _("Tag")
verbose_name_plural = _("Tags")
class Comment(models.Model):
text = models.CharField(max_length=255)
def __str__(self) -> str:
return self.text
class BaseComment(polymorphic.PolymorphicModel):
comments = models.ManyToManyField(Comment)
class Post(BaseComment):
title = models.CharField(max_length=255)
desc = models.TextField()
image = models.ImageField(upload_to="posts/", blank=True)
tags = models.ManyToManyField(Tags)
def __str__(self):
return self.title
class FrontendTranslation(BaseComment):
key = models.CharField(max_length=255, unique=True)
value = models.TextField()
def __str__(self):
return self.key
class Meta:
verbose_name = _("Frontend Translation")
verbose_name_plural = _("Frontend Translations")

9
core/http/models/base.py Normal file
View File

@@ -0,0 +1,9 @@
from django.db import models
class AbstractBaseModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True

110
core/http/models/user.py Normal file
View File

@@ -0,0 +1,110 @@
import math
from datetime import datetime, timedelta
from django.contrib.auth import models as auth_models
from django.db import models
from django.utils.translation import gettext_lazy as _
from core.http import managers
class User(auth_models.AbstractUser):
ROLE_CHOICES = (
("admin", _("Admin")),
("market", _("Market")),
("courier", _("Courier")),
("sklad", _("Sklad")),
)
phone = models.CharField(max_length=255, unique=True)
username = models.CharField(max_length=255, null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
validated_at = models.DateTimeField(null=True, blank=True)
USERNAME_FIELD = "phone"
objects = managers.UserManager()
avatar = models.ImageField(
upload_to="avatars/",
null=True,
blank=True,
default="avatars/golden_eggs.png",
)
role = models.CharField(
max_length=10,
choices=ROLE_CHOICES,
default="admin",
)
fcm_token = models.CharField(max_length=255, null=True, blank=True)
def __str__(self):
return f"{self.phone} | {self.id}"
class SmsConfirm(models.Model):
SMS_EXPIRY_SECONDS = 120
RESEND_BLOCK_MINUTES = 10
TRY_BLOCK_MINUTES = 2
RESEND_COUNT = 5
TRY_COUNT = 10
code = models.IntegerField()
try_count = models.IntegerField(default=0)
resend_count = models.IntegerField(default=0)
phone = models.CharField(max_length=20)
expire_time = models.DateTimeField(null=True, blank=True)
unlock_time = models.DateTimeField(null=True, blank=True)
resend_unlock_time = models.DateTimeField(null=True, blank=True)
def sync_limits(self):
if self.resend_count >= self.RESEND_COUNT:
self.try_count = 0
self.resend_count = 0
self.resend_unlock_time = datetime.now() + timedelta(
minutes=self.RESEND_BLOCK_MINUTES
)
elif self.try_count >= self.TRY_COUNT:
self.try_count = 0
self.unlock_time = datetime.now() + timedelta(
minutes=self.TRY_BLOCK_MINUTES
)
if (
self.resend_unlock_time is not None
and self.resend_unlock_time.timestamp()
< datetime.now().timestamp()
):
self.resend_unlock_time = None
if (
self.unlock_time is not None
and self.unlock_time.timestamp() < datetime.now().timestamp()
):
self.unlock_time = None
self.save()
def is_expired(self):
return (
self.expire_time.timestamp() < datetime.now().timestamp()
if hasattr(self.expire_time, "timestamp")
else None
)
def is_block(self):
return self.unlock_time is not None
def reset_limits(self):
self.try_count = 0
self.resend_count = 0
self.unlock_time = None
def interval(self, time):
expire = time.timestamp() - datetime.now().timestamp()
minutes = math.floor(expire / 60)
expire -= minutes * 60
expire = math.floor(expire)
return f"{minutes:02d}:{expire:02d}"
def __str__(self) -> str:
return f"{self.phone} | {self.code}"

View File

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

View File

@@ -0,0 +1,16 @@
from rest_framework.permissions import BasePermission
from django.utils.translation import gettext_lazy as _
class IsRole(BasePermission):
message = _("You must be an admin to perform this action.")
def __init__(self, role):
super().__init__()
self.role = role
def __call__(self):
return self
def has_permission(self, request, view):
return request.user.role in self.role

View File

@@ -0,0 +1,4 @@
from .another import * # noqa
from .auth import * # noqa
from .generics import * # noqa
from .user import * # noqa

View File

@@ -0,0 +1,15 @@
from rest_framework import serializers
from core.http import models
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = models.Post
fields = ["title", "desc", "image"]
class FrontendTransactionSerializer(serializers.ModelSerializer):
class Meta:
model = models.FrontendTranslation
fields = ["key", "value"]

View File

@@ -0,0 +1,66 @@
from django.utils.translation import gettext as _
from rest_framework import exceptions, serializers
from core.http import models
class LoginSerializer(serializers.Serializer):
username = serializers.CharField(max_length=255)
password = serializers.CharField(max_length=255)
class RegisterSerializer(serializers.ModelSerializer):
phone = serializers.CharField(max_length=255)
def validate_phone(self, value):
user = models.User.objects.filter(
phone=value, validated_at__isnull=False
)
if user.exists():
return exceptions.ValidationError(
_("Telefon raqami allaqachon ro'yxatdan o'tgan."),
code="unique",
)
return value
class Meta:
model = models.User
fields = ["first_name", "last_name", "phone", "password"]
extra_kwargs = {
"first_name": {
"required": True,
},
"last_name": {"required": True},
}
class ConfirmSerializer(serializers.Serializer):
code = serializers.IntegerField(min_value=1000, max_value=9999)
phone = serializers.CharField(max_length=255)
class ResetPasswordSerializer(serializers.Serializer):
phone = serializers.CharField(max_length=255)
def validate_phone(self, value):
user = models.User.objects.filter(phone=value)
if user.exists():
return value
raise serializers.ValidationError(_("Foydalanuvchi mavjud emas"))
class ResetConfirmationSerializer(serializers.Serializer):
code = serializers.IntegerField(min_value=1000, max_value=9999)
phone = serializers.CharField(max_length=255)
password = serializers.CharField(max_length=255)
def validate_phone(self, value):
user = models.User.objects.filter(phone=value)
if user.exists():
return value
raise serializers.ValidationError(_("User does not exist"))
class ResendSerializer(serializers.Serializer):
phone = serializers.CharField(max_length=255)

View File

@@ -0,0 +1,17 @@
from rest_framework import exceptions
from rest_framework import serializers
from core import enums
from core.utils import exception
class GenericSerializer(serializers.Serializer):
def to_internal_value(self, data):
try:
return super().to_internal_value(data)
except exceptions.ValidationError as e:
key, value = next(iter(e.detail.items()))
exception.ResponseException(
value[0], error_code=enums.Codes.INVALID_PARAMETER_VALUE
)

View File

@@ -0,0 +1,35 @@
from rest_framework import serializers
from core.http import models
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = models.User
fields = (
"id",
"first_name",
"last_name",
"phone",
"email",
"role",
"username",
"avatar",
)
class UserUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = models.User
fields = (
"first_name",
"last_name",
"username",
"phone",
)
class UserAvatarUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = models.User
fields = ("avatar",)

View File

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

25
core/http/tasks/sms.py Normal file
View File

@@ -0,0 +1,25 @@
"""
Base celery tasks
"""
from celery import shared_task
from django.utils.translation import gettext as _
from core.services import sms_service
from core.utils import console
@shared_task
def SendConfirm(phone, code):
try:
service: sms_service.SendService = sms_service.SendService()
service.send_sms(
phone, _("Sizning Tasdiqlash ko'dingiz: %(code)s") % {"code": code}
)
console.Console().success(f"Success: {phone}-{code}")
except Exception as e:
console.Console().error(
"Error: {phone}-{code}\n\n{error}".format(
phone=phone, code=code, error=e
)
) # noqa

View File

54
core/http/templatetags/vite.py Executable file
View File

@@ -0,0 +1,54 @@
import json
from django import template
from django.conf import settings
from django.templatetags import static
from django.utils import safestring
from common.env import env
register = template.Library()
def getScript(url: object) -> str:
ext: str = str(url).split(".")[-1]
if env("VITE_LIVE"):
url = f"http://{env('VITE_HOST')}:{env('VITE_PORT')}/{url}"
else:
url: str = static.static(f"vite/{url}")
if ext == "css":
script: str = f"<link rel='stylesheet' type='text/css' href='{url}'>"
else:
script: str = (
"<script type='module' type='text/javascript' src='{"
"}'></script>"
).format(url)
return script
@register.simple_tag
def vite_load(*args):
try:
fd = open(f"{settings.VITE_APP_DIR}/manifest.json")
manifest = json.load(fd)
except Exception:
raise Exception(
f"Vite manifest file not found or invalid. Maybe your"
f" {settings.VITE_APP_DIR}/manifest.json file is empty?"
)
if not env("VITE_LIVE"):
imports_files = "".join(
[getScript(file["file"]) for file in manifest.values()]
)
else:
imports_files = "".join([getScript(file) for file in args])
imports_files += f""" <script type="module"
src="http://{env('VITE_HOST')}:{env('VITE_PORT')}/@vite/client"></script> <script
type="module" src="{static.static(
"js/vite-refresh.js")}"></script>
"""
return safestring.mark_safe(imports_files)

View File

@@ -0,0 +1,2 @@
from .core import * # noqa
from .another import * # noqa

View File

@@ -0,0 +1,16 @@
"""
Django model translation resources
"""
from modeltranslation import translator
class PostTranslationOption(translator.TranslationOptions):
fields = (
"title",
"desc",
)
class FrontendTranslationOption(translator.TranslationOptions):
fields = ("value",)

View File

@@ -0,0 +1,14 @@
"""
Register models
"""
from modeltranslation.translator import translator
from core.http import models
from core.http.translation import another
translator.register(models.Post, another.PostTranslationOption)
translator.register(
models.FrontendTranslation, another.FrontendTranslationOption
) # noqa

View File

@@ -0,0 +1,2 @@
from .auth import * # noqa
from .generics import * # noqa

25
core/http/views/auth.py Normal file
View File

@@ -0,0 +1,25 @@
from django.utils.translation import gettext as _
from rest_framework import views
from rest_framework import request
from rest_framework import throttling
from core import enums
from core import services
from core.http import serializers
from core.http.views import generics as http_views
class AbstractSendSms(views.APIView, http_views.ApiResponse):
serializer_class = serializers.ResendSerializer
throttle_classes = [throttling.UserRateThrottle]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.service = services.UserService()
def post(self, request: request.Request):
ser = self.serializer_class(data=request.data)
ser.is_valid(raise_exception=True)
phone = ser.data.get("phone")
self.service.send_confirmation(phone)
return self.success(_(enums.Messages.SEND_MESSAGE) % {"phone": phone})

View File

@@ -0,0 +1,67 @@
from rest_framework import generics, response, status
from core.exceptions import BreakException
class ApiResponse:
def response(
self,
success=True,
message="",
data=None,
status_code=status.HTTP_200_OK,
**kwargs
):
if data is None:
data = {}
response_data = {
"success": success,
"message": message,
"data": data,
**kwargs,
}
return response.Response(data=response_data, status=status_code)
def success(
self, message="", data=None, status_code=status.HTTP_200_OK, **kwargs
):
return self.response(True, message, data, status_code, **kwargs)
def error(
self,
message="",
data=None,
error_code=0,
status_code=status.HTTP_400_BAD_REQUEST,
exception=None,
**kwargs
):
if isinstance(exception, BreakException):
raise exception
return self.response(
False, message, data, status_code, error_code=error_code, **kwargs
) # noqa
class ListApiView(generics.ListAPIView, ApiResponse):
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return self.success(data=serializer.data)
class CreateApiView(generics.CreateAPIView, ApiResponse):
def create(self, request, *args, **kwargs):
super().create(request, *args, **kwargs)
return self.success(
self.message
if hasattr(self, "message")
else "Muvaffaqiyatli yaratildi"
) # noqa

29
core/http/views/user.py Normal file
View File

@@ -0,0 +1,29 @@
from rest_framework.generics import UpdateAPIView
from core.http.models import User
from core.http.serializers.user import (
UserAvatarUpdateSerializer,
UserUpdateSerializer,
)
class UserUpdateView(UpdateAPIView):
serializer_class = UserUpdateSerializer
queryset = User.objects.all()
def get_object(self):
return self.request.user
def perform_update(self, serializer):
serializer.save(user=self.request.user)
class UserAvatarUpdateView(UpdateAPIView):
serializer_class = UserAvatarUpdateSerializer
queryset = User.objects.all()
def get_object(self):
return self.request.user
def perform_update(self, serializer):
serializer.save(user=self.request.user)