can't click category url Django 1.10 - django

enter image description here
I see URL, but click on it not goving at page.
If I go directly to the link, the page opens. In my opinion the matter lies in the def post_list
model
class Category(models.Model):
name = models.CharField(max_length=128, unique=True, verbose_name='Название')
slug = models.SlugField(unique=True)
image = models.ImageField(null=True, blank=True, verbose_name='Изображение')
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Category, self).save(*args, **kwargs)
class Meta:
verbose_name = 'Категории'
verbose_name_plural = 'Категории'
def __str__(self): # For Python 2, use __unicode__ too
return self.name
def get_absolute_url(self):
return reverse('show_category', kwargs={'slug': self.slug})
class Post(models.Model):
category = models.ForeignKey(Category, default=1, verbose_name='Категория')
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1, verbose_name='Пользователь')
title = models.CharField(max_length=120, verbose_name='Заголовок')
slug = models.SlugField(unique=True)
image = models.ImageField(null=True, blank=True, verbose_name='Изображение')
content = models.TextField(max_length=10000, verbose_name='Контент')
updated = models.DateTimeField(auto_now=True, auto_now_add=False, verbose_name='Обновлено')
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True, verbose_name='Создано')
keywords = models.CharField(max_length=1024, blank=True, null=True)
description = models.CharField(max_length=1024, blank=True, null=True)
class Meta:
verbose_name = 'Статьи'
verbose_name_plural = 'Статьи'
ordering = ["-timestamp", "-updated"]
def __str__(self): # For Python 2, use __unicode__ too
return self.title
def get_absolute_url(self):
return reverse('detail', kwargs={'slug': self.slug, 'category': self.category})
views
only problem page
def post_list(request):
queryset_list = Post.objects.all()
category_list = Category.objects.all()
search = request.GET.get("s")
if search:
queryset_list = queryset_list.filter(
Q(title__icontains=search) |
Q(content__icontains=search) #|
#Q(user__first_name__icontains=search) |
#Q(user__last_name__icontains=search)
).distinct()
paginator = Paginator(queryset_list, 5) # Show 5 contacts per page
page = request.GET.get('page')
try:
queryset = paginator.page(page)
except PageNotAnInteger:
queryset = paginator.page(1)
except EmptyPage:
queryset = paginator.page(paginator.num_pages)
context = {
"object_list": queryset,
"category_list": category_list,
"title": "Новое"
}
return render(request, "post_list.html", context)
urls
from .views import (
post_list,
post_detail,
show_category,
)
urlpatterns = [
url(r'^$', post_list, name="list"),
url(r'^(?P<category>[-\w]+)/(?P<slug>[-\w]+)/$', post_detail, name="detail"),
url(r'^(?P<slug>[-\w]+)/$', show_category, name='show_category'),
]
html
{% for cat in category_list %}
<li>{{ cat.name }}</li>
{% endfor %}

Related

Render all products that relate to one of subcategories of one category, in category page

I had a question. I am creating an ecommerce website in django. There, I have categories and subcategories. When I enter to subcategory page, I able to render all products that relate to this subcategory. But, when I wanted to render all product that relate on one parent category, I am having troubles. So, I have some subcategories in one category. In that category page, I want to render all products that relate to one of subcategories of this category. Can you help me please?
models.py
class Category(models.Model):
parent = models.ForeignKey('self', related_name='children', on_delete=models.CASCADE, blank=True, null=True)
title = models.CharField(max_length=255)
slug = models.SlugField(max_length=255)
image = models.ImageField(null=True, blank=True, verbose_name="Изображение")
ordering = models.IntegerField(default=0)
is_featured = models.BooleanField(default=False)
class Meta:
verbose_name_plural = 'Categories'
ordering = ('ordering',)
def __str__(self):
if self.parent is not None:
return f"{self.parent}/{self.title}"
return self.title
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
def get_absolute_url(self):
return '/%s/' % (self.slug)
class Product(models.Model):
category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
parent = models.ForeignKey('self', related_name='variants', on_delete=models.CASCADE, blank=True, null=True)
name = models.CharField(max_length=200, verbose_name="Название продукта")
price = models.IntegerField(verbose_name="Цена")
slug = models.SlugField(max_length=255)
description = models.CharField(max_length=5000,blank=True, verbose_name="Описание:")
image = models.ImageField(null=True, blank=True, verbose_name="Изображение")
novinki = models.BooleanField(default=False, verbose_name="Новинки")
popularnye = models.BooleanField(default=False, verbose_name="Популарные")
def __str__(self):
return self.name
class Meta:
verbose_name = 'Продукты'
verbose_name_plural = "Продукты"
#property
def imageURL(self):
try:
url = self.image.url
except:
url = ''
return url
views.py
def category_detail(request, slug):
data = cartData(request)
cartItems = data['cartItems']
order = data['order']
items = data['items']
categories_for_menu = Category.objects.filter(parent=None)[:3]
categories = Category.objects.filter(parent=None)
category = get_object_or_404(Category, slug=slug)
**products_all = Product.objects.filter(category.parent==category)**
print(products_all)
products = category.products.all()
context = {'items' : items, 'order' : order, 'cartItems' : cartItems, 'products':products, 'category':category, 'categories':categories,'categories_for_menu':categories_for_menu,'products_all':products_all}
return render(request, "store/categories.html", context)
Here I want to save all products that relate the category in products_all. Looking forward to your help!
class Category(models.Model):
# ...
root = models.ForeignKey('self', on_delete=models.CASCADE)
# ...
def save(self, *args, **kwargs):
self.root = self.parent.root if self.parent else self
# I didn't debug it. Maybe it has some bug.
super(Category, self).save(*args, **kwargs)
# query
Product.objects.filter(category__root=(...))
I don't agree this answer:
products = Product.objects.filter(Q(category = category)|Q(category__parent = category))
When your category is more than 2 depth, it will be wrong.
You can do it using Q function:
from django.db.models import Q
category = get_object_or_404(Category, slug=slug)
products = Product.objects.filter(Q(category = category)|Q(category__parent = category))

Django Forms - how to add the + sign for a Many2Many field

enter image description hereRelated to Django Forms and Many2Many
I have tried to look for ways to add the + to my django form when I want to add a new post to my webpage.
What I'm looking for is a similar function as the one in admin module. See picture.
I have tried to read though the docs but not sure what to look for. Have anybody build something similar?
my model looks like this
class Wine_taste(models.Model):
title = models.CharField(max_length=128, null=True, blank=True)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
category = models.ManyToManyField('Wine_Category', verbose_name='Kind of Wine',related_name='wcategory')
subcategory = models.ForeignKey('Wine_SubCategory', verbose_name='Wine type',on_delete=models.SET_NULL, null=True, blank=True)
review = models.TextField()
producer_taste = models.ForeignKey('Wine_Producer', verbose_name='Producer or shipper', on_delete=models.SET_NULL, null=True, blank=True )
grape_taste = models.ManyToManyField('Wine_Grapes', verbose_name='Grapes')
country_taste = models.ForeignKey('Wine_Country', verbose_name='Country of origin', on_delete=models.SET_NULL, null=True, blank=True )
sweetness = models.PositiveSmallIntegerField(choices=LEVELRATE_CHOICES, verbose_name='Rate Sweetness')
acid = models.PositiveSmallIntegerField(choices=LEVELRATE_CHOICES, verbose_name='Rate acid level')
fruit = models.PositiveSmallIntegerField(choices=LEVELRATE_CHOICES, verbose_name='Rate fruitness')
taste = models.PositiveSmallIntegerField(choices=RATE_CHOICES, verbose_name='Rate taste')
overall = models.PositiveSmallIntegerField(choices=RATE_CHOICES, verbose_name='Overall rate')
thumbnail = models.ImageField()
timestamp = models.DateTimeField(auto_now_add=True)
featured = models.BooleanField()
previous_post = models.ForeignKey('self', related_name='previous', on_delete=models.SET_NULL, null=True, blank=True)
next_post = models.ForeignKey('self', related_name='next', on_delete=models.SET_NULL, null=True, blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('wine:wine-dyn', kwargs={"id": self.id})
def get_update_url(self):
return reverse('wine:wine-update', kwargs={"id": self.id})
def get_delete_url(self):
return reverse('wine:wine-delete', kwargs={"id": self.id})
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.thumbnail.path)
if img.height > 400:
new_height = 400
new_width = new_height / img.height * img.width
output_size = ((new_height, new_width))
img.thumbnail(output_size)
img.save(self.thumbnail.path)
#property
def get_comments(self):
return self.comments.all().order_by('-timestamp')
#property
def comment_count(self):
return Comment.objects.filter(post=self).count()
#property
def view_count(self):
return PostView.objects.filter(post=self).count()
Blockquote
this is my view:
def wine_detailed_create(request):
title = 'Create'
form = CreateForm(request.POST or None, request.FILES or None)
author = get_author(request.user)
if request.method == 'POST':
if form.is_valid():
form.instance.author = author
form.save()
return redirect (reverse('wine:wine-dyn', kwargs={'id': form.instance.id}))
context = {
'title': title,
'form': form
}
return render(request, 'wine/wine_create.html', context)
and my forms:
class CreateForm(forms.ModelForm):
class Meta:
model = Wine_taste
fields = ('title',
'country_taste',
'category',
'subcategory',
'producer_taste',
'grape_taste',
'review',
'thumbnail',
'sweetness',
'acid',
'fruit',
'taste',
'overall',
'featured',
'previous_post',
'next_post',)
Blockquote
br
Lars

Django: NoReverseMatch at /shop/stickers/minion-cushion/medida-y-cantidad

I've problems when trying to access to the 2nd part of a 2 Steps form.
When clicking on a product, in a given category, for example category 'stickers' and product 'minion-cushion', users are taken to this url:
/shop/stickers/minion-cushion/medida-y-cantidad
In here they'll find a form 'StepOneForm' that only displays a tamanios (sizes in english) and cantidades (quantities in english) both as forms.ChoiceFields.
I'll capture the user's choices for this fields and save the values in the session. And then user should click on Continuar button and should be taken to this url:
/shop/stickers/minion-cushion/subir-arte
Where users will see the 2nd form "StepTwoForm" and the button to submit the form to DataBase.
However, when using this in my StepOneForm template, I get this error:
Continuar
Error:
NoReverseMatch at /shop/stickers/minion-cushion/medida-y-cantidad
Reverse for 'UploadArt' with no arguments not found. 1 pattern(s) tried: ['shop\\/(?P<c_slug>[-a-zA-Z0-9_]+)\\/(?P<product_slug>[-a-zA-Z0-9_]+)\\/subir\\-arte$']
But leaving the a tag href attribute blank lets me access this page without problems (except, obviously, I cannot access the the next page when clicking on Continue).
Continuar
Likes this:
Form in template:
<form method="post">
{% csrf_token %}
<div id="tamanios">
<legend class="text-size20 bold-font"> {{ form.tamanios.label }}</legend>
<ul class="form-items">
<li>
<span>
{{ form.tamanios.0.tag }}
{{ form.tamanios.0.choice_label }}
</span>
</li>
</ul>
</div>
Continuar
</br>
<p>Siguiente: subir imagen</p>
</form>
My urls:
app_name = 'shop'
urlpatterns = [
path('', views.allProdCat, name = 'allProdCat'),
path('<slug:c_slug>', views.allProdCat, name = 'products_by_category'),
path('<slug:c_slug>/<slug:product_slug>/medida-y-cantidad', views.StepOneView.as_view(), name='ProdCatDetail'),
path('<slug:c_slug>/<slug:product_slug>/subir-arte', views.StepTwoView.as_view(), name='UploadArt'),
]
shop/views.py
class StepOneView(FormView):
form_class = StepOneForm
template_name = 'shop/product.html'
success_url = 'shop/subir-arte'
def get_initials(self):
# pre-populate form if someone goes back and forth between forms
initial = super(StepOneView, self).get_initial()
initial['tamanios'] = self.request.session.get('tamanios', None)
initial['cantidades'] = self.request.session.get('cantidades', None)
return initial
# pre-populate form if someone goes back and forth between forms
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['product'] = Product.objects.get(
category__slug=self.kwargs['c_slug'],
slug=self.kwargs['product_slug']
)
return context
def form_valid(self, form):
# In form_valid method we can access the form data in dict format
# and will store it in django session
self.request.session['tamanios'] = form.cleaned_data.get('tamanios')
self.request.session['cantidades'] = form.cleaned_data.get('cantidades')
return HttpResponseRedirect(self.get_success_url())
# here we are going to use CreateView to save the Third step ModelForm
class StepTwoView(CreateView):
form_class = StepTwoForm
template_name = 'shop/subir-arte.html'
success_url = '/'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['product'] = Product.objects.get(
category__slug=self.kwargs['c_slug'],
slug=self.kwargs['product_slug']
)
return context
def form_valid(self, form):
form.instance.tamanios = self.request.session.get('tamanios') # get tamanios from session
form.instance.cantidades = self.request.session.get('cantidades') # get cantidades from session
del self.request.session['cantidades'] # delete cantidades value from session
del self.request.session['tamanios'] # delete tamanios value from session
self.request.session.modified = True
return super(StepTwoView, self).form_valid(form)
shop/models.py
class Category(models.Model):
name = models.CharField(max_length=250, unique=True)
slug = models.SlugField(max_length=250, unique=True)
description = models.TextField(blank=True)
image = models.ImageField(upload_to='category', blank=True)
class Meta:
ordering = ('name',)
verbose_name = 'category'
verbose_name_plural = 'categories'
def get_url(self):
return reverse('shop:products_by_category', args=[self.slug])
def __str__(self):
return '{}'.format(self.name)
class Product(models.Model):
name = models.CharField(max_length=250, unique=True)
slug = models.SlugField(max_length=250, unique=True)
description = models.TextField(blank=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
price = models.DecimalField(max_digits=10, decimal_places=2)
image = models.ImageField(upload_to='product', blank=True)
stock = models.IntegerField()
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('name',)
verbose_name = 'product'
verbose_name_plural = 'products'
def get_url(self):
return reverse('shop:ProdCatDetail', args=[self.category.slug, self.slug])
def __str__(self):
return '{}'.format(self.name)
class TamaniosCantidades(models.Model):
# usuario = models.ForeignKey(User, on_delete=models.DO_NOTHING)
producto = models.ForeignKey(Product, on_delete=models.CASCADE)
tamanios = models.CharField(max_length=10, choices=TAMANIOS)
cantidades = models.CharField(max_length=10, choices=CANTIDADES)
imagenes = models.FileField(upload_to='imagenes/', null=True, blank=True)
# imagenes = models.ImageField(upload_to='category', blank=True)
instrucciones = models.CharField(max_length=200, blank=True, null=True, default='')
uploaded_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.tamanios
shop/forms.py
class StepOneForm(forms.Form):
tamanios = forms.ChoiceField(choices=TAMANIOS, widget=forms.RadioSelect(), label='Selecciona un tamaño')
cantidades = forms.ChoiceField(choices=CANTIDADES, widget=forms.RadioSelect(), label='Selecciona la cantidad')
class StepTwoForm(forms.ModelForm):
instrucciones = forms.CharField(widget=forms.Textarea)
class Meta:
model = TamaniosCantidades
fields = ('imagenes', 'instrucciones')
def __init__(self, *args, **kwargs):
super(StepTwoForm, self).__init__(*args, **kwargs)
self.fields['instrucciones'].required = False
Because uploadart has arguments ( c_slug and product_slug ):
path('<slug:c_slug>/<slug:product_slug>/subir-arte',
views.StepTwoView.as_view(),
name='UploadArt'),
Your url must to inform this arguments:
<a href="{% url 'shop:UploadArt' _some_data_here_ _some_data_here_ %}"
Take a look to django url docs samples

Django slug two in one confusion

I'm trying to display a blog as follows:
domain.com/blog/category/categoryA
domain.com/blog/category/categoryA/post-one
At the moment (1) works successfully, and (2) works partially, so it displays like:
domain.com/blog/post-one
How can I set post category - posts that belong to that category before display post slug?
My urls.py:
url(r'^(?P<slug>[-\w]+)/$', views.post_detail, name='post_detail'),
url(r'^category/(?P<category_slug>[-\w]+)/$', views.list_of_post_by_category, name='list_of_post_by_category'),
My views.py
def list_of_post_by_category(request,category_slug):
categories = Category.objects.all()
post = Post.objects.filter(status='published')
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
post = post.filter(category=category)
template = 'blog/category/list_of_post_by_category.html'
context = {'categories': categories, 'post': post}
return render(request, template, context)
def list_of_post(request):
post = Post.objects.filter(status="published")
template = 'blog/post/list_of_post.html'
context = {'post': post}
return render(request, template, context)
def post_detail(request, slug):
post = get_object_or_404(Post, slug=slug)
template = 'blog/post/post_detail.html'
context = {'post': post}
return render(request, template, context)
My models.py:
class Category(models.Model):
name = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique=True)
class Meta:
ordering = ('name',)
verbose_name = 'category'
verbose_name_plural = 'categories'
def get_absoulte_url(self):
return reverse('blogCMSApp:list_of_post_by_category', args=[self.slug])
def __str__(self):
return self.name
# Posts
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published')
)
category = models.ForeignKey(Category, on_delete=models.PROTECT)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique=True)
content = models.TextField()
seo_title = models.CharField(max_length=250)
seo_description = models.CharField(max_length=160)
author = models.ForeignKey(User, related_name='blog_posts', on_delete=models.PROTECT)
published = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=9, choices=STATUS_CHOICES, default='draft')
def get_absoulte_url(self):
return reverse('blogCMSApp:post_detail', args=[self.slug])
def __str__(self):
return self.title
You need to look for that pattern in urls.py, and then you need to build the correct URL for the post links:
url(
r'^category/(?P<category_slug>[-\w]+)/(?P<slug>[-\w]+)/$',
views.post_detail,
name='post_detail'
),
url(
r'^category/(?P<category_slug>[-\w]+)/$',
views.list_of_post_by_category,
name='list_of_post_by_category'
),
And in the Post model:
def get_absoulte_url(self):
return reverse(
'blogCMSApp:post_detail',
args=[self.category.slug, self.slug]
)

Title based Slug for URLs in django without app label

I got products app with ListView and DetailView. I need to implement slug with title of products on detail page with no app label in url. Such as in detail page it should say 'mysite.com/complete-product-title' instead of 'mysite.com/products/complete-product-title'. This detail page can help me to great deal for SEO.
Following is the code:
models.py:
class Product(models.Model):
title = models.CharField(max_length=500)
description = models.TextField(blank=True, null=True)
price = models.DecimalField(max_digits=20, decimal_places=2)
sku = models.CharField(null=True, max_length=100)
url = models.URLField(blank=True)
slug = models.SlugField(default='')
categories = models.ManyToManyField('Category', blank=True)
default = models.ForeignKey('Category', related_name='default_category', null=True, blank=True)
def __unicode__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save(*args, **kwargs)
def get_absolute_url(self):
kwargs={"slug": self.slug}
return reverse('product_detail', kwargs=kwargs)
Views.py:
class ProductListView(ListView):
model = Product
paginate_by = 20
def get_context_data(self, *args, **kwargs):
context = super(ProductListView, self).get_context_data(*args, **kwargs)
return context
def get_queryset(self, *args, **kwargs):
query = super(ProductListView, self).get_queryset(*args, **kwargs)
return query
class ProductDetailView(DetailView):
model = Product
slug_field = 'slug'
Project urls.py:
url(r'^products/', include('products.urls')),
App urls.py:
url(r'^(?P<slug>[\w-]+)/$', ProductDetailView.as_view(), name='product_detail'),
I have implemented elasticsearch with haystack and for it I have to add haystack urls in project root urls.py like url(r'^$', include('haystack.urls'), name='search'),
My complete models.py for products app are
class Product(models.Model):
title = models.CharField(max_length=500)
description = models.TextField(blank=True, null=True)
price = models.DecimalField(max_digits=20, decimal_places=2)
sku = models.CharField(null=True, max_length=100)
url = models.URLField(blank=True)
slug = models.SlugField(unique=False)
categories = models.ManyToManyField('Category', blank=True)
default = models.ForeignKey('Category', related_name='default_category', null=True, blank=True)
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse('product_detail', kwargs={"slug":self.slug})
def get_image_url(self):
img = self.productimage_set.first()
if img:
return img.image.url
return img
class Category(models.Model):
title = models.CharField(max_length=120, unique=True)
#slug = models.SlugField(unique=True)
description = models.TextField(null=True, blank=True)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
def __unicode__(self):
return self.title
def image_upload_to(instance, filename):
title = instance.product.title
slug = slugify(title)
basename, file_extension = filename.split('.')
new_filename = '%s-%s.%s'%(basename, instance.id, file_extension)
return 'products/%s/%s' %(slug, new_filename)
class ProductImage(models.Model):
product = models.ForeignKey(Product)
image = models.ImageField(upload_to=image_upload_to)
def __unicode__(self):
return self.product.title
When I try to add slug=models.SlugField(unique=True) I get error message like column slug is not unique.
Now I can't remove products/ from url(r'^products/', include('products.urls')), because then it will make haystack urls and product app urls both default. Ultimate goal here is to just implement haystack urls as default but not showing 'mysite.com/products/product-title-as-slug' instead 'mysite.com/product-title-as-slug'.
Please assist how can I achieve this goal.
You can do this immediately by changing:
url(r'^products/', include('products.urls')),
to
url(r'^', include('products.urls')),
This is all you would need to do if your site is not yet live. Otherwise you should also write in a 301 redirect from your old URLs (mysite.com/products/complete-product-title) to your new ones at the same time.