refactor product search form. Fix logic of getting active product directory

remotes/origin/HEAD
Max Yakovenko 8 years ago
parent fcc5e223fa
commit d976d220eb
  1. 8
      products/context_processors.py
  2. 11
      products/forms.py
  3. 26
      products/models.py
  4. 9
      products/urls.py
  5. 71
      products/views.py

@ -3,6 +3,7 @@ from products.models import ProductCategory
def product_search_form(request): def product_search_form(request):
#@TODO: APPLY SEARCH IN THE CONTEXT OF CHOSSEN DIRECTORY
left_product_search_form = ProductSearchForm(submit_css_class='left-menu__search-btn') left_product_search_form = ProductSearchForm(submit_css_class='left-menu__search-btn')
content_product_search_form = ProductSearchForm(submit_css_class='content__search-btn') content_product_search_form = ProductSearchForm(submit_css_class='content__search-btn')
if ProductSearchForm.form_action.__str__() in request.path and request.GET.get('name'): if ProductSearchForm.form_action.__str__() in request.path and request.GET.get('name'):
@ -14,4 +15,9 @@ def product_search_form(request):
def product_root_categories(request): def product_root_categories(request):
return {'product_root_categories': ProductCategory.objects.get_root_categories()} current_category = request.resolver_match.kwargs.get('category_slug',None)
current_category = ProductCategory.objects.filter(slug=current_category).first()
return {
'product_categories': ProductCategory.active.get_categories(current_category),
'the_product_category' : current_category
}

@ -32,18 +32,21 @@
from crispy_forms.layout import Layout, Field, Button from crispy_forms.layout import Layout, Field, Button
from django import forms from django import forms
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from django.forms import formset_factory
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from .models import Product from .models import Product, ProductAttribute
class ProductFilterForm(forms.Form): class ProductFilterForm(forms.Form):
pass def __init__(self, *args,**kwargs):
super().__init__(*args,**kwargs)
class ProductSearchForm(forms.ModelForm): class ProductSearchForm(forms.ModelForm):
field_template = 'bootstrap/forms/product_search.html' field_template = 'bootstrap/forms/product_search.html'
form_action = reverse_lazy('products:product_search') form_action = reverse_lazy('products:product_list')
submit_css_class = None submit_css_class = None
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -61,3 +64,5 @@ class ProductSearchForm(forms.ModelForm):
class Meta: class Meta:
model = Product model = Product
fields = ['name'] fields = ['name']
inline_product_filter_formset = formset_factory(ProductFilterForm,extra=ProductAttribute.objects.all(),can_order=True,can_delete=False)

@ -12,7 +12,7 @@ from mptt import (
from mptt.models import MPTTModel, TreeForeignKey from mptt.models import MPTTModel, TreeForeignKey
from autoslug import AutoSlugField from autoslug import AutoSlugField
from core.models import AbstractStatusModel, ActualOnlyManager, AbstractDateTimeModel from core.models import AbstractStatusModel, ActualOnlyManager, AbstractDateTimeModel, ActiveOnlyManager
# ---------------------------------- COMMON PRODUCT STATUS ---------------------------------------# # ---------------------------------- COMMON PRODUCT STATUS ---------------------------------------#
# Create your models here. # Create your models here.
@ -41,7 +41,7 @@ PRODUCT_ATTRIBUTE_TYPE_CHOICES = (
PRODUCT_ATTRIBUTE_TYPE_DEFAULT = PRODUCT_ATTRIBUTE_TYPE_NONE PRODUCT_ATTRIBUTE_TYPE_DEFAULT = PRODUCT_ATTRIBUTE_TYPE_NONE
class ProductAttributeManager(models.Manager): class ProductAttributeManager(ActiveOnlyManager):
def get_range_type_attributes(self, product=None): def get_range_type_attributes(self, product=None):
pass pass
@ -90,18 +90,26 @@ class Manufacturer(AbstractStatusModel):
class ProductCategoryManager(mptt_managers.TreeManager, ActualOnlyManager): class ProductCategoryManager(mptt_managers.TreeManager, ActualOnlyManager):
def get_root_categories(self): def get_categories(self, parent=None):
return self.get_queryset().all() return self.get_queryset().filter(parent=parent).all()
class ProductActiveCategoryManager(mptt_models.TreeManager, ActiveOnlyManager):
def get_categories(self, parent=None):
return self.get_queryset().filter(parent=parent).all()
class ProductCategory(MPTTModel, AbstractStatusModel): class ProductCategory(MPTTModel, AbstractStatusModel):
name = models.CharField(db_index=True, unique=True, max_length=64, blank=True, null=True, default=None) name = models.CharField(_('название'), db_index=True, unique=True, max_length=64, blank=True, null=True,
slug = AutoSlugField(populate_from='name') default=None)
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children') slug = AutoSlugField(_('slug'), populate_from='name')
image = models.ImageField(upload_to='categories', blank=True, verbose_name="image of category") parent = TreeForeignKey('self', verbose_name=_('родительская категория'), on_delete=models.CASCADE, null=True,
blank=True, related_name='children')
image = models.ImageField(_("иконка"), upload_to='categories', blank=True)
status = models.SmallIntegerField(_('статус'), default=STATUS_DEFAULT, choices=STATUS_CHOICES) status = models.SmallIntegerField(_('статус'), default=STATUS_DEFAULT, choices=STATUS_CHOICES)
objects = ProductCategoryManager() objects = ProductCategoryManager()
active = ProductActiveCategoryManager()
def __str__(self): def __str__(self):
return self.name return self.name
@ -199,7 +207,7 @@ class ProductImage(AbstractStatusModel):
}) })
product = models.ForeignKey(Product, on_delete=models.CASCADE) product = models.ForeignKey(Product, on_delete=models.CASCADE)
status = models.SmallIntegerField(_('Статус'),choices=STATUS_CHOICES, default=STATUS_DEFAULT) status = models.SmallIntegerField(_('Статус'), choices=STATUS_CHOICES, default=STATUS_DEFAULT)
filename = models.CharField(_('Имя файла'), max_length=255) filename = models.CharField(_('Имя файла'), max_length=255)
image = models.FileField(_('Изображение'), upload_to=get_file_path, max_length=500) image = models.FileField(_('Изображение'), upload_to=get_file_path, max_length=500)
is_default = models.BooleanField(_('По умолчанию'), default=False) is_default = models.BooleanField(_('По умолчанию'), default=False)

@ -20,9 +20,12 @@ from .models import ProductCategory
urlpatterns = [ urlpatterns = [
re_path(r'^search/$', views.ProductSearchView.as_view(), name='product_search'),
re_path(r'^product/(?P<product_slug>\w+)/$', views.ProductDetailsView.as_view(), name='product_details'), re_path(r'^list/$', views.ProductListView.as_view(), name='product_list'),
re_path(r'^category/list/$', views.ProductCategoryListView.as_view(), name='product_category'), re_path(r'^list/(?P<category_slug>\w+)/$', views.ProductListView.as_view(),name='product_list'),
re_path(r'^(?P<product_slug>\w+)/$', views.ProductDetailsView.as_view(), name='product_details'),
# Uncomment for elasticsearch # Uncomment for elasticsearch
# url(r'^autocomplete/$', autocomplete), # url(r'^autocomplete/$', autocomplete),

@ -7,6 +7,7 @@ from django.contrib import auth
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.views.generic import ListView, DetailView from django.views.generic import ListView, DetailView
from core.views import ProtectedListView
from .models import ( from .models import (
Manufacturer,Product,ProductCategory Manufacturer,Product,ProductCategory
) )
@ -24,69 +25,57 @@ class ProductDetailsView(DetailView):
template_name = 'products/product_detail.html' template_name = 'products/product_detail.html'
class ProductSearchView(ListView):
model = Product
template_name = 'products/product_search.html'
context_object_name = 'products'
paginate_by = settings.DEFAULT_PAGE_AMOUNT
title = _('Поиск товара')
def get_queryset(self):
queryset = super().get_queryset()
if self.kwargs.get('name'):
queryset = queryset.filter(name__icontains=self.kwargs.get('name'))
return queryset
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(object_list=object_list, **kwargs)
context['title'] = self.title + ":" + self.request.GET.get('name', '')
return context
class ProductListView(ListView): class ProductListView(ListView):
model = Product model = Product
form = ProductSearchForm
template_name = 'products/product_list.html' template_name = 'products/product_list.html'
context_object_name = 'products' context_object_name = 'products'
paginate_by = settings.DEFAULT_PAGE_AMOUNT paginate_by = settings.DEFAULT_PAGE_AMOUNT
title = _('Список товаров') title = _('Список товаров')
def get_title(self):
if self.request.GET.get('name'):
return _('Поиск товара') + ":" + self.request.GET.get('name')
title = _('Список товаров')
if self.request.resolver_match.kwargs.get('category_slug'):
return title + ":" + self.request.resolver_match.kwargs.get('category_slug')
return title
def get_queryset(self): def get_queryset(self):
queryset = super().get_queryset() queryset = super().get_queryset()
if self.kwargs.get('name'):
queryset = queryset.filter(name__icontains=self.kwargs.get('name'))
return queryset return queryset
def get_context_data(self, *, object_list=None, **kwargs): def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(object_list=object_list, **kwargs) context = super().get_context_data(object_list=object_list, **kwargs)
context['title'] = self.title context['title'] = self.get_title()
return context return context
class ProductCategoryListView(ListView):
model = ProductCategory
template_name = 'products/product_category_list.html'
# Uncomment for elasticsearch # Uncomment for elasticsearch
# from .layout import FacetedProductSearchForm # from .layout import FacetedProductSearchForm
# from haystack.generic_views import FacetedSearchView as BaseFacetedSearchView # from haystack.generic_views import FacetedSearchView as BaseFacetedSearchView
# from haystack.query import SearchQuerySet # from haystack.query import SearchQuerySet
def serialize_decimal(obj): # def serialize_decimal(obj):
if isinstance(obj, decimal.Decimal): # if isinstance(obj, decimal.Decimal):
return str(obj) # return str(obj)
return json.JSONEncoder.default(obj) # return json.JSONEncoder.default(obj)
#
#
def producerslist(request): # def producerslist(request):
username = auth.get_user(request).username # username = auth.get_user(request).username
# category = None # # category = None
# categories = ProductCategory.objects.filter(level__lte=0) # # categories = ProductCategory.objects.filter(level__lte=0)
# products = Product.objects.filter(is_active=True) # # products = Product.objects.filter(is_active=True)
producers = Manufacturer.objects.filter(is_active=True) # producers = Manufacturer.objects.filter(is_active=True)
# if category_slug: # # if category_slug:
# category = get_object_or_404(ProductCategory, slug=category_slug) # # category = get_object_or_404(ProductCategory, slug=category_slug)
# products = products.filter(category__in=category.get_descendants(include_self=True)) # # products = products.filter(category__in=category.get_descendants(include_self=True))
return render(request, 'products/list.html', locals()) # return render(request, 'products/list.html', locals())
# def categorieslist(request, producer_slug, category_slug=None): # def categorieslist(request, producer_slug, category_slug=None):
# username = accounts_ext.get_user(request).username # username = accounts_ext.get_user(request).username

Loading…
Cancel
Save