first django
parent
eb4465fbf4
commit
18cc739291
@ -0,0 +1,9 @@
|
|||||||
|
services:
|
||||||
|
web:
|
||||||
|
build:
|
||||||
|
context: app
|
||||||
|
target: dev-envs
|
||||||
|
ports:
|
||||||
|
- '8090:8090'
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
.vercel
|
||||||
|
*.pyc
|
||||||
|
__pycache__
|
||||||
|
db.sqlite3
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.idea/
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"liveServer.settings.port": 8000,
|
||||||
|
"liveServer.settings.donotShowInfoMsg": true,
|
||||||
|
"liveServer.settings.AdvanceCustomBrowserCmdLine": "",
|
||||||
|
"liveServer.settings.root": "/",
|
||||||
|
"liveServer.settings.host": "localhost",
|
||||||
|
// "liveServer.settings.https": {
|
||||||
|
// "enable": true,
|
||||||
|
// "cert": "/Users/16716942/SOFTWARRIOR/TemaBot2/app/certs/localhost.crt",
|
||||||
|
// "key": "/Users/16716942/SOFTWARRIOR/TemaBot2/app/certs/localhost.key",
|
||||||
|
// "passphrase": ""
|
||||||
|
// }
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
# syntax=docker/dockerfile:1.4
|
||||||
|
|
||||||
|
FROM --platform=linux/arm64/v8 python:3.12 AS builder
|
||||||
|
EXPOSE 8080
|
||||||
|
WORKDIR /app
|
||||||
|
COPY requirements.txt /app
|
||||||
|
RUN pip3 install -r requirements.txt --no-cache-dir
|
||||||
|
COPY . /app
|
||||||
|
ENTRYPOINT ["python3"]
|
||||||
|
CMD ["manage.py", "runserver", "0.0.0.0:8080"]
|
||||||
|
|
||||||
|
FROM builder as dev-envs
|
||||||
|
RUN <<EOF
|
||||||
|
apk update
|
||||||
|
apk add git
|
||||||
|
EOF
|
||||||
|
|
||||||
|
RUN <<EOF
|
||||||
|
addgroup -S docker
|
||||||
|
adduser -S --shell /bin/bash --ingroup docker vscode
|
||||||
|
EOF
|
||||||
|
# install Docker tools (cli, buildx, compose)
|
||||||
|
COPY --from=gloursdocker/docker / /
|
||||||
|
CMD ["manage.py", "runserver", "0.0.0.0:8080"]
|
||||||
@ -0,0 +1,123 @@
|
|||||||
|
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fexamples%2Ftree%2Fmain%2Fpython%2Fdjango&demo-title=Django%20%2B%20Vercel&demo-description=Use%20Django%204%20on%20Vercel%20with%20Serverless%20Functions%20using%20the%20Python%20Runtime.&demo-url=https%3A%2F%2Fdjango-template.vercel.app%2F&demo-image=https://assets.vercel.com/image/upload/v1669994241/random/django.png)
|
||||||
|
|
||||||
|
# Django and Vercel
|
||||||
|
|
||||||
|
This example shows how to use Django 4 on Vercel with Serverless Functions using the [Python Runtime](https://vercel.com/docs/concepts/functions/serverless-functions/runtimes/python).
|
||||||
|
Version 1.0.0
|
||||||
|
|
||||||
|
## Demo5
|
||||||
|
|
||||||
|
https://django-template.vercel.app/
|
||||||
|
|
||||||
|
## How it Works
|
||||||
|
|
||||||
|
Our Django application, `example` is configured as an installed application in `vercel_app/settings.py`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# vercel_app/settings.py
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
# ...
|
||||||
|
'django_app',
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
We allow "\*.vercel.app" subdomains in `ALLOWED_HOSTS`, in addition to 127.0.0.1:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# vercel_app/settings.py
|
||||||
|
ALLOWED_HOSTS = ['127.0.0.1', '.vercel.app']
|
||||||
|
```
|
||||||
|
|
||||||
|
The `wsgi` module must use a public variable named `app` to expose the WSGI application:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# vercel_app/wsgi.py
|
||||||
|
app = get_wsgi_application()
|
||||||
|
```
|
||||||
|
|
||||||
|
The corresponding `WSGI_APPLICATION` setting is configured to use the `app` variable from the `vercel_app.wsgi` module:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# vercel_app/settings.py
|
||||||
|
WSGI_APPLICATION = 'vercel_app.wsgi.app'
|
||||||
|
```
|
||||||
|
|
||||||
|
There is a single view which renders the current time in `example/views.py`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# django_app/views.py
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from django.http import HttpResponse
|
||||||
|
|
||||||
|
|
||||||
|
def index(request):
|
||||||
|
now = datetime.now()
|
||||||
|
html = f'''
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>Hello from Vercel!</h1>
|
||||||
|
<p>The current time is { now }.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
'''
|
||||||
|
return HttpResponse(html)
|
||||||
|
```
|
||||||
|
|
||||||
|
This view is exposed a URL through `example/urls.py`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# django_app/urls.py
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from django_app.views import index
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('', index),
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, it's made accessible to the Django server inside `vercel_app/urls.py`:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# vercel_app/urls.py
|
||||||
|
from django.urls import path, include
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
...
|
||||||
|
path('', include('django_app.urls')),
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
This example uses the Web Server Gateway Interface (WSGI) with Django to enable handling requests on Vercel with Serverless Functions.
|
||||||
|
|
||||||
|
## Running Locally
|
||||||
|
|
||||||
|
```bash
|
||||||
|
|
||||||
|
python manage.py collectstatic
|
||||||
|
python manage.py runserver 8080
|
||||||
|
|
||||||
|
docker rmi -f <image_id>
|
||||||
|
|
||||||
|
docker compose down && docker compose build --no-cache && docker compose up
|
||||||
|
|
||||||
|
Docker: https://sematext.com/blog/docker-logs-location/
|
||||||
|
UI: https://docs.sencha.com/touch/2.3.1/#!/api
|
||||||
|
Localhost: https://letsencrypt.org/ru/docs/certificates-for-localhost/
|
||||||
|
|
||||||
|
|
||||||
|
ssh first@192.168.1.100
|
||||||
|
less +G /var/lib/docker/containers/<container_id>/<container_id>-json.log
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
https://c0.klipartz.com/pngpicture/54/511/gratis-png-meme-informacion-pegatina-telegrama-meme-thumbnail.png
|
||||||
|
|
||||||
|
Your Django application is now available at `http://localhost:8000`.
|
||||||
|
|
||||||
|
## One-Click Deploy
|
||||||
|
|
||||||
|
Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=vercel-examples):
|
||||||
|
|
||||||
|
[](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fexamples%2Ftree%2Fmain%2Fpython%2Fdjango&demo-title=Django%20%2B%20Vercel&demo-description=Use%20Django%204%20on%20Vercel%20with%20Serverless%20Functions%20using%20the%20Python%20Runtime.&demo-url=https%3A%2F%2Fdjango-template.vercel.app%2F&demo-image=https://assets.vercel.com/image/upload/v1669994241/random/django.png)
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
from .api import *
|
||||||
|
from .admin_api import *
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import psycopg2
|
import psycopg2
|
||||||
|
|
||||||
from const import DB_CONFIG
|
from consts import DB_CONFIG
|
||||||
|
|
||||||
def add_product_to_shop(
|
def add_product_to_shop(
|
||||||
name: str,
|
name: str,
|
||||||
@ -0,0 +1 @@
|
|||||||
|
from .const import *
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""Django's command-line utility for administrative tasks."""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Run administrative tasks."""
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.settings')
|
||||||
|
try:
|
||||||
|
from django.core.management import execute_from_command_line
|
||||||
|
except ImportError as exc:
|
||||||
|
raise ImportError(
|
||||||
|
"Couldn't import Django. Are you sure it's installed and "
|
||||||
|
"available on your PYTHONPATH environment variable? Did you "
|
||||||
|
"forget to activate a virtual environment?"
|
||||||
|
) from exc
|
||||||
|
execute_from_command_line(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
Django==5.2.7
|
||||||
|
aiohttp
|
||||||
|
requests
|
||||||
|
pytz
|
||||||
|
psycopg2-binary
|
||||||
|
bcrypt
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
# Register your models here.
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ExampleConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'server'
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
#from django.contrib import admin
|
||||||
|
from django.urls import path
|
||||||
|
|
||||||
|
from server.views import (get_shop, get_user, get_basket, get_history)
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path("shop/", get_shop, name="get_shop"),
|
||||||
|
path("user/", get_user, name="get_user"),
|
||||||
|
path("basket/", get_basket, name="get_basket"),
|
||||||
|
path("history/", get_history, name="get_history"),
|
||||||
|
]
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
import json
|
||||||
|
from django.http import JsonResponse
|
||||||
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
|
||||||
|
from api import get_products
|
||||||
|
from utils import decimal_to_float
|
||||||
|
|
||||||
|
@csrf_exempt
|
||||||
|
async def get_shop(request):
|
||||||
|
try:
|
||||||
|
products = None
|
||||||
|
if request.method == 'GET':
|
||||||
|
products = get_products()
|
||||||
|
user_agent = request.headers.get('User-Agent')
|
||||||
|
products = decimal_to_float(products)
|
||||||
|
print("get_shop", user_agent)
|
||||||
|
return JsonResponse({"OK": products}, status=200)
|
||||||
|
except Exception as error:
|
||||||
|
return JsonResponse({"ERROR": format(error)}, status=500)
|
||||||
|
|
||||||
|
@csrf_exempt
|
||||||
|
async def get_user(request):
|
||||||
|
try:
|
||||||
|
if request.method == 'POST':
|
||||||
|
body: dict = json.loads(request.body)
|
||||||
|
# TODO: вызвать API метод и вернуть JSON
|
||||||
|
print("get_user", body)
|
||||||
|
return JsonResponse({"OK": "JSON cleared"}, status=200)
|
||||||
|
except Exception as error:
|
||||||
|
return JsonResponse({"error": format(error)}, status=500)
|
||||||
|
|
||||||
|
@csrf_exempt
|
||||||
|
async def get_basket(request):
|
||||||
|
try:
|
||||||
|
if request.method == 'POST':
|
||||||
|
body: dict = json.loads(request.body)
|
||||||
|
# TODO: вызвать API метод и вернуть JSON
|
||||||
|
print("get_basket", body)
|
||||||
|
return JsonResponse({"OK": "JSON cleared"}, status=200)
|
||||||
|
except Exception as error:
|
||||||
|
return JsonResponse({"error": format(error)}, status=500)
|
||||||
|
|
||||||
|
@csrf_exempt
|
||||||
|
async def get_history(request):
|
||||||
|
try:
|
||||||
|
if request.method == 'POST':
|
||||||
|
body: dict = json.loads(request.body)
|
||||||
|
# TODO: вызвать API метод и вернуть JSON
|
||||||
|
print("get_history", body)
|
||||||
|
return JsonResponse({"OK": "JSON cleared"}, status=200)
|
||||||
|
except Exception as error:
|
||||||
|
return JsonResponse({"error": format(error)}, status=500)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
ASGI config for vercel_app project.
|
||||||
|
|
||||||
|
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.asgi import get_asgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.settings')
|
||||||
|
|
||||||
|
app = get_asgi_application()
|
||||||
@ -0,0 +1,125 @@
|
|||||||
|
"""
|
||||||
|
Django settings for vercel_app project.
|
||||||
|
|
||||||
|
Generated by 'django-admin startproject' using Django 4.1.3.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/4.1/topics/settings/
|
||||||
|
|
||||||
|
For the full list of settings and their values, see
|
||||||
|
https://docs.djangoproject.com/en/4.1/ref/settings/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
|
# Quick-start development settings - unsuitable for production
|
||||||
|
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/
|
||||||
|
|
||||||
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
|
SECRET_KEY = 'django-insecure-=cldztbc4jg&xl0!x673!*v2_=p$$eu)=7*f#d0#zs$44xx-h^'
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = True
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = ['localhost', '127.0.0.1', '192.168.1.100', 'game_shop.softwarrior.ru']
|
||||||
|
|
||||||
|
|
||||||
|
# Application definition
|
||||||
|
|
||||||
|
INSTALLED_APPS = [
|
||||||
|
'django.contrib.admin',
|
||||||
|
'django.contrib.auth',
|
||||||
|
'django.contrib.contenttypes',
|
||||||
|
'django.contrib.sessions',
|
||||||
|
'django.contrib.messages',
|
||||||
|
'django.contrib.staticfiles',
|
||||||
|
'server'
|
||||||
|
]
|
||||||
|
|
||||||
|
MIDDLEWARE = [
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
]
|
||||||
|
|
||||||
|
ROOT_URLCONF = 'settings.urls'
|
||||||
|
|
||||||
|
TEMPLATES = [
|
||||||
|
{
|
||||||
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
|
'DIRS': [BASE_DIR, 'templates'],
|
||||||
|
'APP_DIRS': True,
|
||||||
|
'OPTIONS': {
|
||||||
|
'context_processors': [
|
||||||
|
'django.template.context_processors.debug',
|
||||||
|
'django.template.context_processors.request',
|
||||||
|
'django.contrib.auth.context_processors.auth',
|
||||||
|
'django.contrib.messages.context_processors.messages',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
WSGI_APPLICATION = 'settings.wsgi.app'
|
||||||
|
|
||||||
|
|
||||||
|
# Database
|
||||||
|
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases
|
||||||
|
# Note: Django modules for using databases are not support in serverless
|
||||||
|
# environments like Vercel. You can use a database over HTTP, hosted elsewhere.
|
||||||
|
|
||||||
|
DATABASES = {}
|
||||||
|
|
||||||
|
|
||||||
|
# Password validation
|
||||||
|
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
AUTH_PASSWORD_VALIDATORS = [
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Internationalization
|
||||||
|
# https://docs.djangoproject.com/en/4.1/topics/i18n/
|
||||||
|
|
||||||
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
|
||||||
|
TIME_ZONE = 'UTC'
|
||||||
|
|
||||||
|
USE_I18N = True
|
||||||
|
|
||||||
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
|
# Static files (CSS, JavaScript, Images)
|
||||||
|
# https://docs.djangoproject.com/en/4.1/howto/static-files/
|
||||||
|
|
||||||
|
STATIC_URL = 'static/'
|
||||||
|
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
|
||||||
|
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)
|
||||||
|
|
||||||
|
|
||||||
|
# Default primary key field type
|
||||||
|
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
|
||||||
|
|
||||||
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
"""vercel_app URL Configuration
|
||||||
|
|
||||||
|
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||||
|
https://docs.djangoproject.com/en/4.1/topics/http/urls/
|
||||||
|
Examples:
|
||||||
|
Function views
|
||||||
|
1. Add an import: from my_app import views
|
||||||
|
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||||
|
Class-based views
|
||||||
|
1. Add an import: from other_app.views import Home
|
||||||
|
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||||
|
Including another URLconf
|
||||||
|
1. Import the include() function: from django.urls import include, path
|
||||||
|
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||||
|
"""
|
||||||
|
from django.contrib import admin
|
||||||
|
from django.urls import path, include, re_path
|
||||||
|
from django.views.static import serve
|
||||||
|
from settings import settings
|
||||||
|
|
||||||
|
static_urlpatterns = [
|
||||||
|
re_path(r"^static/(?P<path>.*)$", serve, {"document_root": settings.STATIC_ROOT}),
|
||||||
|
]
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('admin/', admin.site.urls),
|
||||||
|
path('', include('server.urls')),
|
||||||
|
path('bot/', include('server.urls')),
|
||||||
|
path("", include(static_urlpatterns)),
|
||||||
|
]
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
"""
|
||||||
|
WSGI config for vercel_app project.
|
||||||
|
|
||||||
|
It exposes the WSGI callable as a module-level variable named ``app``.
|
||||||
|
|
||||||
|
For more information on this file, see
|
||||||
|
https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from django.core.wsgi import get_wsgi_application
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.settings')
|
||||||
|
|
||||||
|
app = get_wsgi_application()
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
export const COMMANDS = [
|
||||||
|
{
|
||||||
|
name: 'Запустить',
|
||||||
|
uid: '1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Остановить',
|
||||||
|
uid: '2'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Применить',
|
||||||
|
uid: '3'
|
||||||
|
},
|
||||||
|
]
|
||||||
@ -0,0 +1,167 @@
|
|||||||
|
:root {
|
||||||
|
--color-menu-point1: #e8ecef;
|
||||||
|
--color-menu-point2: #1879da;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: lightgray;
|
||||||
|
padding: 0 10px 10px 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 2px solid var(--color-menu-point1);
|
||||||
|
background-color: var(--color-menu-point2);
|
||||||
|
color: var(--color-menu-point1);
|
||||||
|
padding: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
border-color: var(--color-menu-point2);
|
||||||
|
background-color: var(--color-menu-point1);
|
||||||
|
color: var(--color-menu-point2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider_hr {
|
||||||
|
width: 100%;
|
||||||
|
border-top: 0.5px solid var(--color-menu-point2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider_h3 {
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1;
|
||||||
|
padding-top: 100px;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 100px);
|
||||||
|
overflow: auto;
|
||||||
|
background-color: rgb(0,0,0);
|
||||||
|
background-color: rgba(0,0,0,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
background-color: #fefefe;
|
||||||
|
margin: auto;
|
||||||
|
padding: 20px;
|
||||||
|
border: 1px solid #888;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-text {
|
||||||
|
white-space: break-spaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-close {
|
||||||
|
color: #aaaaaa;
|
||||||
|
float: right;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-close:hover,
|
||||||
|
.modal-close:focus {
|
||||||
|
color: #000;
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 60px;
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch input {
|
||||||
|
opacity: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider {
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #807272;
|
||||||
|
-webkit-transition: .4s;
|
||||||
|
transition: .4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider:before {
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
height: 26px;
|
||||||
|
width: 26px;
|
||||||
|
left: 4px;
|
||||||
|
bottom: 4px;
|
||||||
|
background-color: white;
|
||||||
|
-webkit-transition: .4s;
|
||||||
|
transition: .4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked + .slider {
|
||||||
|
background-color: var(--color-menu-point2);
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus + .slider {
|
||||||
|
box-shadow: 0 0 1px var(--color-menu-point2);
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked + .slider:before {
|
||||||
|
-webkit-transform: translateX(26px);
|
||||||
|
-ms-transform: translateX(26px);
|
||||||
|
transform: translateX(26px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Rounded sliders */
|
||||||
|
.slider.round {
|
||||||
|
border-radius: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider.round:before {
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timeInput {
|
||||||
|
background-color: var(--color-menu-point1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.group {
|
||||||
|
display: flex;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.direction_column {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.direction_row {
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Настройка GameShop</title>
|
||||||
|
<link href="/static/index.css"rel="stylesheet"/>
|
||||||
|
<script defer src="/static/index.js" ></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id='root'></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -0,0 +1 @@
|
|||||||
|
from .type import *
|
||||||
@ -0,0 +1 @@
|
|||||||
|
from .utils import *
|
||||||
@ -1,31 +0,0 @@
|
|||||||
from api import *
|
|
||||||
from utils import *
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# products_json = get_products()
|
|
||||||
# print(json.dumps(products_json, ensure_ascii=False, indent=2))
|
|
||||||
#
|
|
||||||
# product1_json = get_product(1)
|
|
||||||
# print(json.dumps(product1_json, ensure_ascii=False, indent=2))
|
|
||||||
|
|
||||||
# try:
|
|
||||||
# # registration("Vasya1", "Vasya2005", "vasili_pupkin@gmail.com")
|
|
||||||
# token = login("vasili_pupkin@gmail.com", "Vasya2005")
|
|
||||||
# logout(token)
|
|
||||||
# print(check_token(token))
|
|
||||||
|
|
||||||
# token = login("stepan.pilipenko@xmail.ru", "sage123")
|
|
||||||
# registration("Petia", "Petia2005", "petia_pupkin@gmail.com")
|
|
||||||
# token = login("stepan.pilipenko@xmail.ru", "Vasya2005")
|
|
||||||
# print(get_basket(token))
|
|
||||||
# print(get_history(token))
|
|
||||||
|
|
||||||
token = login("vasili_pupkin@gmail.com", "Vasya2005")
|
|
||||||
# add_product_to_basket(token, 3)
|
|
||||||
# add_product_to_basket(token, 3)
|
|
||||||
# add_product_to_basket(token, 5)
|
|
||||||
# add_product_to_basket(token, 5)
|
|
||||||
add_money()
|
|
||||||
# buy_products(token)
|
|
||||||
# print(get_histories(token))
|
|
||||||
# unregister(token)
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
psycopg2-binary
|
|
||||||
bcrypt
|
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDDzCCAfegAwIBAgIUf2BJSySSLLnH0Ac5wA7I28/qnPcwDQYJKoZIhvcNAQEL
|
||||||
|
BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI0MDUwMzE5MTkyMFoXDTI0MDYw
|
||||||
|
MjE5MTkyMFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF
|
||||||
|
AAOCAQ8AMIIBCgKCAQEA4EUNokJK5XVV1sa6E3iGPqQBwCn5K02X4ktZ5hktg8bo
|
||||||
|
3dpcgdrmdP6KEB1vPwcEOBmMEasE1bI/ocCiwHGC/yY+C+z+T8YSw5WUBCSQgPEj
|
||||||
|
xcxNt/AI8r5DZGTcqXt/5M9pEywPy0mjgwCogbe0R8MIL98PLqT6Bt3fIN1v8bjN
|
||||||
|
XySH04N2WJ/YU4SXdeI8QUy+ET4cTV0U9xC49T7knpYK9I1zGHeYvd+E2AJCYnLU
|
||||||
|
841qxZAr0O/5Oi0jgiYoltQi+u7ejQaqJJfp2+XYsgHhKpMBdJbyhNuE8KIZLhgU
|
||||||
|
8kFRejEHBgYJq9X6OyQ6ZRQxsQ18GrUrFq0kf2qZWwIDAQABo1kwVzAUBgNVHREE
|
||||||
|
DTALgglsb2NhbGhvc3QwCwYDVR0PBAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMB
|
||||||
|
MB0GA1UdDgQWBBRD48TR9xtQIhaDMHuqbXqH9lsgfzANBgkqhkiG9w0BAQsFAAOC
|
||||||
|
AQEAAAGRN5NEzE2eKpn1clBbHpFB3sOnxRQ5efVafz0U0XSCqyLlYU9IibGdk3Yk
|
||||||
|
huaslxUFGtPPlzPbRjHYP3ST5pZpCOuH7Ze/8AOaeNu+DFxILjD04wAGV881JPSB
|
||||||
|
Sw3wrxk0hWMMwWTCTnsaDIeLOejhf86CB1gH3UdvZzcxGIanXtyb86wcnkj107+B
|
||||||
|
5Pv6Q8J0Thn2gMjisVqybdqrQi7tAtDURefyoPuRxgK2k6kgTBSMPXxRqWvq6Aem
|
||||||
|
ozxYrT7/QV0gKXjCNTmhFjEOOIGdN8h/Rmih7/TbcPpaEHcsVwG2w8eRKvJ2xrIk
|
||||||
|
dHL+Xn35P1jTwxwRq1vfLhEIkg==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDgRQ2iQkrldVXW
|
||||||
|
xroTeIY+pAHAKfkrTZfiS1nmGS2Dxujd2lyB2uZ0/ooQHW8/BwQ4GYwRqwTVsj+h
|
||||||
|
wKLAcYL/Jj4L7P5PxhLDlZQEJJCA8SPFzE238AjyvkNkZNype3/kz2kTLA/LSaOD
|
||||||
|
AKiBt7RHwwgv3w8upPoG3d8g3W/xuM1fJIfTg3ZYn9hThJd14jxBTL4RPhxNXRT3
|
||||||
|
ELj1PuSelgr0jXMYd5i934TYAkJictTzjWrFkCvQ7/k6LSOCJiiW1CL67t6NBqok
|
||||||
|
l+nb5diyAeEqkwF0lvKE24TwohkuGBTyQVF6MQcGBgmr1fo7JDplFDGxDXwatSsW
|
||||||
|
rSR/aplbAgMBAAECggEAAsPXLzDyC3Iu5L7+fE74GL2c5+mckNQcE0YqjZOx4/YH
|
||||||
|
2PRgP5mbTcX1nc0/Gd/URXzLJUyeeqP/9NaTKxw7KTonea4qVIF0qcSmVoa84VoX
|
||||||
|
vtCOBL6I3bVKz2oO7mf/Y6rK+NmKOE9oHK1dZnwFVP0qlKyDW2fdTUhe/+C7CJfg
|
||||||
|
x8KXNQ66cky5VaM+/Oqqaxs866XI9sjUr234YRarwgIwoP1hVrVfOaKJounbqHtS
|
||||||
|
HCwyWlvk1JkmGNEnPIH8HlkTPfh1Q1ifK3t8qKFfnj6ITarbZildsPJD9P/eN8E5
|
||||||
|
oujw0eUi1YOkWRI91ecCTVqvFNh35nRFF9fDchRygQKBgQDxCWqaPDfmQIQxRoaX
|
||||||
|
z2UkXZZfQ2I/CdmVT1TrgpMndyzYI1KC93VdDCDZlWMCEOyfN2qDg/bSbQFCWlUJ
|
||||||
|
m+fgZd2ovrtyx7AL4P808mVgR0+ZcW6+48ZI5TKs/UI+m/WBy+QMedPcObhx26CA
|
||||||
|
MqdyLw3nAU5u9M1beQ+F34XGQwKBgQDuMSxQjc+FoT38exDPcLyrmvMxiJDl9F7q
|
||||||
|
BzWGxp2HtgBxLRvI0E7tb0kJ2ZgZjq3xdbPYgYVUKkaSxDNU7/63nE6vw+ZbW42V
|
||||||
|
XBnt55c0GixnV9LQLv0Qz9Tp7RfdOZlDQ/azoLHY2XWOt08rac3TgHwD3YNALrkQ
|
||||||
|
NrDa30tLCQKBgFsCTC7qN80HZSJZ163wT+cYMxPLFIhqxq3ao1y9E6TeGZ+OTrRG
|
||||||
|
jRjR4IFnJ1f7XeyL9vqrVAGFyOjtxJf5NucCb1wskAg5n54MmS+7qk1c/5AXRVJs
|
||||||
|
HE0fxS+N/Ho5VsxoWLXhNf48CQlsfMCK37B8Vcp4Ms4wPm2gWx0YFaGTAoGBAN6i
|
||||||
|
9cHhm0xTV4YMXb0XqjJYZeIxvQZDsQfcbyqnsQztkGI5AJRmKLAD6egcC/AvjeR4
|
||||||
|
2P6QqdfuoAKFA1nr7VEf9+iQGlvgKmmmKdJWOt2HbWO3EiRnF0HEkUWJyFmOgfP+
|
||||||
|
rbRein2fXSNlsclpXurHWKOgRBMU2QQPqqUaO91JAoGBAM5EcSu1uZkMs2urRKJY
|
||||||
|
SDO0N13Dm1rY3t+nInrBk6j4AxEuwdF5k1lAevmEPRNKXSqh0JjInGPQij+Z3Brp
|
||||||
|
kLCubqZKTRmXkhMkI8p++d0aW5voSo4E1Fr4mWrK/WakMHMVcwVRyqTmmXYyY9v/
|
||||||
|
FMNjTyw8P7HAaUuhdazp/pzM
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
services:
|
||||||
|
web:
|
||||||
|
platform: linux/arm64/v8
|
||||||
|
image: firstsoftwarrior/game_shop
|
||||||
|
build:
|
||||||
|
context: app
|
||||||
|
target: builder
|
||||||
|
container_name: firstsoftwarrior-game_shop
|
||||||
|
ports:
|
||||||
|
- '8090:8090'
|
||||||
Loading…
Reference in New Issue