master
Lowlights 2024-01-24 16:16:47 +06:00
commit a86035d757
58 changed files with 1453 additions and 0 deletions

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

0
NITAKUSHOP/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

16
NITAKUSHOP/asgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
ASGI config for NITAKUSHOP 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.0/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'NITAKUSHOP.settings')
application = get_asgi_application()

127
NITAKUSHOP/settings.py Normal file
View File

@ -0,0 +1,127 @@
"""
Django settings for NITAKUSHOP project.
Generated by 'django-admin startproject' using Django 5.0.1.
For more information on this file, see
https://docs.djangoproject.com/en/5.0/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.0/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.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-&b24xw3mg)lbuo4pdea^cxgkoc!yace&t^o9*o#n=-_jhwe+x!'
# 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',
'main.apps.MainConfig',
]
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 = 'NITAKUSHOP.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 = 'NITAKUSHOP.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/5.0/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.0/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.0/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
MEDIA_URL = 'media/'
MEDIA_ROOT = BASE_DIR / 'media'

33
NITAKUSHOP/urls.py Normal file
View File

@ -0,0 +1,33 @@
"""
URL configuration for app project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.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
from main import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index, name='index'),
path('', include('main.urls', namespace='main')),
path('about/', views.about, name='about'),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

16
NITAKUSHOP/wsgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
WSGI config for NITAKUSHOP 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.0/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'NITAKUSHOP.settings')
application = get_wsgi_application()

BIN
db.sqlite3 Normal file

Binary file not shown.

0
main/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

13
main/admin.py Normal file
View File

@ -0,0 +1,13 @@
from django.contrib import admin
from .models import Category, Product
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ['name', 'slug']
prepopulated_fields = {'slug': ('name',)}
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ['name', 'slug', 'price','available', 'created', 'updated']
list_filter = ['available', 'created', 'updated']
list_editable = ['price', 'available']
prepopulated_fields = {'slug': ('name',)}

6
main/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class MainConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'main'

View File

@ -0,0 +1,62 @@
# Generated by Django 4.2.7 on 2024-01-24 10:15
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Category',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200)),
('slug', models.SlugField(max_length=200, unique=True)),
],
options={
'verbose_name': 'category',
'verbose_name_plural': 'categories',
'ordering': ['name'],
},
),
migrations.CreateModel(
name='Product',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200)),
('slug', models.SlugField(max_length=200)),
('image', models.ImageField(blank=True, upload_to='products/%Y/%m/%d')),
('description', models.TextField(blank=True)),
('price', models.DecimalField(decimal_places=2, max_digits=10)),
('available', models.BooleanField(default=True)),
('created', models.DateTimeField(auto_now_add=True)),
('updated', models.DateTimeField(auto_now=True)),
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='products', to='main.category')),
],
options={
'ordering': ['name'],
},
),
migrations.AddIndex(
model_name='category',
index=models.Index(fields=['name'], name='main_catego_name_5111b9_idx'),
),
migrations.AddIndex(
model_name='product',
index=models.Index(fields=['id', 'slug'], name='main_produc_id_f4bffc_idx'),
),
migrations.AddIndex(
model_name='product',
index=models.Index(fields=['name'], name='main_produc_name_168fc5_idx'),
),
migrations.AddIndex(
model_name='product',
index=models.Index(fields=['-created'], name='main_produc_created_4330ad_idx'),
),
]

View File

Binary file not shown.

52
main/models.py Normal file
View File

@ -0,0 +1,52 @@
from django.db import models
from django.urls import reverse
class Category(models.Model):
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=200,unique=True)
class Meta:
ordering = ['name']
indexes = [models.Index(fields=['name']),]
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('main:product_list_by_category',
args=[self.slug])
class Product(models.Model):
category = models.ForeignKey(Category,
related_name='products',
on_delete=models.CASCADE)
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=200)
image = models.ImageField(upload_to='products/%Y/%m/%d',
blank=True)
description = models.TextField(blank=True)
price = models.DecimalField(max_digits=10,
decimal_places=2)
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['name']
indexes = [
models.Index(fields=['id', 'slug']),
models.Index(fields=['name']),
models.Index(fields=['-created']),
]
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('main:product_detail',
args=[self.id, self.slug])

View File

@ -0,0 +1,47 @@
/* Стили для страницы about */
body {
background-image: url("../images/walp.jpg");
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center center;
background-size: cover;
height: 100%;
margin: 0;
padding: 0;
font-family: 'Arial', sans-serif;
}
.about-container {
background-color: rgba(107, 91, 149, 0.8);
color: #ffffff;
padding: 20px;
border-radius: 10px;
box-shadow: 5px 5px 25px 19px #380069;
margin: 50px auto;
max-width: 600px;
}
h2 {
color: #ffa07a;
}
p {
font-size: 16px;
line-height: 1.6;
}
a.telegram-button {
display: inline-block;
background-color: #4CAF50; /* Зеленый цвет */
color: #ffffff;
padding: 15px 30px;
text-decoration: none;
border-radius: 8px;
margin-top: 20px;
transition: background-color 0.3s;
font-size: 18px;
}
a.telegram-button:hover {
background-color: #45a049; /* Темно-зеленый цвет при наведении */
}

View File

@ -0,0 +1,330 @@
@import url(//fonts.googleapis.com/css?family=Ubuntu);
body {
margin:0;
padding:0;
font-family:helvetica, sans-serif;
}
h1, h2, h3, h4, h5 , h6 {
font-family: 'Ubuntu', sans-serif; font-weight:normal;
}
a {
text-decoration:none;
color:#5993bb;
}
a:hover {
color:#77b6e2;
}
a.button, input[type="submit"] {
color:#fff;
background:#5993bb;
border-radius:4px;
padding:10px 20px;
font-size:14px;
border:0;
}
a.button.light {
color:#666;
background:#ededed;
}
.text-left {
text-align:left;
}
.text-right {
text-align:right;
}
table {
width:100%;
border-spacing:0;
border-collapse: collapse;
}
table th, table td {
text-align:left;
font-size:14px;
padding:10px;
margin:0;
}
tbody tr:nth-child(odd) {
background:#efefef;
}
tbody tr.subtotal {
background:#ccc;
}
thead th, tbody tr.total {
background:#5993bb;
color:#fff;
font-weight:bold;
}
table.cart {
margin-bottom:40px;
}
table.cart img {
width:180px;
}
tbody td.num {
text-align:right;
}
td input[type="submit"] {
font-size:12px;
padding:4px 10px;
}
form p label, form p input {
float:left;
clear:both;
}
form p label {
font-size:14px;
padding-bottom:4px;
}
form p input {
width:300px;
font-size:13px;
margin-bottom:10px;
padding:10px 12px;
border:0;
background:#efefef;
color:#666;
border-radius:4px;
}
ul.errorlist {
float:left;
color:#ff0000;
clear:both;
font-size:13px;
margin:0 0 0 10px;
padding:10px 0;
}
#header {
padding:10px 100px;
font-size:18px;
overflow:auto;
}
#subheader {
background:#ececec;
color:#444;
padding:15px 100px;
overflow:auto;
}
#header .logo {
font-family: 'Ubuntu', sans-serif;
float:left;
color:#333;
font-size:22px;
margin-right:10%;
}
#subheader .cart {
float:right;
padding-top:4px;
}
#content {
padding:0 100px;
overflow:hidden;
}
#sidebar {
width:220px;
padding:30px 20px 0 0;
float:left;
}
#sidebar ul{
margin:0;
padding:0;
}
#sidebar ul li {
margin:0;
list-style:none;
padding:10px 14px;
}
#sidebar ul li a {
display:block;
}
#sidebar ul li.selected {
background:#5993bb;
border-radius:4px;
}
#sidebar ul li.selected a {
color:#fff;
}
#main {
float:left;
width: 96%;
margin-right:-220px;
overflow:hidden;
}
.product-list .item {
width:25%;
padding:10px 20px 10px 0;
float:left;
text-align:center;
line-height:1.2;
}
.product-list .item img {
width:100%;
margin-bottom:8px;
}
.product-detail {
text-align:justify;
}
.product-detail .price {
color:#333;
font-size:28px;
font-weight:bold;
}
.product-detail img {
width:40%;
float:left;
padding:0 20px 20px 0;
}
.product-detail h1 {
margin-bottom:0;
}
.product-detail h2 {
margin-top:10px;
}
.order-form {
float:left;
}
.order-info {
float:right;
width:300px;
background:#efefef;
padding:10px 20px;
color:#333;
border-bottom:4px solid #5993bb;
}
.order-info h3 {
color:#5993bb;
}
.order-info ul li {
margin:0;
padding:0;
font-size:14px;
}
.order-info p {
font-weight:bold;
float:right;
}
.order-info span {
float:right;
}
.neg {
color:#dc1616;
}
.languages {
float:right;
padding-top:4px;
font-size:14px;
}
.languages ul {
list-style:none;
margin:0;
padding:0;
float:left;
}
.languages ul li {
float:left;
margin:0 0 0 10px;
font-size:14px;
}
.languages p {
float:left;
margin:0;
}
.recommendations {
clear:both;
}
.recommendations div {
float:left;
}
.recommendations img {
width:200px
}
.recommendations p {
clear:both;
}
.recommendations.cart {
width:60%;
float:left;
overflow:auto;
}
.recommendations.cart h3 {
margin-top:0;
}
.recommendations.cart .item {
margin-right:10px;
}
.recommendations.cart img {
width:120px;
}
/* braintree hosted fields */
form div.field {
font-size:13px;
color:#666;
width:300px;
height:22px;
margin-bottom:10px;
padding:6px 12px;
border:0;
background:#efefef;
color:#666;
border-radius:4px;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,100 @@
body {
background-image: url("../images/bg-image.jpg");
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center center;
background-size: cover;
height: 100%;
}
.dropdown-toggle::after {
content: none;
}
.custom-shadow {
box-shadow: 5px 5px 25px 19px #380069;
}
.product_id {
color: #cb5cff;
font-size: 15px;
}
.badge.bg-warning.text-dark {
position: absolute;
top: 10px;
right: 5px;
z-index: 1;
padding: 5px 10px;
border-radius: 3px;
font-size: 1rem;
box-shadow: 2px 2px 15px 9px #000000;
}
.badge-banner {
top: 80%;
border-radius: 15px;
font-size: 0.7rem;
}
/* Ваши стили для футера */
footer {
padding-top: 20px; /* Расстояние от верха футера */
background-color: #343a40; /* Цвет фона футера */
color: #ffffff; /* Цвет текста внутри футера */
}
.footer-content {
display: flex;
justify-content: space-between;
align-items: center;
}
.footer-ad {
flex-grow: 1; /* Растянуть колонку на всю доступную ширину */
}
.ad-text {
text-align: center;
}
.ad-block {
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
margin-top: 10px;
}
.ad-heading {
color: #ffffff;
font-size: 18px;
}
.ad-description {
color: #ffffff;
font-size: 14px;
margin-bottom: 10px;
}
.ad-button {
background-color: #ffc107; /* Цвет кнопки */
color: #343a40; /* Цвет текста на кнопке */
border: none;
padding: 10px 20px;
border-radius: 5px;
text-decoration: none;
transition: background-color 0.3s;
}
.ad-button:hover {
background-color: #ffca2c; /* Цвет кнопки при наведении */
}
.footer-text {
font-size: 18px; /* Размер шрифта */
font-weight: bold; /* Жирное начертание */
margin-top: 10px; /* Верхний отступ */
}
.footer-text span {
color: #ff6b6b; /* Цвет для части текста */
}

View File

@ -0,0 +1,7 @@
footer {
position: fixed;
bottom: 0;
width: 100%;
background-color: #8100bb;
padding: 10px 0;
}

View File

@ -0,0 +1,60 @@
body {
font-family:Helvetica, sans-serif;
color:#222;
line-height:1.5;
}
table {
width:100%;
border-spacing:0;
border-collapse: collapse;
margin:20px 0;
}
table th, table td {
text-align:left;
font-size:14px;
padding:10px;
margin:0;
}
tbody tr:nth-child(odd) {
background:#efefef;
}
thead th, tbody tr.total {
background:#5993bb;
color:#fff;
font-weight:bold;
}
h1 {
margin:0;
}
.secondary {
color:#bbb;
margin-bottom:20px;
}
.num {
text-align:right;
}
.paid, .pending {
color:#1bae37;
border:4px solid #1bae37;
text-transform:uppercase;
font-weight:bold;
font-size:22px;
padding:4px 12px 0px;
float:right;
transform: rotate(-15deg);
margin-right:40px;
}
.pending {
color:#a82d2d;
border:4px solid #a82d2d;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -0,0 +1 @@
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-box-arrow-in-left" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M10 3.5a.5.5 0 0 0-.5-.5h-8a.5.5 0 0 0-.5.5v9a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5v-2a.5.5 0 0 1 1 0v2A1.5 1.5 0 0 1 9.5 14h-8A1.5 1.5 0 0 1 0 12.5v-9A1.5 1.5 0 0 1 1.5 2h8A1.5 1.5 0 0 1 11 3.5v2a.5.5 0 0 1-1 0v-2z"/>
<path fill-rule="evenodd" d="M4.146 8.354a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L5.707 7.5H14.5a.5.5 0 0 1 0 1H5.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3z"/>
</svg>

After

Width:  |  Height:  |  Size: 552 B

View File

@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-box-arrow-in-right" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M6 3.5a.5.5 0 0 1 .5-.5h8a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-8a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 0-1 0v2A1.5 1.5 0 0 0 6.5 14h8a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-8A1.5 1.5 0 0 0 5 3.5v2a.5.5 0 0 0 1 0v-2z"/>
<path fill-rule="evenodd" d="M11.854 8.354a.5.5 0 0 0 0-.708l-3-3a.5.5 0 1 0-.708.708L10.293 7.5H1.5a.5.5 0 0 0 0 1h8.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3z"/>
</svg>

After

Width:  |  Height:  |  Size: 555 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-github" viewBox="0 0 16 16">
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
</svg>

After

Width:  |  Height:  |  Size: 709 B

View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-grid-fill" viewBox="0 0 16 16">
<path d="M1 2.5A1.5 1.5 0 0 1 2.5 1h3A1.5 1.5 0 0 1 7 2.5v3A1.5 1.5 0 0 1 5.5 7h-3A1.5 1.5 0 0 1 1 5.5v-3zm8 0A1.5 1.5 0 0 1 10.5 1h3A1.5 1.5 0 0 1 15 2.5v3A1.5 1.5 0 0 1 13.5 7h-3A1.5 1.5 0 0 1 9 5.5v-3zm-8 8A1.5 1.5 0 0 1 2.5 9h3A1.5 1.5 0 0 1 7 10.5v3A1.5 1.5 0 0 1 5.5 15h-3A1.5 1.5 0 0 1 1 13.5v-3zm8 0A1.5 1.5 0 0 1 10.5 9h3a1.5 1.5 0 0 1 1.5 1.5v3a1.5 1.5 0 0 1-1.5 1.5h-3A1.5 1.5 0 0 1 9 13.5v-3z"/>
</svg>

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

File diff suppressed because one or more lines are too long

181
main/static/deps/js/jquery-ajax.js vendored Normal file
View File

@ -0,0 +1,181 @@
// Когда html документ готов (прорисован)
$(document).ready(function () {
// берем в переменную элемент разметки с id jq-notification для оповещений от ajax
var successMessage = $("#jq-notification");
// // Ловим собыитие клика по кнопке добавить в корзину
// $(document).on("click", ".add-to-cart", function (e) {
// // Блокируем его базовое действие
// e.preventDefault();
// // Берем элемент счетчика в значке корзины и берем оттуда значение
// var goodsInCartCount = $("#goods-in-cart-count");
// var cartCount = parseInt(goodsInCartCount.text() || 0);
// // Получаем id товара из атрибута data-product-id
// var product_id = $(this).data("product-id");
// // Из атрибута href берем ссылку на контроллер django
// var add_to_cart_url = $(this).attr("href");
// // делаем post запрос через ajax не перезагружая страницу
// $.ajax({
// type: "POST",
// url: add_to_cart_url,
// data: {
// product_id: product_id,
// csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
// },
// success: function (data) {
// // Сообщение
// successMessage.html(data.message);
// successMessage.fadeIn(400);
// // Через 7сек убираем сообщение
// setTimeout(function () {
// successMessage.fadeOut(400);
// }, 7000);
// // Увеличиваем количество товаров в корзине (отрисовка в шаблоне)
// cartCount++;
// goodsInCartCount.text(cartCount);
// // Меняем содержимое корзины на ответ от django (новый отрисованный фрагмент разметки корзины)
// var cartItemsContainer = $("#cart-items-container");
// cartItemsContainer.html(data.cart_items_html);
// },
// error: function (data) {
// console.log("Ошибка при добавлении товара в корзину");
// },
// });
// });
// // Ловим собыитие клика по кнопке удалить товар из корзины
// $(document).on("click", ".remove-from-cart", function (e) {
// // Блокируем его базовое действие
// e.preventDefault();
// // Берем элемент счетчика в значке корзины и берем оттуда значение
// var goodsInCartCount = $("#goods-in-cart-count");
// var cartCount = parseInt(goodsInCartCount.text() || 0);
// // Получаем id корзины из атрибута data-cart-id
// var cart_id = $(this).data("cart-id");
// // Из атрибута href берем ссылку на контроллер django
// var remove_from_cart = $(this).attr("href");
// // делаем post запрос через ajax не перезагружая страницу
// $.ajax({
// type: "POST",
// url: remove_from_cart,
// data: {
// cart_id: cart_id,
// csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
// },
// success: function (data) {
// // Сообщение
// successMessage.html(data.message);
// successMessage.fadeIn(400);
// // Через 7сек убираем сообщение
// setTimeout(function () {
// successMessage.fadeOut(400);
// }, 7000);
// // Уменьшаем количество товаров в корзине (отрисовка)
// cartCount -= data.quantity_deleted;
// goodsInCartCount.text(cartCount);
// // Меняем содержимое корзины на ответ от django (новый отрисованный фрагмент разметки корзины)
// var cartItemsContainer = $("#cart-items-container");
// cartItemsContainer.html(data.cart_items_html);
// },
// error: function (data) {
// console.log("Ошибка при добавлении товара в корзину");
// },
// });
// });
// // Теперь + - количества товара
// // Обработчик события для уменьшения значения
// $(document).on("click", ".decrement", function () {
// // Берем ссылку на контроллер django из атрибута data-cart-change-url
// var url = $(this).data("cart-change-url");
// // Берем id корзины из атрибута data-cart-id
// var cartID = $(this).data("cart-id");
// // Ищем ближайшеий input с количеством
// var $input = $(this).closest('.input-group').find('.number');
// // Берем значение количества товара
// var currentValue = parseInt($input.val());
// // Если количества больше одного, то только тогда делаем -1
// if (currentValue > 1) {
// $input.val(currentValue - 1);
// // Запускаем функцию определенную ниже
// // с аргументами (id карты, новое количество, количество уменьшилось или прибавилось, url)
// updateCart(cartID, currentValue - 1, -1, url);
// }
// });
// // Обработчик события для увеличения значения
// $(document).on("click", ".increment", function () {
// // Берем ссылку на контроллер django из атрибута data-cart-change-url
// var url = $(this).data("cart-change-url");
// // Берем id корзины из атрибута data-cart-id
// var cartID = $(this).data("cart-id");
// // Ищем ближайшеий input с количеством
// var $input = $(this).closest('.input-group').find('.number');
// // Берем значение количества товара
// var currentValue = parseInt($input.val());
// $input.val(currentValue + 1);
// // Запускаем функцию определенную ниже
// // с аргументами (id карты, новое количество, количество уменьшилось или прибавилось, url)
// updateCart(cartID, currentValue + 1, 1, url);
// });
// function updateCart(cartID, quantity, change, url) {
// $.ajax({
// type: "POST",
// url: url,
// data: {
// cart_id: cartID,
// quantity: quantity,
// csrfmiddlewaretoken: $("[name=csrfmiddlewaretoken]").val(),
// },
// success: function (data) {
// // Сообщение
// successMessage.html(data.message);
// successMessage.fadeIn(400);
// // Через 7сек убираем сообщение
// setTimeout(function () {
// successMessage.fadeOut(400);
// }, 7000);
// // Изменяем количество товаров в корзине
// var goodsInCartCount = $("#goods-in-cart-count");
// var cartCount = parseInt(goodsInCartCount.text() || 0);
// cartCount += change;
// goodsInCartCount.text(cartCount);
// // Меняем содержимое корзины
// var cartItemsContainer = $("#cart-items-container");
// cartItemsContainer.html(data.cart_items_html);
// },
// error: function (data) {
// console.log("Ошибка при добавлении товара в корзину");
// },
// });
// }
});

35
main/static/deps/js/jquery-events.js vendored Normal file
View File

@ -0,0 +1,35 @@
// Когда html документ готов (прорисован)
$(document).ready(function () {
// Берем из разметки элемент по id - оповещения от django
var notification = $('#notification');
// И через 7 сек. убираем
if (notification.length > 0) {
setTimeout(function () {
notification.alert('close');
}, 7000);
}
// При клике по значку корзины открываем всплывающее(модальное) окно
$('#modalButton').click(function () {
$('#exampleModal').appendTo('body');
$('#exampleModal').modal('show');
});
// Собыите клик по кнопке закрыть окна корзины
$('#exampleModal .btn-close').click(function () {
$('#exampleModal').modal('hide');
});
// Обработчик события радиокнопки выбора способа доставки
$("input[name='requires_delivery']").change(function() {
var selectedValue = $(this).val();
// Скрываем или отображаем input ввода адреса доставки
if (selectedValue === "1") {
$("#deliveryAddressField").show();
} else {
$("#deliveryAddressField").hide();
}
});
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,35 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{% static "/deps/css/bootstrap/bootstrap.min.css"%}">
<link rel="stylesheet" href="{% static "/deps/css/my_css.css"%}">
<!-- Стиль footer-a для главной страницы -->
<link rel="stylesheet" href="{% static "/deps/css/my_footer_css.css"%}">
<!-- Favicons for different platforms -->
<link rel="apple-touch-icon" sizes="180x180" href="{% static "/deps/favicon/apple-touch-icon.png"%}">
<link rel="icon" type="image/png" sizes="32x32" href="{% static "/deps/favicon/favicon-32x32.png"%}">
<link rel="icon" type="image/png" sizes="16x16" href="{% static "/deps/favicon/favicon-16x16.png"%}">
<link rel="manifest" href="{% static "/deps/favicon/site.webmanifest"%}">
<link rel="stylesheet" href="{% static "deps/css/about.css" %}">
<!-- Добавьте ссылку на ваш файл со стилями для about страницы -->
<title>About Us</title>
</head>
<body>
<div class="about-container">
<h2 class="m-2"><strong>{{ content }}</strong></h2>
<p class="m-2">{{ text_on_page|safe }}</p>
<a href="{% url 'index' %}" class="btn btn-primary">Вернуться на главную</a>
<a href="https://t.me/silky_way_bot" class="telegram-button">Перейти к Silky Way</a>
</div>
</body>
</html>

View File

@ -0,0 +1,21 @@
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>{% block title %}My shop{% endblock %}</title>
<link href="{% static "/deps/css/base.css" %}" rel="stylesheet">
</head>
<body>
<div id="header">
<a href="/" class="logo">Nitaku</a>
</div>
<div id="subheader">
</div>
<div id="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>

View File

@ -0,0 +1,126 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="{% static "/deps/css/bootstrap/bootstrap.min.css"%}">
<link rel="stylesheet" href="{% static "/deps/css/my_css.css"%}">
<!-- Стиль footer-a для главной страницы -->
<link rel="stylesheet" href="{% static "/deps/css/my_footer_css.css"%}">
<!-- Favicons for different platforms -->
<link rel="apple-touch-icon" sizes="180x180" href="{% static "/deps/favicon/apple-touch-icon.png"%}">
<link rel="icon" type="image/png" sizes="32x32" href="{% static "/deps/favicon/favicon-32x32.png"%}">
<link rel="icon" type="image/png" sizes="16x16" href="{% static "/deps/favicon/favicon-16x16.png"%}">
<link rel="manifest" href="{% static "/deps/favicon/site.webmanifest"%}">
<title>Home</title>
</head>
<body>
<header>
<nav class="navbar navbar-expand-lg bg-dark" data-bs-theme="dark">
<div class="container">
<a class="navbar-brand" href="{% url "index"%}">Nitaku</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item dropdown ">
<a class="nav-link dropdown-toggle text-white" href="#" role="button"
data-bs-toggle="dropdown" aria-expanded="false">
Информация
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item text-white" href="https://t.me/silky_way_bot">Контактная информация</a></li>
<li><a class="dropdown-item text-white" href="{% url 'about' %}">Про нас</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container">
<div class="row mt-1">
<div class="col-lg-2">
<!-- Пустой блок на Ваше усмотрение -->
</div>
<div id="header">
<h3><img src="{% static "deps/favicon/favicon.ico.png"%}" alt="Логотип"> Nitaku shop</h3>
</div>
</div>
</div>
<section>
{# <div class="container">#}
{# <!-- Каталог и корзина с фиксированным расположением на странице -->#}
{##}
{# <!-- Карта товара -->#}
{# <div class="col-lg-4 col-md-6 p-4">#}
{# <div class="card border-primary rounded custom-shadow">#}
{# <img src="{% static "/deps/images/goods/O1CN01xsBTy51MVZ2HM1sjf_!!4200721440-0-cib.jpg"%}" class="card-img-top" alt="...">#}
{# <div class="card-body">#}
{# <a href="../goods/product.html">#}
{# <p class="card-title">Anime girl/p>#}
{# </a>#}
{# <p class="card-text text-truncate">Re Zero</p>#}
{##}
{# <div class="d-flex justify-content-between">#}
{##}
{# <p><strong>90.00 $</strong></p>#}
{##}
{# <!-- <p><strong>100.00 $</strong></p> -->#}
{##}
{# </div>#}
{# </div>#}
{# </div>#}
{# </div>#}
{##}
{# </div>#}
{# </div>#}
{# </div>#}
{# <!-- Закончилась разметка модального окна -->#}
{# </div>#}
{# </div>#}
<!-- Контент -->
</section>
<footer class="py-4 bg-dark">
<div class="container">
<div class="row">
<!-- Колонка для рекламного блока -->
<div class="col-lg-8">
<p class="m-0 text-center text-white footer-text">Nitaku shop <span>&</span> Silky Way 2024</p>
</div>
<!-- Колонка для рекламного блока -->
<div class="col-lg-4">
<div class="text-center mt-3">
<h5 class="text-white">Посетите нашего телеграм бота!</h5>
<p class="text-white">Распознавайте товары в картинах и найдите их онлайн.</p>
<a href="https://t.me/silky_way_bot" class="btn btn-warning"> Silky Way </a>
</div>
</div>
</div>
</div>
</footer>
<script src="{% static "/deps/js/jquery/jquery-3.7.0.min.js"%}"></script>
<script src="{% static "/deps/js/jquery-events.js"%}"></script>
<script src="{% static "/deps/js/jquery-ajax.js"%}"></script>
<script src="{% static "/deps/js/bootstrap/bootstrap.bundle.min.js"%}"></script>
</body>
</html>

View File

@ -0,0 +1,19 @@
{% extends "main/base.html" %}
{% load static %}
{% block title %}
{{ product.name }}
{% endblock %}
{% block content %}
<div class="product-detail">
<img src="{% if product.image %}{{ product.image.url }}{% else %}
{% static "deps/img/no_image.jpg" %}{% endif %}">
<h1>{{ product.name }}</h1>
<h2>
<a href="{{ product.category.get_absolute_url }}">
{{ product.category }}
</a>
</h2>
<p class="price">${{ product.price }}</p>
{{ product.description|linebreaks }}
</div>
{% endblock %}

View File

@ -0,0 +1,35 @@
{% extends "main/base.html" %}
{% load static %}
{% block title %}
{% if category %}{{ category.name }}{% else %}Products{% endif %}
{% endblock %}
{% block content %}
<div id="sidebar">
<h3>Categories</h3>
<ul>
<li {% if not category %}class="selected"{% endif %}>
<a href="{% url "main:product_list" %}">All</a>
</li>
{% for c in categories %}
<li {% if category.slug == c.slug %}class="selected"
{% endif %}>
<a href="{{ c.get_absolute_url }}">{{ c.name }}</a>
</li>
{% endfor %}
</ul>
</div>
<div id="main" class="product-list">
<h1>{% if category %}{{ category.name }}{% else %}Products
{% endif %}</h1>
{% for product in products %}
<div class="item">
<a href="{{ product.get_absolute_url }}">
<img src="{% if product.image %}{{ product.image.url }}{% else %}{% static "img/no_image.png" %}{% endif %}">
</a>
<a href="{{ product.get_absolute_url }}">{{ product.name }}</a>
<br>
${{ product.price }}
</div>
{% endfor %}
</div>
{% endblock %}

3
main/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

16
main/urls.py Normal file
View File

@ -0,0 +1,16 @@
from django.urls import path
from . import views
app_name = 'main'
urlpatterns = [
path('', views.index, name='index'),
path('about/', views.about, name='about'),
path('', views.product_list, name='product_list'),
path('<slug:category_slug>/', views.product_list,
name='product_list_by_category'),
path('<int:id>/<slug:slug>/', views.product_detail,
name='product_detail'),
]

53
main/views.py Normal file
View File

@ -0,0 +1,53 @@
from django.shortcuts import render,get_object_or_404
from django.http import HttpResponse
from .models import Category, Product
def index(request) -> HttpResponse:
context : dict = {
'title':'Home',
'contect' : 'Главная страница - HOME',
'list':['first','second'],
'dict' : {'first':1},
'is_authenticated':False
}
return render(request, 'main/index.html',context)
def about(request):
context = {
'title' : 'Nitaku - О нас',
'content' : 'О нас',
'text_on_page' : """Добро пожаловать в NITAKU shop ваш уютный уголок аниме-фигурок! Здесь вас ждет настоящий рай для ценителей аниме и фигурок. В нашем магазине вы обнаружите богатый выбор высококачественных аниме-фигурок по привлекательным ценам.
Откройте для себя удивительный мир аниме вместе с нами, где цены приятно удивят вас, а коллекции уникальны и разнообразны. Мы гордимся тем, что предоставляем доступ к самым лучшим и красочным фигуркам, чтобы ваши любимые персонажи ожили у вас дома.
Но это еще не все! Мы также рады представить вам Silky Way телеграм-бота, вашего надежного помощника в поиске аниме-товаров. Silky Way обладает уникальной функцией распознавания товаров на картинках. Просто отправьте фотографию интересующего вас товара, и бот предложит вам ссылки и информацию о нем.
Присоединяйтесь к NITAKU shop, создайте свою уникальную аниме-коллекцию и воспользуйтесь удобством Silky Way для поиска и приобретения ваших желанных предметов! Магия аниме ждет вас! 🌟
""",
}
return render(request,'main/about.html',context)
def product_list(request, category_slug=None):
category = None
categories = Category.objects.all()
products = Product.objects.filter(available=True)
if category_slug:
category = get_object_or_404(Category,
slug=category_slug)
products = products.filter(category=category)
return render(request,'main/product/list.html',
{'category': category,
'categories': categories,
'products': products})
def product_detail(request, id, slug):
product = get_object_or_404(Product,
id=id,
slug=slug,
available=True)
return render(request,
'main/product/detail.html',
{'product': product})

22
manage.py Normal file
View File

@ -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', 'NITAKUSHOP.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()