feat: MVP-скелет площадки (Django + MySQL/SQLite, модели по ТЗ §4, базовые страницы)

This commit is contained in:
apuc committed 2026-09-23 16:47:57 +03:00
1 parent e5f312a00f
commit 8218a568ce
67 files changed
+1929

No files matched your search

View File
Whitespace-only changes.
+10
View File
@@ -0,0 +1,10 @@
from django.contrib import admin
from .models import Review
@admin.register(Review)
class ReviewAdmin(admin.ModelAdmin):
list_display = ('id', 'author', 'product', 'service', 'rating', 'status', 'created_at')
list_filter = ('status', 'rating')
search_fields = ('author__username', 'text')
+7
View File
@@ -0,0 +1,7 @@
from django.apps import AppConfig
class ReviewsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.reviews'
+40
View File
@@ -0,0 +1,40 @@
# Generated by Django 5.1.15 on 2026-09-23 13:44
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('catalog', '0001_initial'),
('orders', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Review',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('rating', models.PositiveSmallIntegerField(default=5, verbose_name='Оценка')),
('text', models.TextField(blank=True, verbose_name='Текст отзыва')),
('images', models.JSONField(blank=True, default=list, verbose_name='Фото')),
('brand_reply', models.TextField(blank=True, verbose_name='Ответ бренда')),
('status', models.CharField(choices=[('pending', 'На модерации'), ('published', 'Опубликован'), ('rejected', 'Отклонён')], default='pending', max_length=20, verbose_name='Статус')),
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Создан')),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reviews', to=settings.AUTH_USER_MODEL, verbose_name='Автор')),
('order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reviews', to='orders.order', verbose_name='Заказ')),
('product', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reviews', to='catalog.product', verbose_name='Товар')),
('service', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reviews', to='catalog.service', verbose_name='Услуга')),
],
options={
'verbose_name': 'Отзыв',
'verbose_name_plural': 'Отзывы',
'ordering': ('-created_at',),
},
),
]
View File
Whitespace-only changes.
+50
View File
@@ -0,0 +1,50 @@
from django.conf import settings
from django.db import models
from apps.catalog.models import Product, Service
from apps.orders.models import Order
class ReviewStatus(models.TextChoices):
PENDING = 'pending', 'На модерации'
PUBLISHED = 'published', 'Опубликован'
REJECTED = 'rejected', 'Отклонён'
class Review(models.Model):
"""Отзыв на товар/услугу после подтверждённого заказа (ТЗ §3.5)."""
order = models.ForeignKey(
Order, on_delete=models.CASCADE, related_name='reviews',
verbose_name='Заказ',
)
author = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
related_name='reviews', verbose_name='Автор',
)
product = models.ForeignKey(
Product, null=True, blank=True, on_delete=models.CASCADE,
related_name='reviews', verbose_name='Товар',
)
service = models.ForeignKey(
Service, null=True, blank=True, on_delete=models.CASCADE,
related_name='reviews', verbose_name='Услуга',
)
rating = models.PositiveSmallIntegerField('Оценка', default=5)
text = models.TextField('Текст отзыва', blank=True)
images = models.JSONField('Фото', default=list, blank=True)
brand_reply = models.TextField('Ответ бренда', blank=True)
status = models.CharField(
'Статус', max_length=20, choices=ReviewStatus.choices,
default=ReviewStatus.PENDING,
)
created_at = models.DateTimeField('Создан', auto_now_add=True)
class Meta:
verbose_name = 'Отзыв'
verbose_name_plural = 'Отзывы'
ordering = ('-created_at',)
def __str__(self):
return f'Отзыв #{self.pk} ({self.rating}/5)'
+3
View File
@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.
+3
View File
@@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.