lkejfgle 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/db.sqlite3 +0 -0
  2. package/ekz/__init__.py +0 -0
  3. package/ekz/__pycache__/__init__.cpython-312.pyc +0 -0
  4. package/ekz/__pycache__/__init__.cpython-313.pyc +0 -0
  5. package/ekz/__pycache__/settings.cpython-312.pyc +0 -0
  6. package/ekz/__pycache__/settings.cpython-313.pyc +0 -0
  7. package/ekz/__pycache__/urls.cpython-312.pyc +0 -0
  8. package/ekz/__pycache__/urls.cpython-313.pyc +0 -0
  9. package/ekz/__pycache__/wsgi.cpython-312.pyc +0 -0
  10. package/ekz/__pycache__/wsgi.cpython-313.pyc +0 -0
  11. package/ekz/asgi.py +16 -0
  12. package/ekz/settings.py +137 -0
  13. package/ekz/urls.py +77 -0
  14. package/ekz/wsgi.py +16 -0
  15. package/front/__init__.py +0 -0
  16. package/front/__pycache__/__init__.cpython-312.pyc +0 -0
  17. package/front/__pycache__/__init__.cpython-313.pyc +0 -0
  18. package/front/__pycache__/admin.cpython-312.pyc +0 -0
  19. package/front/__pycache__/admin.cpython-313.pyc +0 -0
  20. package/front/__pycache__/apps.cpython-312.pyc +0 -0
  21. package/front/__pycache__/apps.cpython-313.pyc +0 -0
  22. package/front/__pycache__/backends.cpython-312.pyc +0 -0
  23. package/front/__pycache__/backends.cpython-313.pyc +0 -0
  24. package/front/__pycache__/forms.cpython-312.pyc +0 -0
  25. package/front/__pycache__/forms.cpython-313.pyc +0 -0
  26. package/front/__pycache__/models.cpython-312.pyc +0 -0
  27. package/front/__pycache__/models.cpython-313.pyc +0 -0
  28. package/front/__pycache__/views.cpython-312.pyc +0 -0
  29. package/front/__pycache__/views.cpython-313.pyc +0 -0
  30. package/front/admin.py +124 -0
  31. package/front/apps.py +6 -0
  32. package/front/backends.py +51 -0
  33. package/front/forms.py +454 -0
  34. package/front/migrations/0001_initial.py +52 -0
  35. package/front/migrations/0002_customuser_avatar_alter_customuser_address_and_more.py +68 -0
  36. package/front/migrations/0003_alter_customuser_email_alter_customuser_first_name_and_more.py +34 -0
  37. package/front/migrations/0004_category_application_forumtopic_forumcomment_news_and_more.py +187 -0
  38. package/front/migrations/0005_table_tablereservation.py +52 -0
  39. package/front/migrations/0006_applicationreview.py +30 -0
  40. package/front/migrations/0007_alter_application_status.py +18 -0
  41. package/front/migrations/0008_application_category.py +19 -0
  42. package/front/migrations/__init__.py +0 -0
  43. package/front/migrations/__pycache__/0001_initial.cpython-312.pyc +0 -0
  44. package/front/migrations/__pycache__/0001_initial.cpython-313.pyc +0 -0
  45. package/front/migrations/__pycache__/0002_alter_customuser_options_customuser_education_and_more.cpython-312.pyc +0 -0
  46. package/front/migrations/__pycache__/0002_customuser_avatar_alter_customuser_address_and_more.cpython-312.pyc +0 -0
  47. package/front/migrations/__pycache__/0002_customuser_avatar_alter_customuser_address_and_more.cpython-313.pyc +0 -0
  48. package/front/migrations/__pycache__/0003_alter_customuser_email_alter_customuser_first_name_and_more.cpython-312.pyc +0 -0
  49. package/front/migrations/__pycache__/0003_alter_customuser_email_alter_customuser_first_name_and_more.cpython-313.pyc +0 -0
  50. package/front/migrations/__pycache__/0003_alter_customuser_options_alter_customuser_address_and_more.cpython-312.pyc +0 -0
  51. package/front/migrations/__pycache__/0004_alter_customuser_managers_and_more.cpython-312.pyc +0 -0
  52. package/front/migrations/__pycache__/0004_category_application_forumtopic_forumcomment_news_and_more.cpython-313.pyc +0 -0
  53. package/front/migrations/__pycache__/0005_table_tablereservation.cpython-313.pyc +0 -0
  54. package/front/migrations/__pycache__/0006_applicationreview.cpython-313.pyc +0 -0
  55. package/front/migrations/__pycache__/0007_alter_application_status.cpython-313.pyc +0 -0
  56. package/front/migrations/__pycache__/0008_application_category.cpython-313.pyc +0 -0
  57. package/front/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
  58. package/front/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  59. package/front/models.py +425 -0
  60. package/front/static/bootstrap-icons.css +2018 -0
  61. package/front/static/bootstrap.bundle.min.js +7 -0
  62. package/front/static/bootstrap.min.css +6 -0
  63. package/front/static/bootstrap.min.js +7 -0
  64. package/front/static/fonts/bootstrap-icons.woff +0 -0
  65. package/front/static/fonts/bootstrap-icons.woff2 +0 -0
  66. package/front/static/images/logo.png +0 -0
  67. package/front/static/styles.css +282 -0
  68. package/front/templates/admin/confirm_delete.html +39 -0
  69. package/front/templates/admin/dashboard.html +39 -0
  70. package/front/templates/admin/model_form.html +79 -0
  71. package/front/templates/admin/model_list.html +100 -0
  72. package/front/templates/base.html +42 -0
  73. package/front/templates/components/header.html +78 -0
  74. package/front/templates/components/login.html +120 -0
  75. package/front/templates/components/login_in_modal.html +193 -0
  76. package/front/templates/components/register.html +360 -0
  77. package/front/templates/components/register_in_modal.html +261 -0
  78. package/front/templates/pages/add_application_review.html +58 -0
  79. package/front/templates/pages/application_form.html +103 -0
  80. package/front/templates/pages/application_success.html +20 -0
  81. package/front/templates/pages/cancel_reservation.html +63 -0
  82. package/front/templates/pages/cart.html +91 -0
  83. package/front/templates/pages/catalog.html +93 -0
  84. package/front/templates/pages/checkout.html +70 -0
  85. package/front/templates/pages/contacts.html +67 -0
  86. package/front/templates/pages/create_forum_topic.html +43 -0
  87. package/front/templates/pages/edit_application.html +112 -0
  88. package/front/templates/pages/edit_forum_topic.html +45 -0
  89. package/front/templates/pages/favorites.html +43 -0
  90. package/front/templates/pages/forum_list.html +78 -0
  91. package/front/templates/pages/forum_topic.html +133 -0
  92. package/front/templates/pages/main_page.html +150 -0
  93. package/front/templates/pages/news_detail.html +38 -0
  94. package/front/templates/pages/news_list.html +36 -0
  95. package/front/templates/pages/order_detail.html +129 -0
  96. package/front/templates/pages/order_success.html +50 -0
  97. package/front/templates/pages/orders.html +54 -0
  98. package/front/templates/pages/product_detail.html +202 -0
  99. package/front/templates/pages/profile.html +214 -0
  100. package/front/templates/pages/reviews.html +89 -0
  101. package/front/templates/pages/table_detail.html +219 -0
  102. package/front/templates/pages/tables_catalog.html +91 -0
  103. package/front/templates/pages/user_applications.html +134 -0
  104. package/front/templates/pages/user_reservations.html +92 -0
  105. package/front/templatetags/__pycache__/admin_extras.cpython-313.pyc +0 -0
  106. package/front/templatetags/admin_extras.py +13 -0
  107. package/front/tests.py +3 -0
  108. package/front/views.py +1087 -0
  109. package/manage.py +22 -0
  110. package/media/avatars//320/260/320/270/314/206/321/201_/320/273/320/260/321/202/321/202/320/265.jpg +0 -0
  111. package/media/categories//320/260/320/270/314/206/321/201_/320/273/320/260/321/202/321/202/320/265.jpg +0 -0
  112. package/media/news/5de24294bad21ec99931f4c362354f22.jpg +0 -0
  113. package/media/news/alien-pictures-g3ywlhr5ik0fwdwg.jpg +0 -0
  114. package/media/products/d438c31d0caf10b0dc17a5fcb503a38e.jpg +0 -0
  115. package/package.json +12 -0
package/db.sqlite3 ADDED
Binary file
File without changes
package/ekz/asgi.py ADDED
@@ -0,0 +1,16 @@
1
+ """
2
+ ASGI config for ekz project.
3
+
4
+ It exposes the ASGI callable as a module-level variable named ``application``.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
8
+ """
9
+
10
+ import os
11
+
12
+ from django.core.asgi import get_asgi_application
13
+
14
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ekz.settings')
15
+
16
+ application = get_asgi_application()
@@ -0,0 +1,137 @@
1
+ """
2
+ Django settings for ekz project.
3
+
4
+ Generated by 'django-admin startproject' using Django 5.0.6.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/5.0/topics/settings/
8
+
9
+ For the full list of settings and their values, see
10
+ https://docs.djangoproject.com/en/5.0/ref/settings/
11
+ """
12
+
13
+ from pathlib import Path
14
+ import os
15
+
16
+ # Build paths inside the project like this: BASE_DIR / 'subdir'.
17
+ BASE_DIR = Path(__file__).resolve().parent.parent
18
+
19
+
20
+ # Quick-start development settings - unsuitable for production
21
+ # See https://docs.djangoproject.com/en/5.0/howto/deployment/checklist/
22
+
23
+ # SECURITY WARNING: keep the secret key used in production secret!
24
+ SECRET_KEY = 'django-insecure-m&-$wt=t76(#qk%y-%dq$1r+ct1gxn99nq3+(ix9%t@2n+aq7u'
25
+
26
+ # SECURITY WARNING: don't run with debug turned on in production!
27
+ DEBUG = True
28
+
29
+ ALLOWED_HOSTS = []
30
+
31
+
32
+ # Application definition
33
+
34
+ INSTALLED_APPS = [
35
+ 'django.contrib.admin',
36
+ 'django.contrib.auth',
37
+ 'django.contrib.contenttypes',
38
+ 'django.contrib.sessions',
39
+ 'django.contrib.messages',
40
+ 'django.contrib.staticfiles',
41
+ 'front'
42
+ ]
43
+
44
+ MIDDLEWARE = [
45
+ 'django.middleware.security.SecurityMiddleware',
46
+ 'django.contrib.sessions.middleware.SessionMiddleware',
47
+ 'django.middleware.common.CommonMiddleware',
48
+ 'django.middleware.csrf.CsrfViewMiddleware',
49
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
50
+ 'django.contrib.messages.middleware.MessageMiddleware',
51
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
52
+ ]
53
+
54
+ ROOT_URLCONF = 'ekz.urls'
55
+
56
+ TEMPLATES = [
57
+ {
58
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
59
+ 'DIRS': [],
60
+ 'APP_DIRS': True,
61
+ 'OPTIONS': {
62
+ 'context_processors': [
63
+ 'django.template.context_processors.debug',
64
+ 'django.template.context_processors.request',
65
+ 'django.contrib.auth.context_processors.auth',
66
+ 'django.contrib.messages.context_processors.messages',
67
+ ],
68
+ },
69
+ },
70
+ ]
71
+
72
+ WSGI_APPLICATION = 'ekz.wsgi.application'
73
+
74
+
75
+ # Database
76
+ # https://docs.djangoproject.com/en/5.0/ref/settings/#databases
77
+
78
+ DATABASES = {
79
+ 'default': {
80
+ 'ENGINE': 'django.db.backends.sqlite3',
81
+ 'NAME': BASE_DIR / 'db.sqlite3',
82
+ }
83
+ }
84
+
85
+
86
+ # Password validation
87
+ # https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
88
+
89
+ AUTH_PASSWORD_VALIDATORS = [
90
+ {
91
+ 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
92
+ },
93
+ {
94
+ 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
95
+ },
96
+ {
97
+ 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
98
+ },
99
+ {
100
+ 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
101
+ },
102
+ ]
103
+
104
+
105
+ # Internationalization
106
+ # https://docs.djangoproject.com/en/5.0/topics/i18n/
107
+
108
+ LANGUAGE_CODE = 'en-us'
109
+
110
+ TIME_ZONE = 'UTC'
111
+
112
+ USE_I18N = True
113
+
114
+ USE_TZ = True
115
+
116
+
117
+ # Static files (CSS, JavaScript, Images)
118
+ # https://docs.djangoproject.com/en/5.0/howto/static-files/
119
+
120
+ STATIC_URL = 'static/'
121
+
122
+ # Default primary key field type
123
+ # https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
124
+
125
+ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
126
+
127
+ AUTH_USER_MODEL = 'front.CustomUser'
128
+
129
+ MEDIA_URL = '/media/'
130
+ MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
131
+
132
+ LOGOUT_REDIRECT_URL = '/' # Перенаправлять на главную после выхода
133
+
134
+ AUTHENTICATION_BACKENDS = [
135
+ 'django.contrib.auth.backends.ModelBackend',
136
+ 'front.backends.MultiFieldAuthBackend',
137
+ ]
package/ekz/urls.py ADDED
@@ -0,0 +1,77 @@
1
+ from django.contrib import admin
2
+ from django.urls import path
3
+ from front import views
4
+ from django.conf.urls.static import static
5
+ from django.conf import settings
6
+ from django.contrib.auth.views import LogoutView
7
+
8
+ urlpatterns = [
9
+ # Администрирование и аутентификация
10
+ path('admin/', admin.site.urls, name='admin'),
11
+ path('myadmin/', views.custom_admin_dashboard, name='custom_admin'), # Кастомная админка
12
+ path('myadmin/<str:model_name>/', views.custom_admin_model, name='custom_admin_model'),
13
+ path('myadmin/<str:model_name>/add/', views.custom_admin_add, name='custom_admin_add'),
14
+ path('myadmin/<str:model_name>/<int:object_id>/edit/', views.custom_admin_edit, name='custom_admin_edit'),
15
+ path('myadmin/<str:model_name>/<int:object_id>/delete/', views.custom_admin_delete, name='custom_admin_delete'),
16
+ path('admin/', admin.site.urls, name='admin'),
17
+ path('', views.main_page, name='main_page'),
18
+ path('register/', views.register_view, name='register'),
19
+ path('login/', views.login_view, name='login'),
20
+ path('logout/', views.logout_view, name='logout'),
21
+ path('modal/register/', views.modal_register_view, name='modal_register'),
22
+ path('modal/login/', views.modal_login_view, name='modal_login'),
23
+ path('profile/', views.profile_view, name='profile'),
24
+
25
+ # 1. Каталог товаров
26
+ path('catalog/', views.catalog_view, name='catalog'),
27
+ path('product/<int:product_id>/', views.product_detail_view, name='product_detail'),
28
+
29
+ # 2. Корзина
30
+ path('cart/', views.cart_view, name='cart'),
31
+ path('cart/add/<int:product_id>/', views.add_to_cart, name='add_to_cart'),
32
+ path('cart/update/<int:item_id>/', views.update_cart_item, name='update_cart_item'),
33
+ path('cart/remove/<int:item_id>/', views.remove_from_cart, name='remove_from_cart'),
34
+
35
+ # 3. Избранное
36
+ path('favorites/', views.favorites_view, name='favorites'),
37
+ path('favorites/add/<int:product_id>/', views.add_to_favorites, name='add_to_favorites'),
38
+ path('favorites/remove/<int:favorite_id>/', views.remove_from_favorites, name='remove_from_favorites'),
39
+
40
+ # 4. Заказы
41
+ path('checkout/', views.checkout_view, name='checkout'),
42
+ path('order/success/<int:order_id>/', views.order_success_view, name='order_success'),
43
+ path('orders/', views.orders_view, name='orders'),
44
+ path('order/<int:order_id>/', views.order_detail_view, name='order_detail'),
45
+
46
+ # 5. Отзывы
47
+ path('reviews/', views.reviews_view, name='reviews'),
48
+
49
+ # 6-7. Заявки
50
+ path('application/new/', views.application_form_view, name='application_form'),
51
+ path('application/success/', views.application_success_view, name='application_success'),
52
+ path('applications/', views.user_applications_view, name='user_applications'),
53
+ path('application/edit/<int:application_id>/', views.edit_application_view, name='edit_application'),
54
+ path('application/<int:application_id>/review/', views.add_application_review_view, name='add_application_review'),
55
+
56
+ # 8. Новости
57
+ path('news/', views.news_list_view, name='news_list'),
58
+ path('news/<int:news_id>/', views.news_detail_view, name='news_detail'),
59
+
60
+ # 9. Форум
61
+ path('forum/', views.forum_list_view, name='forum_list'),
62
+ path('forum/topic/<int:topic_id>/', views.forum_topic_view, name='forum_topic'),
63
+ path('forum/topic/create/', views.create_forum_topic_view, name='create_forum_topic'),
64
+ path('forum/topic/<int:topic_id>/edit/', views.edit_forum_topic_view, name='edit_forum_topic'),
65
+
66
+ # 10. Бронирование столов
67
+ path('tables/', views.tables_catalog_view, name='tables_catalog'),
68
+ path('tables/<int:table_id>/', views.table_detail_view, name='table_detail'),
69
+ path('reservations/', views.user_reservations_view, name='user_reservations'),
70
+ path('reservations/cancel/<int:reservation_id>/', views.cancel_reservation_view, name='cancel_reservation'),
71
+
72
+ # 11. Контакты
73
+ path('contacts/', views.contacts, name='contacts'),
74
+ ]
75
+
76
+ if settings.DEBUG:
77
+ urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
package/ekz/wsgi.py ADDED
@@ -0,0 +1,16 @@
1
+ """
2
+ WSGI config for ekz project.
3
+
4
+ It exposes the WSGI callable as a module-level variable named ``application``.
5
+
6
+ For more information on this file, see
7
+ https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
8
+ """
9
+
10
+ import os
11
+
12
+ from django.core.wsgi import get_wsgi_application
13
+
14
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ekz.settings')
15
+
16
+ application = get_wsgi_application()
File without changes
package/front/admin.py ADDED
@@ -0,0 +1,124 @@
1
+ from django.contrib import admin
2
+ from django.contrib.auth.admin import UserAdmin
3
+ from .models import (
4
+ CustomUser,
5
+ Category,
6
+ Product,
7
+ CartItem,
8
+ Favorite,
9
+ Order,
10
+ OrderItem,
11
+ Review,
12
+ Application,
13
+ News,
14
+ ForumTopic,
15
+ ForumComment,
16
+ Table,
17
+ TableReservation
18
+ )
19
+
20
+ class CustomUserAdmin(UserAdmin):
21
+ list_display = ('username', 'email', 'first_name', 'last_name', 'phone', 'is_staff')
22
+ search_fields = ('username', 'email', 'first_name', 'last_name', 'phone')
23
+ ordering = ('username',)
24
+
25
+ fieldsets = (
26
+ (None, {'fields': ('username', 'password')}),
27
+ ('Personal info', {'fields': ('first_name', 'last_name', 'email', 'phone')}),
28
+ ('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
29
+ ('Important dates', {'fields': ('last_login', 'date_joined')}),
30
+ ('Additional info', {'fields': ('address', 'age', 'birth_date', 'gender', 'city', 'country', 'occupation', 'avatar')}),
31
+ )
32
+
33
+ # Register CustomUser with a custom admin
34
+ admin.site.register(CustomUser, CustomUserAdmin)
35
+
36
+ # Register Category
37
+ @admin.register(Category)
38
+ class CategoryAdmin(admin.ModelAdmin):
39
+ list_display = ('name',)
40
+ search_fields = ('name',)
41
+
42
+ # Register Product
43
+ @admin.register(Product)
44
+ class ProductAdmin(admin.ModelAdmin):
45
+ list_display = ('name', 'category', 'price', 'created_at')
46
+ list_filter = ('category',)
47
+ search_fields = ('name', 'description')
48
+
49
+ # Register CartItem
50
+ @admin.register(CartItem)
51
+ class CartItemAdmin(admin.ModelAdmin):
52
+ list_display = ('user', 'product', 'quantity')
53
+ list_filter = ('user',)
54
+
55
+ # Register Favorite
56
+ @admin.register(Favorite)
57
+ class FavoriteAdmin(admin.ModelAdmin):
58
+ list_display = ('user', 'product')
59
+ list_filter = ('user',)
60
+
61
+ # Register Order
62
+ @admin.register(Order)
63
+ class OrderAdmin(admin.ModelAdmin):
64
+ list_display = ('user', 'status', 'total_amount', 'created_at')
65
+ list_filter = ('status', 'created_at')
66
+ search_fields = ('user__username', 'shipping_address')
67
+
68
+ # Register OrderItem
69
+ @admin.register(OrderItem)
70
+ class OrderItemAdmin(admin.ModelAdmin):
71
+ list_display = ('order', 'product', 'quantity', 'price')
72
+ list_filter = ('order',)
73
+
74
+ # Register Review
75
+ @admin.register(Review)
76
+ class ReviewAdmin(admin.ModelAdmin):
77
+ list_display = ('user', 'product', 'rating', 'created_at')
78
+ list_filter = ('rating', 'created_at')
79
+ search_fields = ('user__username', 'comment')
80
+
81
+ # Register Application
82
+ @admin.register(Application)
83
+ class ApplicationAdmin(admin.ModelAdmin):
84
+ list_display = ('user', 'title', 'status', 'created_at')
85
+ list_filter = ('status', 'created_at')
86
+ search_fields = ('user__username', 'title', 'description')
87
+
88
+ # Register News
89
+ @admin.register(News)
90
+ class NewsAdmin(admin.ModelAdmin):
91
+ list_display = ('title', 'created_at')
92
+ list_filter = ('created_at',)
93
+ search_fields = ('title', 'content')
94
+
95
+ # Register ForumTopic
96
+ @admin.register(ForumTopic)
97
+ class ForumTopicAdmin(admin.ModelAdmin):
98
+ list_display = ('title', 'author', 'created_at')
99
+ list_filter = ('created_at',)
100
+ search_fields = ('title', 'content', 'author__username')
101
+
102
+ # Register ForumComment
103
+ @admin.register(ForumComment)
104
+ class ForumCommentAdmin(admin.ModelAdmin):
105
+ list_display = ('topic', 'author', 'created_at')
106
+ list_filter = ('created_at',)
107
+ search_fields = ('content', 'author__username')
108
+
109
+ # Register Table
110
+ @admin.register(Table)
111
+ class TableAdmin(admin.ModelAdmin):
112
+ list_display = ('number', 'seats', 'location', 'status', 'price_per_hour')
113
+ list_filter = ('status', 'location')
114
+ search_fields = ('number', 'description')
115
+ list_editable = ('status', 'price_per_hour')
116
+
117
+ # Register TableReservation
118
+ @admin.register(TableReservation)
119
+ class TableReservationAdmin(admin.ModelAdmin):
120
+ list_display = ('id', 'table', 'user', 'start_time', 'end_time', 'guests_count', 'status')
121
+ list_filter = ('status', 'start_time')
122
+ search_fields = ('user__username', 'table__number', 'notes')
123
+ list_editable = ('status',)
124
+ readonly_fields = ('created_at',)
package/front/apps.py ADDED
@@ -0,0 +1,6 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class FrontConfig(AppConfig):
5
+ default_auto_field = 'django.db.models.BigAutoField'
6
+ name = 'front'
@@ -0,0 +1,51 @@
1
+ from django.contrib.auth.backends import ModelBackend
2
+ from django.contrib.auth import get_user_model
3
+ from django.db.models import Q
4
+
5
+ User = get_user_model()
6
+
7
+ class MultiFieldAuthBackend(ModelBackend):
8
+ def authenticate(self, request, username=None, password=None, **kwargs):
9
+ # Если в kwargs есть email или phone, используем их вместо username
10
+ if 'email' in kwargs:
11
+ username = kwargs.get('email')
12
+ field = 'email'
13
+ elif 'phone' in kwargs:
14
+ username = kwargs.get('phone')
15
+ field = 'phone'
16
+ else:
17
+ field = 'username'
18
+
19
+ if username is None or password is None:
20
+ return None
21
+
22
+ try:
23
+ # Строим запрос на основе используемого поля
24
+ if field == 'phone':
25
+ # Нормализация телефона (удаление пробелов, скобок, дефисов)
26
+ clean_phone = ''.join(c for c in username if c.isdigit() or c == '+')
27
+ user = User.objects.get(phone=clean_phone)
28
+ elif field == 'email':
29
+ user = User.objects.get(email__iexact=username)
30
+ else:
31
+ # Если это обычный логин или запрос с неизвестного поля,
32
+ # пробуем найти по всем полям
33
+ user = User.objects.get(
34
+ Q(phone=username) |
35
+ Q(email__iexact=username) |
36
+ Q(username=username)
37
+ )
38
+
39
+ if user.check_password(password):
40
+ return user
41
+ except User.DoesNotExist:
42
+ return None
43
+ except User.MultipleObjectsReturned:
44
+ # Если найдено несколько пользователей, возвращаем None для безопасности
45
+ return None
46
+
47
+ def get_user(self, user_id):
48
+ try:
49
+ return User.objects.get(pk=user_id)
50
+ except User.DoesNotExist:
51
+ return None