From daf734cafb34635cdbc18a15f9d2e70edadaadf9 Mon Sep 17 00:00:00 2001 From: ack Date: Wed, 21 Jan 2026 01:46:12 +0300 Subject: [PATCH] Add another --- Dockerfile | 22 ++++ core/__init__.py | 0 core/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 141 bytes core/__pycache__/settings.cpython-311.pyc | Bin 0 -> 2529 bytes core/__pycache__/urls.cpython-311.pyc | Bin 0 -> 1127 bytes core/__pycache__/wsgi.cpython-311.pyc | Bin 0 -> 656 bytes core/asgi.py | 16 +++ core/settings.py | 123 ++++++++++++++++++ core/urls.py | 23 ++++ core/wsgi.py | 16 +++ db.sqlite3 | Bin 0 -> 135168 bytes docker-compose.yml | 11 ++ manage.py | 22 ++++ products/__init__.py | 0 products/__pycache__/__init__.cpython-311.pyc | Bin 0 -> 145 bytes products/__pycache__/admin.cpython-311.pyc | Bin 0 -> 639 bytes products/__pycache__/apps.cpython-311.pyc | Bin 0 -> 520 bytes products/__pycache__/models.cpython-311.pyc | Bin 0 -> 974 bytes products/__pycache__/urls.cpython-311.pyc | Bin 0 -> 343 bytes products/__pycache__/views.cpython-311.pyc | Bin 0 -> 590 bytes products/admin.py | 6 + products/apps.py | 6 + products/migrations/0001_initial.py | 23 ++++ products/migrations/__init__.py | 0 .../__pycache__/0001_initial.cpython-311.pyc | Bin 0 -> 1201 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 0 -> 156 bytes products/models.py | 9 ++ products/templates/products/list.html | 8 ++ products/tests.py | 3 + products/urls.py | 6 + products/views.py | 6 + requirements.txt | Bin 0 -> 134 bytes 32 files changed, 300 insertions(+) create mode 100644 Dockerfile create mode 100644 core/__init__.py create mode 100644 core/__pycache__/__init__.cpython-311.pyc create mode 100644 core/__pycache__/settings.cpython-311.pyc create mode 100644 core/__pycache__/urls.cpython-311.pyc create mode 100644 core/__pycache__/wsgi.cpython-311.pyc create mode 100644 core/asgi.py create mode 100644 core/settings.py create mode 100644 core/urls.py create mode 100644 core/wsgi.py create mode 100644 db.sqlite3 create mode 100644 docker-compose.yml create mode 100644 manage.py create mode 100644 products/__init__.py create mode 100644 products/__pycache__/__init__.cpython-311.pyc create mode 100644 products/__pycache__/admin.cpython-311.pyc create mode 100644 products/__pycache__/apps.cpython-311.pyc create mode 100644 products/__pycache__/models.cpython-311.pyc create mode 100644 products/__pycache__/urls.cpython-311.pyc create mode 100644 products/__pycache__/views.cpython-311.pyc create mode 100644 products/admin.py create mode 100644 products/apps.py create mode 100644 products/migrations/0001_initial.py create mode 100644 products/migrations/__init__.py create mode 100644 products/migrations/__pycache__/0001_initial.cpython-311.pyc create mode 100644 products/migrations/__pycache__/__init__.cpython-311.pyc create mode 100644 products/models.py create mode 100644 products/templates/products/list.html create mode 100644 products/tests.py create mode 100644 products/urls.py create mode 100644 products/views.py create mode 100644 requirements.txt diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..82be43b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +# Используем легкий образ Python +FROM python:3.11-slim + +# Устанавливаем рабочую директорию внутри контейнера +WORKDIR /app + +# Запрещаем Python писать файлы .pyc и включаем небуферизованный вывод (полезно для логов) +ENV PYTHONDONTWRITEBYTECODE 1 +ENV PYTHONUNBUFFERED 1 + +# Устанавливаем зависимости системы (нужны для сборки некоторых пакетов) +RUN apt-get update && apt-get install -y --no-install-recommends gcc libpq-dev && rm -rf /var/lib/apt/lists/* + +# Копируем и устанавливаем зависимости Python +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Копируем весь проект в контейнер +COPY . . + +# Команда для запуска (пока простая) +CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] \ No newline at end of file diff --git a/core/__init__.py b/core/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/core/__pycache__/__init__.cpython-311.pyc b/core/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..707bd8209402f4f5e3aba48edabd845c7867e71e GIT binary patch literal 141 zcmZ3^%ge<81lB+EGePuY5CH>>P{wCAAY(d13PUi1CZpd4BO~Jn L1{hJq3={(Z&PpCM literal 0 HcmV?d00001 diff --git a/core/__pycache__/settings.cpython-311.pyc b/core/__pycache__/settings.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f485ab427931869812ed8579cc07a2034d4eff99 GIT binary patch literal 2529 zcmb7G&2JM&6rc6?cO2u80BvPNAxdc0rGyV5l(Mlm!NRfKtV7xr(rV+GI1~26*$+Z| z^0AdT^wu6YR2-`-+S}sy;=X9PA3pN z&;HTrA1Q?X^cKS>GMK#m3no7xj6{SP98efFAO;u|KqNqdFByb>gqDKwmozF)%P z*JH+RcsMh}QC%y*uy!c8qYC*9ypzO^ zWp&Iu#Uj>QCfj#1456i~MWPh}v1sWX+A@p7aEpC-YljrJZAB?4)U*ov_Q`f+4TB>> zjlvUIv5EPAd>LeW#L?g0Y0fcDs3BWB-Q__VsAiIuZIFeIt!jIh7A5=UWjepOaPRis zo@#e)J>9pqT33`EO*&8)?aLRR;Kl2==%W^Xh}u!0+=l%IorvrSpK(}Aq{N8&^=*_Lg^I<8i{b&?WuPoWmM-c0~=FrN!J z5x%xssqs#z#;x%NT=l4Xe=KUh4mz@F?&}7Y;9j8EcgJp+#NaHi5p9bIRHcgSmG{HG zhHiA1J``zcxHdQKL?sC>W=V3Q9k~7!x@80*wN6Zuyeq@w z8^qL=C&Y<#;EvENC$`K9ym!n_Lf}j5d{cVBf8&J9{PM=Cljf?``X*nN?$?E;;AAQ_ zp$RNtKy3(4Vy#jxSNTnDop(~}^?Fm2{!iSx?H ziI=%1=eZS}8E&I_UutlIuvuR(OAonf1%!2|zI2tVt!{9uyi}@}c>t`e@se1Fl8J3V zz?EyaYfi+QHARTL3CJbSyOS&PE8Ir4DFJd_TB-2W@-OJE_fdFPDBpQhCLKjTDEs~S z$gAc@!*3MZId~Vl3wgB_vSiGHf%iAU4xW zkA1iFZ0Yyp#ov+_UneiU@y7g{n~3ECE*g?v#?8kv z9%Dd2JCCv#dMP)C@;q~x%^l`vj#32|g)U`ANHCI5xbb8-;v$a()9FAj?tX&uS6`tl zI1XnHbL?Su=Eu9Qv$JkEm<2_T1jD}Kc@&>`l@;A!0E}b)qA|MoYIL#QUrePx3c&u| pD`;}2mp)2O_Top$iC*joHWzVIC^HSgC(zj&uTZW(jLVSDe*wE$L)-uW literal 0 HcmV?d00001 diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..204864629687a6fe19bfa3afc2185df4a9d22b59 GIT binary patch literal 1127 zcmb7D&ui2`6rN<0-EEd_#ghjQBcXw}svcf^V`3tfHW^$uRr!z3+YBo0-q;wuNB4{=uS;HH5yY zKhJ&NJrEl2GvLPieOYRpc5UTukcPs zfiz(@N&Q5FFYr#suegEUYm&wbWH*ENkZiqr{uGBS?MH(#4`jqr+-DpjoZ^hL5e=nd zSucka?~Hkz1yWL;iX9wBLSoLwk_rqI0!xP9MD(q2@CM{3DnCkrDw&dIF%1O8f>O`I zFosfQ!gF21LgA26kPcW?E@X*IQ+M52b0y27P`C>0LV4j@kKY9ea0$=a7^h*Ow#sn5}fS$L6()lsmubuR^pWdWnji3q=MPuN~g10`Wmu?uHrOE z=)I0wcWmoX90+lH7mSe^*1xG>a!9!n;uMN2IZuG=f7B?v69`|Ctk}OP+DyZEOrmrE zO(^OqYifI|{%jVF!5{^;M`7uTjr(OQy=l9q+u^8&S0YR7YSEN`R=XRsfeQ_+Ds@z# z;O*G9^<5oLTg%OWBvESXxuH6qH%jz=y@S~~sHGpQqU?x1^k<7oZZ uJAQCxES?*S7e*68*AKT2w~qX?_R@KK>C9L@H{RPw;svpl3t6v*0z18`}^!Vow>-3zn1T!x^% zPMj80*3Ty1QLEm-Jt_Ju#(kL?H={Vs4#J*s<0kVyvU9?kKS{NBZVWJ zNOH{SV@^ku<585c`H_ecN^rLur735TqGdp6%H?T7g$_~}E2=dUv8ojFVi+3!Fw7mP@_P#v z{yfQIX0Bn$i&TtQCPnUMP%Des(b*p}Tf*na`3>Al$i literal 0 HcmV?d00001 diff --git a/core/asgi.py b/core/asgi.py new file mode 100644 index 0000000..e36e2c8 --- /dev/null +++ b/core/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for core 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/5.2/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings') + +application = get_asgi_application() diff --git a/core/settings.py b/core/settings.py new file mode 100644 index 0000000..12ba9d6 --- /dev/null +++ b/core/settings.py @@ -0,0 +1,123 @@ +""" +Django settings for core project. + +Generated by 'django-admin startproject' using Django 5.2.10. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/5.2/ref/settings/ +""" + +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/5.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-pumnq#4_u6%i*4-@8qqmup7xwtbc&lhn_ym4u%!vd437i$k+-o' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'products', +] + +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 = 'core.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'core.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/5.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/5.2/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/5.2/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/5.2/howto/static-files/ + +STATIC_URL = 'static/' + +# Default primary key field type +# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' diff --git a/core/urls.py b/core/urls.py new file mode 100644 index 0000000..66a668f --- /dev/null +++ b/core/urls.py @@ -0,0 +1,23 @@ +""" +URL configuration for core project. + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/5.2/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 + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('products.urls')), # Главная страница теперь ведет в products +] diff --git a/core/wsgi.py b/core/wsgi.py new file mode 100644 index 0000000..050d8bc --- /dev/null +++ b/core/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for core project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/5.2/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings') + +application = get_wsgi_application() diff --git a/db.sqlite3 b/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..a313d8fcf1f7297e5f2e18c43a8de1de17727458 GIT binary patch literal 135168 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%0Dr7gCTQ-GkX`vPstzhga7BTij%2S~=C70_I zNwz4Nnzl?-TJ_V2<%P0VQVF7t@B^X!z24Mu&c?1#)w>0aSd)q(_T-j}&gu7Dq1J5Q z`qVz&n@Di?V@CaUTyL0p$68mHn(r{$RWoRK>3VE+93{+lXN{RqH_npe!qw%_?Qm}t z*x5b;%BC*WwU4yZ?p?GzmLS>qWAFY zKaF?pd+BCu{e^zsn@n=|pEVj3yNa-h(LSrKgSzoBWZL5H(%`zf*i{2$o_2OLQPZ6r zNB=L!>UDdscXX7SV_^03WmUbqq?R(OWzo@w(6aFqJqAycl7adh$9vD7<<=GEGrORa z@@2WG4Yi|$YL|J(j=?*AFr@9z8hzJtBrBI5vx z_BS0Lbo{CP&$<7$y~X`8G2GRsen{lKHv?Qf!LrtRLZqs)&TLs-UDPV7%<|w$Boh^* zQK{WzSWl?v0|nYQb}irNaBMfEX&2MJNMB<#$a@0;Zv7c^Vn>(NUbe4mN=G-Pj+?>U zQP+$#P1u~cHT98@L|D_FM6LLJHFdRS?$a>K?9wOjY^c{e9oQ`S+pb&=wJ-bXQ)gL+ z+4?k#da+W@E@f(DNI_%9x@_qSvToj0E^F&_)nY}-R6!$bHBucb%M1=9EzA5Mx%!+Af0~jjQ;VL z-#*4~*_GF=U&55JeXuBY+m%N;Q1#xi2kFM^Mv1s#y@gxwBqo+#Ix!Odad*>^op$SA zYzu)5!SFwXAsC+alOb!dM!&#A8G&3@$s}{;67&@^2V+$6nk{J=7Zlb-qktJI?|={ z$TRm->gQ~8A$_mg4;yI3Y;?E>P3IdzrTyq>>n;e?FCXWNoUlS}P6J-8Tp71INr`Ep=H+wy2fp(23Sq$xI{~R?|wt}r?@Eu;I{ zT%x6fKk)L;A7S@A?>}p92`#BsMQ`ic23qF3Y5?W*f|{wZ5ekjFy~agRUtLibNhfM^ zfQ)E4Ug^-0a!Jk=l)T?pB{xL{GCs+-RH|xuGHRrChZ(8H$#G%+b$U9ksLBgBBCnUkZA6$*rH= zsrI(u8LTTH3_Qd8`Q$qj$t`Zt31Ogxc0w4eaAOHd& z00JNY0w4eaj}!qs|36aI1+gFi0w4eaAOHd&00JNY0w4eaAh0U}c>doNHWUH@5C8!X z009sH0T2KI5C8!X0D(t}0Db0U{C*009sH0T2KI5C8!X009sH0T2KILcr;8adwBp z<)YvJ&kIX7;oHJL2wxQbMEJPy0kVh>2!H?xfB*=900@8p2!H?xfB*=9z>i8`kayaS z9cliOn*RS_FI}nsEL>Ip|45J1HgZD$Wscg~qFOc0_dA`op&|M+0rV#g+zztjrAzGF z{SVs7;xJt_euv-y=d^i`v7a#^KN+KzYLzwm{BIXlZNlqhf)5CQ00@8p2!H?xfB*=9 z00@8p2!OytC2+y+vI%3ZQO=bVH$J@a`HfF)y!yt6-l%VUX5+P=eaWw6vuf6V&iB%L z-}@pj2F2)DFf=9xeWG|S6gn4)oRK1NF&KW1BVIc;CEpWAqSTMyyz znM5KO3dKy{|0g`u0O1S-KmY_l00ck)1V8`;KmY_l00cnbr-lH1{^x|R*~njfKmY_l z00ck)1V8`;KmY_l00ck)1Rg;GCmh#Yg|)=OYFW&!lod6i-dVl3l!=AQ)lg1dR${sA zy~gwZH*CT;9>D-183aH81V8`;KmY_l00ck)1V8`;KtLyO%#n08-XIXif|C9Qffzg^ Jg{62R@_!t3FKz$; literal 0 HcmV?d00001 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..198934e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +version: '3.8' + +services: + web: + build: . + volumes: + - .:/app + ports: + - "8080:8000" + environment: + - DEBUG=1 \ No newline at end of file diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..f2a662c --- /dev/null +++ b/manage.py @@ -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', 'core.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() diff --git a/products/__init__.py b/products/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/products/__pycache__/__init__.cpython-311.pyc b/products/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8cdfb374aba18ae88d3c97a42d967e28574c2ac7 GIT binary patch literal 145 zcmZ3^%ge<81inA>GePuY5CH>>P{wCAAY(d13PUi1CZpdM`O=Uzn8rSJjle1nMC z_$Ue%vXvkfc9B?V}^2x}njb;g4g9H}^xRyYd35#+uT^T>yF}VmAI$kJs zF;;#{YWqU^?UU|7t)NSsn+WH+%y~$a0%KP=KRfq=aikLXNtX*hi36{93nSCX*J@+4 z*^qG%^%|#MryVuptk0yGwqK8X${}8=%&?Lwss8VJsn+{@W~u3%bx?Ekq)3z1TT!R0 z{9|QCrfup=28lA$)Fma`)Q(iTyl>p;2eVRBCR3VjhODpBR`#E5HBZotEV&>xWQh0- zD-VD7Gb}y)-7h%RpSxVXavpKv2^WSI;`$K&tE-Kt>e`11d>Zw^z*_vzPaFFI(G;2q literal 0 HcmV?d00001 diff --git a/products/__pycache__/apps.cpython-311.pyc b/products/__pycache__/apps.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c3292d3d11cba29c24f52ad8aacdf70c9b81a469 GIT binary patch literal 520 zcmZutze~eF6n>YaQu_-LEOZcb%#v9|glf=1EP|7vaKyfAiClYU(hPO#;2+>t@DEVL zf2L!}>f~0bi=DhnQbF|H-MjDI`|f*p@3~qnfwJ>25j?8>O$RG0xPi@E|6VBir1b(eT1 z8lHuw(y)@+MJO=t45LipZX0j>K~Fe%?eqmQ9yv!ruNe=;Nx(QJMVZrEb|EQJI`I39 z(xgPGV#i$L3Z=KP&-2VCvaTQVA@!98?WQ7@&b`1wKXAF@?zdegxfr==<@TyV+m|wO zVRglA*=ADC|DuIL-M&n!qESk$DYPseWKTZ~ lH&m#*7M&?KHwhs#*q#2K^EHFi=kV7(Tz%-%&wo;Bv2TaDfwuqv literal 0 HcmV?d00001 diff --git a/products/__pycache__/models.cpython-311.pyc b/products/__pycache__/models.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d62b39d8220ef306a53bea6ff9e51048a3f60d92 GIT binary patch literal 974 zcmZuvJ#5oJ6u$FM{%p7WETE#cV!}%Y1_UT#A%uapAR&QjRXW_2i`jFE!wBC2d6sxn+tP6E0rLc4M#;;2-6h-`fbOB+X- zdO(>UR>tnwq$%2Rxs4cdFh!1{Ag0!|6ClM@*;BhR&2E~?(PK;|#b{KgnZ4{k6tXcY zm!fie`K~N;SB^xSJS}V@r$7x!)r_(actBf~=J2<4x6Vi<-im$kS$vfGt2h(~wh|TU z?hE3x^=fl1GM_QN5`>JbyLC2%UJij{3sQ=%IFLd6wwi=cuj)0!Xo9keS9g8V@ZAav zIY3($;NOUY-s{;b;*0oX+ca^nbK?zQ7eZZaG?+ZUwIOmB zjv(ctZA3W|mrY1iAVi+k@|m2QggkAzJ`f><1K%ird(Gu#kNK2Oz}hS&Er_=wy}`W- ziwb2waGS|i<~j4KYfXMuqCX&hP8tqHb9gYZf^$Pps&@JfjH%AGzA^PK6gTb(W4>q1 z_l@~>X<*KD%6)TY=jx&RttQN+p1IUFm)ds*)^z7l-B09_J)|06Af UW&YEuv%2N~fc>BUamMNX06f_CNB{r; literal 0 HcmV?d00001 diff --git a/products/__pycache__/urls.cpython-311.pyc b/products/__pycache__/urls.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9b330d2bc898128cfab702b6553107d18bbc7782 GIT binary patch literal 343 zcmZ3^%ge<81i^pvGh2c5V-N=hSfPy1HbBO7h7^Vr#vF!R#wbQch7_h0<{YM6<|t-H z1}277#uS!R<`mX7Y|EG#7*+!@1f(-Yv81pEGiY+W1PN#|-eM_8EXjDu2;uM)6y>Ls zCYQwLWEPj)VkiRH2U3%ln49XS$$E=BB`Yy6JzuZ1D5tmxWaur{vdq--Vz9zn+(2QV zX(g#edBrOkJ_Ds0ekr(E#kiyvYat=LrjF?O&;MIu;n6>(~HQ^BniM0M+Y}or;4~Z z`X@N1Qm`C2Ik^?OiGwfE6a^o5-@WhMz4v{|Z6-4e7&D)~`-JCPNa8SllKwO%*Fb?1 z4jw5J0@R=;H$1a!Vs2eP*`kRpaFXv~i$io$umj4(JNc%mP2tllPqyuR$IhRZUejY&vq5&@ zVeXLyi^X=j)Jc~DtJKE^Sa%Y7ltxkox$g^AZ73Oe)Je~$jLYa7BAGi7BiJHrgpZ+R nyl!x|BF2%1KUl6I^h`oX7p8*0s|(rS@9J3wStULAA0weJWoL*` literal 0 HcmV?d00001 diff --git a/products/admin.py b/products/admin.py new file mode 100644 index 0000000..ac78e51 --- /dev/null +++ b/products/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from .models import Product + +@admin.register(Product) +class ProductAdmin(admin.ModelAdmin): + list_display = ('name', 'price', 'weight') \ No newline at end of file diff --git a/products/apps.py b/products/apps.py new file mode 100644 index 0000000..145a2ac --- /dev/null +++ b/products/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class ProductsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'products' diff --git a/products/migrations/0001_initial.py b/products/migrations/0001_initial.py new file mode 100644 index 0000000..121b3ca --- /dev/null +++ b/products/migrations/0001_initial.py @@ -0,0 +1,23 @@ +# Generated by Django 5.2.10 on 2026-01-20 21:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Product', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255, verbose_name='Название')), + ('price', models.DecimalField(decimal_places=2, max_digits=10, verbose_name='Цена')), + ('weight', models.FloatField(verbose_name='Вес (кг)')), + ], + ), + ] diff --git a/products/migrations/__init__.py b/products/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/products/migrations/__pycache__/0001_initial.cpython-311.pyc b/products/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f4e2513c1d143955afa04e3e03b57b3613ebd9af GIT binary patch literal 1201 zcmZuvO>7fK6rNeHH{OkH>@;9(OMukyvj}L~N*pSLM6nVP3Tl-KiN(@t@k}VX@G3%T@agzzD16^M{}=Qx)3V9g1sr`#5W3tY;ZT{{(`Gdpj;H}mHGeDj_b z3L1j(@V)17388<4G8x%1*t-DW2_lGK7qzj0+maz+B%wt_q~8(AP`s9zT zA}=F7yDN@$iEC}g_N~zIIssSO9-(f~n%ors>9Mjm0`LS;WMF~}iC`mRBSV%D&8{h9 z8wgG^ursxm+uy+i6PaWON?(RFV5MV4B2$T_I@uvPq7Jk^l>8jlzSVSMl~5w~NS+i( zad6<%qQF}zv72OzNO>^R$KVTAI#wiG9(?hse;XTlG7EGZ?QjX~PgDfC--Hy<&gqI!+99$uGhYS5_SA zlHj^t;5jo%*EG3in$QA0mjce4=C3`=6(xW+<#e17isX4hyR<`Sr{&PV7j4C-FDI;A z6V2m`7v}lz9s3gSwIE_}_42Car!e10(@!;R!S$?gjJ+-$_u(_N2Tst3ZyVn=8?@_s z>y0(5V|&eR`Yb{7zn*Q*&(D8tj*~mrUH3&VCPIMV1&EFP`KCCtu^7vER@wL=&LQ>a z11-uO8I@~q$_H8H^rJgb<@ApHdX5<;>-ek^3@brY30Nr{l`E{OZyt)O`qnaAyveG@ zuxdnAgOzTL%7yv`&5!JaE{zgC{I{UOZ`%qCAP-_ zeaKx%AMm1o5>(Or!3_{`24fs62rxp<^SrMb7_;NAb6CUHLk7%EMZ literal 0 HcmV?d00001 diff --git a/products/migrations/__pycache__/__init__.cpython-311.pyc b/products/migrations/__pycache__/__init__.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..46fe1dd70025d65d4d416d4ebf44f298690651f2 GIT binary patch literal 156 zcmZ3^%ge<81inA>GePuY5CH>>P{wCAAY(d13PUi1CZpdСписок товаров +
    +{% for p in products %} +
  • {{ p.name }} — Цена: {{ p.price }} руб. ({{ p.weight }} кг)
  • +{% empty %} +
  • Товаров пока нет.
  • +{% endfor %} +
\ No newline at end of file diff --git a/products/tests.py b/products/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/products/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/products/urls.py b/products/urls.py new file mode 100644 index 0000000..dad2ee9 --- /dev/null +++ b/products/urls.py @@ -0,0 +1,6 @@ +from django.urls import path +from .views import product_list + +urlpatterns = [ + path('', product_list, name='product_list'), +] \ No newline at end of file diff --git a/products/views.py b/products/views.py new file mode 100644 index 0000000..5ba0d4b --- /dev/null +++ b/products/views.py @@ -0,0 +1,6 @@ +from django.shortcuts import render +from .models import Product + +def product_list(request): + items = Product.objects.all() + return render(request, 'products/list.html', {'products': items}) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..efec9629b603fcc78e6683eb006f8b5c71577720 GIT binary patch literal 134 zcmXAiOAbIl5Cv;3aTQ@EmUb>8F@%WEuyT03X?f{YRjS{o<78wa5*TPSPeG*>l;mWz q%yg`>HsiI3Gw0_g2MfELs8%qi6i;4lg^QbB{L-ZlPGx7@8~*_InG?