Создать структуру базы данных для товаров: Поля: наименование, штрих-код, срок годности, размеры, единицы измерения, производитель, категория товара, температурные условия хранения, акции (тип "1+1", "2+1"). Реализовать функционал: Добавление, редактирование и удаление карточек товаров. Проверка на дублирование данных (штрих-код). Валидация данных (например, срок годности).main
parent
04581f5ebb
commit
87dae7b461
@ -0,0 +1,2 @@
|
|||||||
|
Watching for file changes with StatReloader
|
||||||
|
Watching for file changes with StatReloader
|
@ -0,0 +1,4 @@
|
|||||||
|
Watching for file changes with StatReloader
|
||||||
|
/Users/darius/Documents/franchise_store/settings/base.py changed, reloading.
|
||||||
|
Watching for file changes with StatReloader
|
||||||
|
/Users/darius/Documents/franchise_store/settings/base.py changed, reloading.
|
@ -0,0 +1,8 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
|
||||||
|
from .models import Product
|
||||||
|
|
||||||
|
@admin.register(Product)
|
||||||
|
class ProductAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('name', 'barcode', 'category', 'shelf_life_days', 'promotion')
|
||||||
|
search_fields = ('name', 'barcode')
|
@ -0,0 +1,7 @@
|
|||||||
|
from rest_framework.viewsets import ModelViewSet
|
||||||
|
from .models import Product
|
||||||
|
from .serializers import ProductSerializer
|
||||||
|
|
||||||
|
class ProductViewSet(ModelViewSet):
|
||||||
|
queryset = Product.objects.all()
|
||||||
|
serializer_class = ProductSerializer
|
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class ProductDirectoryConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'product_directory'
|
@ -0,0 +1,15 @@
|
|||||||
|
from django import forms
|
||||||
|
from .models import Product
|
||||||
|
|
||||||
|
class ProductForm(forms.ModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = Product
|
||||||
|
fields = '__all__'
|
||||||
|
|
||||||
|
def clean_shelf_life_days(self):
|
||||||
|
shelf_life_days = self.cleaned_data.get('shelf_life_days')
|
||||||
|
if shelf_life_days <= 0:
|
||||||
|
raise forms.ValidationError("Срок годности должен быть положительным числом.")
|
||||||
|
if shelf_life_days > 3650: # 10 лет
|
||||||
|
raise forms.ValidationError("Срок годности превышает допустимый предел.")
|
||||||
|
return shelf_life_days
|
@ -0,0 +1,29 @@
|
|||||||
|
# Generated by Django 5.1.4 on 2025-01-08 14:18
|
||||||
|
|
||||||
|
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='Наименование товара')),
|
||||||
|
('barcode', models.CharField(max_length=50, unique=True, verbose_name='Штрих-код')),
|
||||||
|
('shelf_life_days', models.PositiveIntegerField(verbose_name='Срок годности (дни)')),
|
||||||
|
('dimensions', models.CharField(max_length=255, verbose_name='Размеры')),
|
||||||
|
('unit_of_measure', models.CharField(max_length=50, verbose_name='Единицы измерения')),
|
||||||
|
('manufacturer', models.CharField(max_length=255, verbose_name='Производитель')),
|
||||||
|
('category', models.CharField(choices=[('Food', 'Продукты'), ('Electronics', 'Электроника'), ('Clothing', 'Одежда'), ('Other', 'Другое')], max_length=50, verbose_name='Категория')),
|
||||||
|
('storage_temperature', models.CharField(max_length=50, verbose_name='Температурные условия хранения')),
|
||||||
|
('promotion', models.CharField(blank=True, choices=[('1+1', '1+1'), ('2+1', '2+1')], max_length=10, null=True, verbose_name='Акция')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,26 @@
|
|||||||
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
|
class Product(models.Model):
|
||||||
|
CATEGORY_CHOICES = [
|
||||||
|
('Food', 'Продукты'),
|
||||||
|
('Electronics', 'Электроника'),
|
||||||
|
('Clothing', 'Одежда'),
|
||||||
|
('Other', 'Другое'),
|
||||||
|
]
|
||||||
|
PROMOTION_CHOICES = [
|
||||||
|
('1+1', '1+1'),
|
||||||
|
('2+1', '2+1'),
|
||||||
|
]
|
||||||
|
name = models.CharField(max_length=255, verbose_name="Наименование товара")
|
||||||
|
barcode = models.CharField(max_length=50, unique=True, verbose_name="Штрих-код")
|
||||||
|
shelf_life_days = models.PositiveIntegerField(verbose_name="Срок годности (дни)")
|
||||||
|
dimensions = models.CharField(max_length=255, verbose_name="Размеры")
|
||||||
|
unit_of_measure = models.CharField(max_length=50, verbose_name="Единицы измерения")
|
||||||
|
manufacturer = models.CharField(max_length=255, verbose_name="Производитель")
|
||||||
|
category = models.CharField(max_length=50, choices=CATEGORY_CHOICES, verbose_name="Категория")
|
||||||
|
storage_temperature = models.CharField(max_length=50, verbose_name="Температурные условия хранения")
|
||||||
|
promotion = models.CharField(max_length=10, choices=PROMOTION_CHOICES, verbose_name="Акция", blank=True, null=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
@ -0,0 +1,7 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
from .models import Product
|
||||||
|
|
||||||
|
class ProductSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Product
|
||||||
|
fields = '__all__'
|
@ -0,0 +1,13 @@
|
|||||||
|
{% for product in products %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ product.name }}</td>
|
||||||
|
<td>{{ product.barcode }}</td>
|
||||||
|
<td>{{ product.category }}</td>
|
||||||
|
<td>{{ product.shelf_life_days }}</td>
|
||||||
|
<td>{{ product.promotion }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{% url 'product_update' product.id %}">Изменить</a>
|
||||||
|
<a href="{% url 'product_delete' product.id %}">Удалить</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
@ -0,0 +1,18 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
from .models import Product
|
||||||
|
|
||||||
|
class ProductTestCase(TestCase):
|
||||||
|
def test_product_creation(self):
|
||||||
|
product = Product.objects.create(
|
||||||
|
name="Тестовый товар",
|
||||||
|
barcode="1234567890123",
|
||||||
|
shelf_life_days=365,
|
||||||
|
dimensions="10x10x10",
|
||||||
|
unit_of_measure="шт.",
|
||||||
|
manufacturer="Производитель",
|
||||||
|
category="Food",
|
||||||
|
storage_temperature="+4C",
|
||||||
|
promotion="1+1"
|
||||||
|
)
|
||||||
|
self.assertEqual(Product.objects.count(), 1)
|
||||||
|
self.assertEqual(product.name, "Тестовый товар")
|
@ -0,0 +1,42 @@
|
|||||||
|
import logging # Импортируем библиотеку для логирования
|
||||||
|
from django.shortcuts import render, get_object_or_404, redirect
|
||||||
|
from .models import Product
|
||||||
|
from .forms import ProductForm
|
||||||
|
|
||||||
|
# Настраиваем логгер
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def product_list(request):
|
||||||
|
products = Product.objects.all()
|
||||||
|
return render(request, 'product_directory/product_list.html', {'products': products})
|
||||||
|
|
||||||
|
def product_create(request):
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = ProductForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
product = form.save()
|
||||||
|
logger.info(f"Пользователь {request.user} создал товар '{product.name}'")
|
||||||
|
return redirect('product_list')
|
||||||
|
else:
|
||||||
|
form = ProductForm()
|
||||||
|
return render(request, 'product_directory/product_form.html', {'form': form})
|
||||||
|
|
||||||
|
def product_update(request, pk):
|
||||||
|
product = get_object_or_404(Product, pk=pk)
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = ProductForm(request.POST, instance=product)
|
||||||
|
if form.is_valid():
|
||||||
|
product = form.save()
|
||||||
|
logger.info(f"Пользователь {request.user} обновил товар '{product.name}'")
|
||||||
|
return redirect('product_list')
|
||||||
|
else:
|
||||||
|
form = ProductForm(instance=product)
|
||||||
|
return render(request, 'product_directory/product_form.html', {'form': form})
|
||||||
|
|
||||||
|
def product_delete(request, pk):
|
||||||
|
product = get_object_or_404(Product, pk=pk)
|
||||||
|
if request.method == 'POST':
|
||||||
|
logger.warning(f"Пользователь {request.user} удалил товар '{product.name}'")
|
||||||
|
product.delete()
|
||||||
|
return redirect('product_list')
|
||||||
|
return render(request, 'product_directory/product_confirm_delete.html', {'product': product})
|
Loading…
Reference in new issue