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.
- package/db.sqlite3 +0 -0
- package/ekz/__init__.py +0 -0
- package/ekz/__pycache__/__init__.cpython-312.pyc +0 -0
- package/ekz/__pycache__/__init__.cpython-313.pyc +0 -0
- package/ekz/__pycache__/settings.cpython-312.pyc +0 -0
- package/ekz/__pycache__/settings.cpython-313.pyc +0 -0
- package/ekz/__pycache__/urls.cpython-312.pyc +0 -0
- package/ekz/__pycache__/urls.cpython-313.pyc +0 -0
- package/ekz/__pycache__/wsgi.cpython-312.pyc +0 -0
- package/ekz/__pycache__/wsgi.cpython-313.pyc +0 -0
- package/ekz/asgi.py +16 -0
- package/ekz/settings.py +137 -0
- package/ekz/urls.py +77 -0
- package/ekz/wsgi.py +16 -0
- package/front/__init__.py +0 -0
- package/front/__pycache__/__init__.cpython-312.pyc +0 -0
- package/front/__pycache__/__init__.cpython-313.pyc +0 -0
- package/front/__pycache__/admin.cpython-312.pyc +0 -0
- package/front/__pycache__/admin.cpython-313.pyc +0 -0
- package/front/__pycache__/apps.cpython-312.pyc +0 -0
- package/front/__pycache__/apps.cpython-313.pyc +0 -0
- package/front/__pycache__/backends.cpython-312.pyc +0 -0
- package/front/__pycache__/backends.cpython-313.pyc +0 -0
- package/front/__pycache__/forms.cpython-312.pyc +0 -0
- package/front/__pycache__/forms.cpython-313.pyc +0 -0
- package/front/__pycache__/models.cpython-312.pyc +0 -0
- package/front/__pycache__/models.cpython-313.pyc +0 -0
- package/front/__pycache__/views.cpython-312.pyc +0 -0
- package/front/__pycache__/views.cpython-313.pyc +0 -0
- package/front/admin.py +124 -0
- package/front/apps.py +6 -0
- package/front/backends.py +51 -0
- package/front/forms.py +454 -0
- package/front/migrations/0001_initial.py +52 -0
- package/front/migrations/0002_customuser_avatar_alter_customuser_address_and_more.py +68 -0
- package/front/migrations/0003_alter_customuser_email_alter_customuser_first_name_and_more.py +34 -0
- package/front/migrations/0004_category_application_forumtopic_forumcomment_news_and_more.py +187 -0
- package/front/migrations/0005_table_tablereservation.py +52 -0
- package/front/migrations/0006_applicationreview.py +30 -0
- package/front/migrations/0007_alter_application_status.py +18 -0
- package/front/migrations/0008_application_category.py +19 -0
- package/front/migrations/__init__.py +0 -0
- package/front/migrations/__pycache__/0001_initial.cpython-312.pyc +0 -0
- package/front/migrations/__pycache__/0001_initial.cpython-313.pyc +0 -0
- package/front/migrations/__pycache__/0002_alter_customuser_options_customuser_education_and_more.cpython-312.pyc +0 -0
- package/front/migrations/__pycache__/0002_customuser_avatar_alter_customuser_address_and_more.cpython-312.pyc +0 -0
- package/front/migrations/__pycache__/0002_customuser_avatar_alter_customuser_address_and_more.cpython-313.pyc +0 -0
- package/front/migrations/__pycache__/0003_alter_customuser_email_alter_customuser_first_name_and_more.cpython-312.pyc +0 -0
- package/front/migrations/__pycache__/0003_alter_customuser_email_alter_customuser_first_name_and_more.cpython-313.pyc +0 -0
- package/front/migrations/__pycache__/0003_alter_customuser_options_alter_customuser_address_and_more.cpython-312.pyc +0 -0
- package/front/migrations/__pycache__/0004_alter_customuser_managers_and_more.cpython-312.pyc +0 -0
- package/front/migrations/__pycache__/0004_category_application_forumtopic_forumcomment_news_and_more.cpython-313.pyc +0 -0
- package/front/migrations/__pycache__/0005_table_tablereservation.cpython-313.pyc +0 -0
- package/front/migrations/__pycache__/0006_applicationreview.cpython-313.pyc +0 -0
- package/front/migrations/__pycache__/0007_alter_application_status.cpython-313.pyc +0 -0
- package/front/migrations/__pycache__/0008_application_category.cpython-313.pyc +0 -0
- package/front/migrations/__pycache__/__init__.cpython-312.pyc +0 -0
- package/front/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
- package/front/models.py +425 -0
- package/front/static/bootstrap-icons.css +2018 -0
- package/front/static/bootstrap.bundle.min.js +7 -0
- package/front/static/bootstrap.min.css +6 -0
- package/front/static/bootstrap.min.js +7 -0
- package/front/static/fonts/bootstrap-icons.woff +0 -0
- package/front/static/fonts/bootstrap-icons.woff2 +0 -0
- package/front/static/images/logo.png +0 -0
- package/front/static/styles.css +282 -0
- package/front/templates/admin/confirm_delete.html +39 -0
- package/front/templates/admin/dashboard.html +39 -0
- package/front/templates/admin/model_form.html +79 -0
- package/front/templates/admin/model_list.html +100 -0
- package/front/templates/base.html +42 -0
- package/front/templates/components/header.html +78 -0
- package/front/templates/components/login.html +120 -0
- package/front/templates/components/login_in_modal.html +193 -0
- package/front/templates/components/register.html +360 -0
- package/front/templates/components/register_in_modal.html +261 -0
- package/front/templates/pages/add_application_review.html +58 -0
- package/front/templates/pages/application_form.html +103 -0
- package/front/templates/pages/application_success.html +20 -0
- package/front/templates/pages/cancel_reservation.html +63 -0
- package/front/templates/pages/cart.html +91 -0
- package/front/templates/pages/catalog.html +93 -0
- package/front/templates/pages/checkout.html +70 -0
- package/front/templates/pages/contacts.html +67 -0
- package/front/templates/pages/create_forum_topic.html +43 -0
- package/front/templates/pages/edit_application.html +112 -0
- package/front/templates/pages/edit_forum_topic.html +45 -0
- package/front/templates/pages/favorites.html +43 -0
- package/front/templates/pages/forum_list.html +78 -0
- package/front/templates/pages/forum_topic.html +133 -0
- package/front/templates/pages/main_page.html +150 -0
- package/front/templates/pages/news_detail.html +38 -0
- package/front/templates/pages/news_list.html +36 -0
- package/front/templates/pages/order_detail.html +129 -0
- package/front/templates/pages/order_success.html +50 -0
- package/front/templates/pages/orders.html +54 -0
- package/front/templates/pages/product_detail.html +202 -0
- package/front/templates/pages/profile.html +214 -0
- package/front/templates/pages/reviews.html +89 -0
- package/front/templates/pages/table_detail.html +219 -0
- package/front/templates/pages/tables_catalog.html +91 -0
- package/front/templates/pages/user_applications.html +134 -0
- package/front/templates/pages/user_reservations.html +92 -0
- package/front/templatetags/__pycache__/admin_extras.cpython-313.pyc +0 -0
- package/front/templatetags/admin_extras.py +13 -0
- package/front/tests.py +3 -0
- package/front/views.py +1087 -0
- package/manage.py +22 -0
- package/media/avatars//320/260/320/270/314/206/321/201_/320/273/320/260/321/202/321/202/320/265.jpg +0 -0
- package/media/categories//320/260/320/270/314/206/321/201_/320/273/320/260/321/202/321/202/320/265.jpg +0 -0
- package/media/news/5de24294bad21ec99931f4c362354f22.jpg +0 -0
- package/media/news/alien-pictures-g3ywlhr5ik0fwdwg.jpg +0 -0
- package/media/products/d438c31d0caf10b0dc17a5fcb503a38e.jpg +0 -0
- package/package.json +12 -0
package/db.sqlite3
ADDED
|
Binary file
|
package/ekz/__init__.py
ADDED
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
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()
|
package/ekz/settings.py
ADDED
|
@@ -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
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
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,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
|