Дата выдачи задания __.__.202__ Задание принял (дата) __.__.202__
Подпись руководителя ____________ Подпись обучающегося____________
Гражданский кодекс Российской Федерации. Часть первая: федер. закон от 30.11.1994 № 51-ФЗ (ред. от 28.05.2022) // Собрание законодательства РФ. – 1994. – № 32. – Ст. 3301.
ГОСТ Р 7.0.100-2018. Библиографическая запись. Библиографическое описание. Общие требования и правила составления. – М.: Стандартинформ, 2019. – 18 с.
О персональных данных: федер. закон от 27.07.2006 № 152-ФЗ (ред. от 01.03.2023) // Собрание законодательства РФ. – 2006. – № 31. – Ст. 3451.
О защите прав потребителей: закон РФ от 07.02.1992 № 2300-1 (ред. от 01.07.2022) // Ведомости СНД и ВС РФ. – 1992. – № 15. – Ст. 766.
Ермаков С.А., Черникова Л.А. Информационные системы в экономике. – М.: Юрайт, 2020. – 343 с.
Журавлёв А.А. Разработка web-приложений на Django. – СПб.: БХВ-Петербург, 2021. – 304 с.
Попов Е.В., Плотникова И.В. Информационные технологии в управлении. – М.: КНОРУС, 2020. – 256 с.
Бояринов И.В. Основы построения и внедрения информационных систем. – М.: Инфра-М, 2019. – 272 с.
Кайдалов В.А. Экономическая эффективность информационных систем. – М.: Финансы и статистика, 2018. – 288 с.
Мурашова Л.В. Управление проектами в ИТ: учеб. пособие. – СПб.: Питер, 2020. – 240 с.
Django Software Foundation. Django documentation, release 4.2 [Электронный ресурс]. – URL: https://docs.djangoproject.com (дата обращения: 01.07.2025).
Python Software Foundation. Python Documentation [Электронный ресурс]. – URL: https://docs.python.org (дата обращения: 01.07.2025).
PostgreSQL Global Development Group. PostgreSQL documentation [Электронный ресурс]. – URL: https://www.postgresql.org/docs (дата обращения: 01.07.2025).
Федосеева Н.В., Кондратьева Т.В. Проектирование информационных систем: учеб. пособие. – М.: Академия, 2020. – 192 с.
Беляев И.Н. Web-программирование. HTML, CSS, JavaScript и React. – СПб.: Питер, 2022. – 320 с.
Архипов В.П. Информационные технологии: концепции и приложения. – М.: Форум, 2021. – 288 с.
Снежко В.П., Захаров И.В. Разработка сайтов и интернет-магазинов на Python и Django. – М.: ДМК Пресс, 2021. – 208 с.
Федеральная служба по техническому и экспортному контролю (ФСТЭК России). Методические рекомендации по защите персональных данных при их обработке в информационных системах [Электронный ресурс]. – URL: https://fstec.ru (дата обращения: 01.07.2025).
ISO/IEC 27001:2022. Information security, cybersecurity and privacy protection — Information security management systems — Requirements. – ISO, 2022.
E-commerce in Russia: Market overview and trends [Электронный ресурс] // Data Insight. – URL: https://datainsight.ru/ecommerce (дата обращения: 01.07.2025).
ПРИЛОЖЕНИЕ
# shop/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .models import User, Category, Product, Order, OrderItem, Review
class UserAdmin(BaseUserAdmin):
list_display = ('email', 'full_name', 'phone_number', 'is_staff', 'date_joined')
search_fields = ('email', 'full_name', 'phone_number')
ordering = ('-date_joined',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Личная информация', {'fields': ('full_name', 'phone_number')}),
('Права доступа', {'fields': ('is_staff', 'is_superuser', 'groups', 'user_permissions')}),
('Прочее', {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'full_name', 'phone_number', 'password1', 'password2'),
}),
)
admin.site.register(User, UserAdmin)
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = ('id', 'name')
search_fields = ('name',)
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ('name', 'category', 'price', 'stock_quantity')
search_fields = ('name',)
list_filter = ('category',)
class OrderItemInline(admin.TabularInline):
model = OrderItem
extra = 0
@admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
list_display = ('id', 'user', 'created_at', 'status', 'total_price')
list_filter = ('status', 'created_at')
search_fields = ('user__email', 'id')
inlines = [OrderItemInline]
@admin.register(Review)
class ReviewAdmin(admin.ModelAdmin):
list_display = ('user', 'product', 'rating', 'created_at')
search_fields = ('user__email', 'product__name')
# shop/forms.py
from django import forms
from django.contrib.auth.forms import AuthenticationForm
from .models import User
class RegisterForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
password_confirm = forms.CharField(widget=forms.PasswordInput, label="Подтверждение пароля")
class Meta:
model = User
fields = ['full_name', 'email', 'phone_number']
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get('password')
password_confirm = cleaned_data.get('password_confirm')
if password != password_confirm:
raise forms.ValidationError("Пароли не совпадают")
return cleaned_data
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data['password'])
if commit:
user.save()
return user
class LoginForm(AuthenticationForm):
username = forms.EmailField(label="Email")
class OrderForm(forms.Form):
address = forms.CharField(label='Адрес доставки', widget=forms.Textarea)
payment_method = forms.ChoiceField(
choices=[('online', 'Онлайн'), ('cod', 'Наложенный платеж')],
label='Способ оплаты'
)
comment = forms.CharField(label='Комментарий к заказу', required=False, widget=forms.Textarea)
# shop/models.py
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
from django.db import models
class UserManager(BaseUserManager):
def create_user(self, email, full_name, phone_number, password=None, **extra_fields):
if not email:
raise ValueError('Email обязателен')
email = self.normalize_email(email)
user = self.model(email=email, full_name=full_name, phone_number=phone_number, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, full_name, phone_number, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
return self.create_user(email, full_name, phone_number, password, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin):
full_name = models.CharField(max_length=255)
email = models.EmailField(unique=True)
phone_number = models.CharField(max_length=20)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(auto_now_add=True)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['full_name', 'phone_number']
def __str__(self):
return self.full_name
class Category(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=255)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
stock_quantity = models.IntegerField()
image_url = models.URLField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Order(models.Model):
STATUS_CHOICES = [
('new', 'Новый'),
('confirmed', 'Подтвержден'),
('shipped', 'Отправлен'),
('completed', 'Завершён')
]
user = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='new')
total_price = models.DecimalField(max_digits=10, decimal_places=2)
def __str__(self):
return f"Заказ #{self.id} - {self.user.email}"
class OrderItem(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='items')
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
class Review(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
rating = models.IntegerField()
comment = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
# shop/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home_view, name='home'),
path('register/', views.register_view, name='register'),
path('login/', views.login_view, name='login'),
path('logout/', views.logout_view, name='logout'),
path('cart/', views.cart_view, name='cart'),
path('add-to-cart/<int:product_id>/', views.add_to_cart, name='add_to_cart'),
path('remove-from-cart/<int:product_id>/', views.remove_from_cart, name='remove_from_cart'),
path('checkout/', views.checkout_view, name='checkout'),
path('account/', views.account_view, name='account'),
path('repeat-order/<int:order_id>/', views.repeat_order_view, name='repeat_order'),
]
# shop/views.py
from .models import *
from .forms import *
from django.contrib.auth import login, authenticate, logout
from django.shortcuts import render, redirect, get_object_or_404
from .forms import RegisterForm, LoginForm
from .forms import OrderForm
from django.contrib.auth.decorators import login_required
from decimal import Decimal
def home_view(request):
categories = Category.objects.all()
products = Product.objects.order_by('-id')[:8] # последние 8 товаров
return render(request, 'shop/home.html', {
'categories': categories,
'products': products,
})
def register_view(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user) # автоматический вход
return redirect('home')
else:
form = RegisterForm()
return render(request, 'shop/register.html', {'form': form})
def login_view(request):
if request.method == 'POST':
form = LoginForm(request, data=request.POST)
if form.is_valid():
user = form.get_user()
login(request, user)
return redirect('home')
else:
form = LoginForm()
return render(request, 'shop/login.html', {'form': form})
def logout_view(request):
logout(request)
return redirect('home')
def add_to_cart(request, product_id):
cart = request.session.get('cart', {})
cart[str(product_id)] = cart.get(str(product_id), 0) + 1
request.session['cart'] = cart
return redirect('cart')
def remove_from_cart(request, product_id):
cart = request.session.get('cart', {})
if str(product_id) in cart:
del cart[str(product_id)]
request.session['cart'] = cart
return redirect('cart')
def cart_view(request):
cart = request.session.get('cart', {})
products = Product.objects.filter(id__in=cart.keys())
cart_items = []
total = 0
for product in products:
quantity = cart[str(product.id)]
subtotal = product.price * quantity
cart_items.append({
'product': product,
'quantity': quantity,
'subtotal': subtotal,
})
total += subtotal
return render(request, 'shop/cart.html', {
'cart_items': cart_items,
'total': total,
})
@login_required
def checkout_view(request):
cart = request.session.get('cart', {})
if not cart:
return redirect('cart')
products = Product.objects.filter(id__in=cart.keys())
cart_items = []
total = Decimal('0.00')
for product in products:
quantity = cart[str(product.id)]
subtotal = product.price * quantity
cart_items.append({'product': product, 'quantity': quantity, 'subtotal': subtotal})
total += subtotal
if request.method == 'POST':
form = OrderForm(request.POST)
if form.is_valid():
order = Order.objects.create(
user=request.user,
status='new',
total_price=total
)
for item in cart_items:
OrderItem.objects.create(
order=order,
product=item['product'],
quantity=item['quantity'],
price=item['product'].price
)
request.session['cart'] = {}
return render(request, 'shop/order_success.html', {'order': order})
else:
form = OrderForm()
return render(request, 'shop/checkout.html', {
'cart_items': cart_items,
'total': total,
'form': form
})
@login_required
def account_view(request):
orders = Order.objects.filter(user=request.user).order_by('-created_at')
return render(request, 'shop/account.html', {'orders': orders})
@login_required
def repeat_order_view(request, order_id):
order = get_object_or_404(Order, id=order_id, user=request.user)
cart = {}
for item in order.items.all():
cart[str(item.product.id)] = item.quantity
request.session['cart'] = cart
return redirect('cart')
"""
Django settings for shop_project project.
Generated by 'django-admin startproject' using Django 5.1.5.
For more information on this file, see
https://docs.djangoproject.com/en/5.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.1/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.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-59ccc68nln&v^7v8jzfd5^e7k2-lk84q*znh@$sc9mdb1^9)f('
# 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',
'shop',
'django_extensions',
]
AUTH_USER_MODEL = 'shop.User'
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 = 'shop_project.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 = 'shop_project.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/5.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/5.1/topics/i18n/
LANGUAGE_CODE = 'ru-Ru'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.1/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'