class CartProduct(models.Model):
user = models.ForeignKey('Customer', verbose_name='Покупатель', on_delete=models.CASCADE)
cart = models.ForeignKey('Cart', verbose_name='Корзина', on_delete=models.CASCADE, related_name='related_products')
product = models.ForeignKey(Product, verbose_name='Товар', on_delete=models.CASCADE)
qty = models.PositiveIntegerField(default=1)
final_price = models.DecimalField(max_digits=9, decimal_places=2, verbose_name='Общая цена')
def __str__(self):
return "Продукт: {} (для корзины)".format(self.product.title)
def save(self, *args, **kwargs):
self.final_price = self.qty * self.product.price
super().save(*args, **kwargs)
class Cart(models.Model):
owner = models.ForeignKey('Customer', null=True, verbose_name='Владелец', on_delete=models.CASCADE)
products = models.ManyToManyField(CartProduct, blank=True, related_name='related_cart')
total_products = models.PositiveIntegerField(default=0)
final_price = models.DecimalField(max_digits=9, default=0, decimal_places=2, verbose_name='Общая цена')
in_order = models.BooleanField(default=False)
for_anonymous_user = models.BooleanField(default=False)
def __str__(self):
return str(self.id)
from django.db import models
from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType
from django.urls import reverse
from django.utils import timezone
User = get_user_model()
class Category(models.Model):
name = models.CharField(max_length=255, verbose_name='Имя категории')
slug = models.SlugField(unique=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('category_detail', kwargs={'slug': self.slug})
class Product(models.Model):
category = models.ForeignKey(Category, verbose_name='Категория', on_delete=models.CASCADE)
title = models.CharField(max_length=255, verbose_name='Наименование')
slug = models.SlugField(unique=True)
image = models.ImageField(verbose_name='Изображение')
description = models.TextField(verbose_name='Описание', null=True)
price = models.DecimalField(max_digits=9, decimal_places=2, verbose_name='Цена')
features = models.ManyToManyField("specs.ProductFeatures", blank=True, related_name='features_for_product')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('product_detail', kwargs={'slug': self.slug})
def get_features(self):
return {f.feature.feature_name: ' '.join([f.value, f.feature.unit or ""]) for f in self.features.all()}
class CartProduct(models.Model):
user = models.ForeignKey('Customer', verbose_name='Покупатель', on_delete=models.CASCADE)
cart = models.ForeignKey('Cart', verbose_name='Корзина', on_delete=models.CASCADE, related_name='related_products')
product = models.ForeignKey(Product, verbose_name='Товар', on_delete=models.CASCADE)
qty = models.PositiveIntegerField(default=1)
final_price = models.DecimalField(max_digits=9, decimal_places=2, verbose_name='Общая цена')
def __str__(self):
return "Продукт: {} (для корзины)".format(self.product.title)
def save(self, *args, **kwargs):
self.final_price = self.qty * self.product.price
super().save(*args, **kwargs)
class Cart(models.Model):
owner = models.ForeignKey('Customer', null=True, verbose_name='Владелец', on_delete=models.CASCADE)
products = models.ManyToManyField(CartProduct, blank=True, related_name='related_cart')
total_products = models.PositiveIntegerField(default=0)
final_price = models.DecimalField(max_digits=9, default=0, decimal_places=2, verbose_name='Общая цена')
in_order = models.BooleanField(default=False)
for_anonymous_user = models.BooleanField(default=False)
def __str__(self):
return str(self.id)
class Customer(models.Model):
user = models.ForeignKey(User, verbose_name='Пользователь', on_delete=models.CASCADE)
phone = models.CharField(max_length=20, verbose_name='Номер телефона', null=True, blank=True)
address = models.CharField(max_length=255, verbose_name='Адрес', null=True, blank=True)
orders = models.ManyToManyField('Order', verbose_name='Заказы покупателя', related_name='related_order')
def __str__(self):
return "Покупатель: {} {}".format(self.user.first_name, self.user.last_name)
class Order(models.Model):
STATUS_NEW = 'new'
STATUS_IN_PROGRESS = 'in_progress'
STATUS_READY = 'is_ready'
STATUS_COMPLETED = 'completed'
BUYING_TYPE_SELF = 'self'
BUYING_TYPE_DELIVERY = 'delivery'
STATUS_CHOICES = (
(STATUS_NEW, 'Новый заказ'),
(STATUS_IN_PROGRESS, 'Заказ в обработке'),
(STATUS_READY, 'Заказ готов'),
(STATUS_COMPLETED, 'Заказ выполнен')
)
BUYING_TYPE_CHOICES = (
(BUYING_TYPE_SELF, 'Самовывоз'),
(BUYING_TYPE_DELIVERY, 'Доставка')
)
customer = models.ForeignKey(Customer, verbose_name='Покупатель', related_name='related_orders', on_delete=models.CASCADE)
first_name = models.CharField(max_length=255, verbose_name='Имя')
last_name = models.CharField(max_length=255, verbose_name='Фамилия')
phone = models.CharField(max_length=20, verbose_name='Телефон')
cart = models.ForeignKey(Cart, verbose_name='Корзина', on_delete=models.CASCADE, null=True, blank=True)
address = models.CharField(max_length=1024, verbose_name='Адрес', null=True, blank=True)
status = models.CharField(
max_length=100,
verbose_name='Статус заказ',
choices=STATUS_CHOICES,
default=STATUS_NEW
)
buying_type = models.CharField(
max_length=100,
verbose_name='Тип заказа',
choices=BUYING_TYPE_CHOICES,
default=BUYING_TYPE_SELF
)
comment = models.TextField(verbose_name='Комментарий к заказу', null=True, blank=True)
created_at = models.DateTimeField(auto_now=True, verbose_name='Дата создания заказа')
order_date = models.DateField(verbose_name='Дата получения заказа', default=timezone.now)
def __str__(self):
return str(self.id)
import operator
from functools import reduce
from itertools import chain
from django.db import transaction
from django.db.models import Q
from django.shortcuts import render
from django.contrib import messages
from django.contrib.auth import login, authenticate
from django.http import HttpResponseRedirect
from django.views.generic import DetailView, View
from .models import Category, Customer, Cart, CartProduct, Product
from .mixins import CartMixin
from .forms import OrderForm, LoginForm, RegistrationForm
from .utils import recalc_cart
from specs.models import ProductFeatures
class MyQ(Q):
default = 'OR'
class BaseView(CartMixin, View):
def get(self, request, *args, **kwargs):
categories = Category.objects.all()
products = Product.objects.all()
context = {
'categories': categories,
'products': products,
'cart': self.cart
}
return render(request, 'base.html', context)
class ProductDetailView(CartMixin, DetailView):
model = Product
context_object_name = 'product'
template_name = 'product_detail.html'
slug_url_kwarg = 'slug'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['categories'] = self.get_object().category.__class__.objects.all()
context['cart'] = self.cart
return context
class CategoryDetailView(CartMixin, DetailView):
model = Category
queryset = Category.objects.all()
context_object_name = 'category'
template_name = 'category_detail.html'
slug_url_kwarg = 'slug'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
query = self.request.GET.get('search')
category = self.get_object()
context['cart'] = self.cart
context['categories'] = self.model.objects.all()
if not query and not self.request.GET:
context['category_products'] = category.product_set.all()
return context
if query:
products = category.product_set.filter(Q(title__icontains=query))
context['category_products'] = products
return context
url_kwargs = {}
for item in self.request.GET:
if len(self.request.GET.getlist(item)) > 1:
url_kwargs[item] = self.request.GET.getlist(item)
else:
url_kwargs[item] = self.request.GET.get(item)
q_condition_queries = Q()
for key, value in url_kwargs.items():
if isinstance(value, list):
q_condition_queries.add(Q(**{'value__in': value}), Q.OR)
else:
q_condition_queries.add(Q(**{'value': value}), Q.OR)
pf = ProductFeatures.objects.filter(
q_condition_queries
).prefetch_related('product', 'feature').values('product_id')
products = Product.objects.filter(id__in=[pf_['product_id'] for pf_ in pf])
context['category_products'] = products
return context
class AddToCartView(CartMixin, View):
def get(self, request, *args, **kwargs):
product_slug = kwargs.get('slug')
product = Product.objects.get(slug=product_slug)
cart_product, created = CartProduct.objects.get_or_create(
user=self.cart.owner, cart=self.cart, product=product
)
if created:
self.cart.products.add(cart_product)
recalc_cart(self.cart)
messages.add_message(request, messages.INFO, "Товар успешно добавлен")
return HttpResponseRedirect('/cart/')
class DeleteFromCartView(CartMixin, View):
def get(self, request, *args, **kwargs):
product_slug = kwargs.get('slug')
product = Product.objects.get(slug=product_slug)
cart_product = CartProduct.objects.get(
user=self.cart.owner, cart=self.cart, product=product
)
self.cart.products.remove(cart_product)
cart_product.delete()
recalc_cart(self.cart)
messages.add_message(request, messages.INFO, "Товар успешно удален")
return HttpResponseRedirect('/cart/')
class ChangeQTYView(CartMixin, View):
def post(self, request, *args, **kwargs):
product_slug = kwargs.get('slug')
product = Product.objects.get(slug=product_slug)
cart_product = CartProduct.objects.get(
user=self.cart.owner, cart=self.cart, product=product
)
qty = int(request.POST.get('qty'))
cart_product.qty = qty
cart_product.save()
recalc_cart(self.cart)
messages.add_message(request, messages.INFO, "Кол-во успешно изменено")
return HttpResponseRedirect('/cart/')
class CartView(CartMixin, View):
def get(self, request, *args, **kwargs):
categories = Category.objects.all()
context = {
'cart': self.cart,
'categories': categories
}
return render(request, 'cart.html', context)
class CheckoutView(CartMixin, View):
def get(self, request, *args, **kwargs):
categories = Category.objects.all()
form = OrderForm(request.POST or None)
context = {
'cart': self.cart,
'categories': categories,
'form': form
}
return render(request, 'checkout.html', context)
class MakeOrderView(CartMixin, View):
@transaction.atomic
def post(self, request, *args, **kwargs):
form = OrderForm(request.POST or None)
customer = Customer.objects.get(user=request.user)
if form.is_valid():
new_order = form.save(commit=False)
new_order.customer = customer
new_order.first_name = form.cleaned_data['first_name']
new_order.last_name = form.cleaned_data['last_name']
new_order.phone = form.cleaned_data['phone']
new_order.address = form.cleaned_data['address']
new_order.buying_type = form.cleaned_data['buying_type']
new_order.order_date = form.cleaned_data['order_date']
new_order.comment = form.cleaned_data['comment']
new_order.save()
self.cart.in_order = True
self.cart.save()
new_order.cart = self.cart
new_order.save()
customer.orders.add(new_order)
messages.add_message(request, messages.INFO, 'Спасибо за заказ! Менеджер с Вами свяжется')
return HttpResponseRedirect('/')
return HttpResponseRedirect('/checkout/')
class LoginView(CartMixin, View):
def get(self, request, *args, **kwargs):
form = LoginForm(request.POST or None)
categories = Category.objects.all()
context = {
'form': form,
'categories': categories,
'cart': self.cart
}
return render(request, 'login.html', context)
def post(self, request, *args, **kwargs):
form = LoginForm(request.POST or None)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(
username=username, password=password
)
if user:
login(request, user)
return HttpResponseRedirect('/')
categories = Category.objects.all()
context = {
'form': form,
'cart': self.cart,
'categories': categories
}
return render(request, 'login.html', context)
class RegistrationView(CartMixin, View):
def get(self, request, *args, **kwargs):
form = RegistrationForm(request.POST or None)
categories = Category.objects.all()
context = {
'form': form,
'categories': categories,
'cart': self.cart
}
return render(request, 'registration.html', context)
def post(self, request, *args, **kwargs):
form = RegistrationForm(request.POST or None)
if form.is_valid():
new_user = form.save(commit=False)
new_user.username = form.cleaned_data['username']
new_user.email = form.cleaned_data['email']
new_user.first_name = form.cleaned_data['first_name']
new_user.last_name = form.cleaned_data['last_name']
new_user.save()
new_user.set_password(form.cleaned_data['password'])
new_user.save()
Customer.objects.create(
user=new_user,
phone=form.cleaned_data['phone'],
address=form.cleaned_data['address']
)
user = authenticate(
username=new_user.username, password=form.cleaned_data['password']
)
login(request, user)
return HttpResponseRedirect('/')
categories = Category.objects.all()
context = {
'form': form,
'categories': categories,
'cart': self.cart
}
return render(request, 'registration.html', context)