Django ListView filter objects - python

I have a simple structure Shop_list --> Product_list --> Product_detail
I want to filter Product class object by slug field, but I see zero products.
I think that the problem in get_queryset()
views.py
class HomePageView(ListView):
model = Shop
template_name = 'blog/shop_list.html'
page_kwarg = 'shop'
context_object_name = 'shops'
class ProductListView(ListView):
model = Product
template_name = 'blog/product_list.html'
page_kwarg = 'product'
context_object_name = 'products'
def get_queryset(self):
pattern = str(self.request)
pattern = pattern[1:]
slug = self.model.shop
return Product.objects.filter(shop__slug=pattern)
def produt_detail(request, **kwargs):
print(request)
product = get_object_or_404(Product, pk=kwargs["pk"])
return render(request, 'blog/product_detail.html', {'product': product})
models.py
class Shop(models.Model):
title = models.CharField(max_length=200)
image = models.ImageField(blank=True)
slug = models.SlugField(null=False, default="Shop")
def get_absolute_url(self):
return reverse('product_list', kwargs={'slug': self.slug})
class Product(models.Model):
shop = models.ForeignKey(Shop, on_delete=models.CASCADE, related_name="shop")
title = models.CharField(max_length=200)
price = models.CharField(max_length=200)
period_start = models.DateTimeField(blank=True, null=True)
period_end = models.DateTimeField(blank=True, null=True)
def get_absolute_url(self):
return reverse('product_detail', kwargs={'slug': self.shop.slug, 'pk': self.pk})
urls.py
urlpatterns = [
path('', HomePageView.as_view(), name='shop_list'),
path('<slug:slug>', ProductListView.as_view(), name='product_list'),
path('<slug:slug>/<int:pk>/', views.produt_detail, name='product_detail'),
]
product_list.html
{% for product in products %}
<a href="{% url 'product_detail' product.shop.slug product.shop.pk %}">
...

You filter with:
class ProductListView(ListView):
model = Product
template_name = 'blog/product_list.html'
page_kwarg = 'product'
context_object_name = 'products'
def get_queryset(self):
return Product.objects.filter(shop__slug=self.kwargs['slug'])

Related

reverse_lazy with no arguments not found

reverse_url is workin fine with a url that has-no/int:pk but does not work with a url that has /int:pk throws an error NoReverseMatch: Reverse for 'read_bty' with no arguments not found. 1 patterns tried:['read_bty/(?P[0-9]+)$']. The first (class=HBTYIndex) lists all customers created from the (class=HBTYCreateView) and the (class=HBTYReadView) displays the customers order records, the last (class=HBTYOrderView) is supposed to create an order and reverse_lazy to the url 'read_bty' but it keeps on throwing the above error when creating an order. Tried to change from int:pk to int:id still getting the same error. if i change the reverse_lazy to point to a url with no int:pk the record gets added and i get redirected to that page instead of staying on the same page and showing the new added record.
Views.py
class HBTYIndex(generic.ListView):
model = HbtyCustomers
context_object_name = 'bty'
paginate_by = 100
template_name = 'accounts/modals/bty/clientindex.html'
ordering = ['-id']
success_url = reverse_lazy('btylist')
def get_queryset(self):
qs = self.model.objects.all()
p_f = CustomerFilter(self.request.GET, queryset=qs)
return p_f.qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = CustomerFilter(self.request.GET, queryset=self.get_queryset())
return context
# Create Customer
class HBTYCreateView(BSModalCreateView):
template_name = 'accounts/modals/bty/create_hbty.html'
form_class = btyForm
success_message = 'Success: Client was created.'
success_url = reverse_lazy('btylist')
# View Customer Orders History
class HBTYReadView(generic.ListView):
model = HbtyOrder
context_object_name = 'bty'
template_name = 'accounts/modals/bty/read_hbty.html'
allow_empty = False
pk_url_kwargs = 'hbtycustomer_pk'
paginate_by = 100
ordering = ['-id']
success_url = reverse_lazy('read_bty')
def get_queryset(self):
qs = self.model.objects.filter(hbtycustomer_id=self.kwargs['pk'])
p_f = HbtyOrdersFilter(self.request.GET, queryset=qs)
return p_f.qs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['filter'] = HbtyOrdersFilter(self.request.GET, queryset=self.get_queryset())
return context
# Create New Order in the customer history page
class HBTYOrderView(BSModalCreateView):
template_name = 'accounts/modals/bty/create_hbty.html'
form_class = HairbtyOrderForm
success_message = 'Success: Order was created.'
success_url = reverse_lazy('read_bty')
read_hbty.html
<div class="row">
<div class="col-12 mb-3">
{% if filter.qs %}
{% include "accounts/modals/hairbty/vw_more.html" %}
{% else %}
<p class="no-books text-primary">No Client addeds yet.</p>
{% endif %}
</div>
</div>
Models.py
class HbtyCustomers(models.Model):
name = models.CharField(max_length=200, blank=False, null=True)
address = models.CharField(max_length=200, blank=False, null=True)
date = models.IntegerField(blank=False, null=True)
remarks = models.CharField(max_length=200, blank=False, null=True)
def __str__(self):
return self.name
class HbtyCategories(models.Model):
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class HbtySubcategories(models.Model):
categ = models.ForeignKey(HbtyCategories, on_delete=models.CASCADE)
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class HbtyOrder(models.Model):
STATUS = (
('Pending', 'Pending'),
('Out for delivery', 'Out for delivery'),
('Delivered', 'Delivered'),
)
categ = models.ForeignKey(HbtyCategories, on_delete=models.SET_NULL, blank=True, null=True)
subcateg = models.ForeignKey(HbtySubcategories, on_delete=models.SET_NULL, blank=True, null=True)
hbtycustomer = models.ForeignKey(HbtyCustomers, on_delete=models.SET_NULL, blank=True, null=True)
price = models.IntegerField(null=True)
date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
status = models.CharField(max_length=200, null=True, choices=STATUS)
def __str__(self):
return str(self.id)
Urls.py
path('btylist/', views.HBTYIndex.as_view(), name="btylist"),
path('create_btycustomer/', views.HBTYCreateView.as_view(), name='create_btycustomer'),
path('create_btyorder/', views.HBTYOrderView.as_view(), name='create_btyorder'),
path('read_bty/<int:pk>', views.HBTYReadView.as_view(), name='read_bty'),
As you can tell from your urls.py, read_bty/HBTYReadView wants to see an int value named pk.
When you call that url in HBTYOrderView via reverse_lazy, you don't provide it, hence the error.
You can build out the success_url by creating a get_success_url method in your HBTYOrderView, rather than using a success_url property, something like:
def get_success_url(self):
return reverse_lazy('read_bty',kwargs={"pk": self.request.user.id} )
(I am assuming here that the ID that read_bty wants is the request.user.id )

How to get object from previous view(CBV) in Django?

I tried to get the object value in CreateView from previous DetailView. But Failed. Is there any simple way to do this?
In this code, how can I replace this '???'(in CreateView) by an album object where album.pk == id according to 'item-add'(url(r'^(?P<id>[0-9]+)/pic/add/$', views.ItemCreate.as_view(), name='item-add'))
models.py
class Album(models.Model):
credit = models.CharField(max_length=250)
album_title = models.CharField(max_length=100)
logo = models.FileField()
def get_absolute_url(self):
return reverse('picture:detail', kwargs={'pk': self.pk})
def __str__(self):
return self.album_title + ' - ' + self.credit
class Item(models.Model):
album = models.ForeignKey(Album, on_delete=models.CASCADE)
file_type = models.CharField(choices=TYPE_CHOICES, max_length=1)
caption = models.CharField(max_length=100)
class Meta:
ordering = ('upload_date', 'caption')
def get_absolute_url(self):
return reverse('picture:item-detail', kwargs={ 'id': self.album_id , 'pk': self.pk})
def __str__(self):
return self.caption
views.py
class DetailView(generic.DetailView):
model = Album
template_name = 'picture/detail.html'
class ItemCreate(CreateView):
model = Item
fields = ['album', 'file_type', 'caption']
def get_initial(self):
album = ???
return {
'album': album,
'file_type': 't',
}
urls.py
urlpatterns = [
# /picture/<album_id>/
url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
# /picture/<album_id>/<pic_id>
url(r'^(?P<id>[0-9]+)/(?P<pk>[0-9]+)/$', views.ItemDetailView.as_view(), name='item-detail'),
# /picture/<album_id>/pic/add
url(r'^(?P<id>[0-9]+)/pic/add/$', views.ItemCreate.as_view(), name='item-add'),
]
The primary key is passed as an id URL parameter, so you can access this with self.kwargs:
from django.shortcuts import get_object_or_404
class ItemCreate(CreateView):
model = Item
fields = ['album', 'file_type', 'caption']
def get_initial(self):
album = get_object_or_404(Album, pk=self.kwargs['id'])
return {
'album': album,
'file_type': 't',
}

Django show posts linked to the spefic user logged in

I have made a blogger website on Django and I would have a page where the user can see/manage their own posts, so they can edit, update and delete.
I have tried to add the page but it keeps throwing an error saying no reverse match?
I am sure how to solve this problem, is something to do with how I have added the author in the Post model to PostAuthor?
This is my models file
class PostAuthor(models.Model):
user = models.OneToOneField(User, on_delete=models.SET_NULL, null=True)
bio = models.TextField(max_length=400, help_text="Enter your bio details here.")
class Meta:
ordering = ["user", "bio"]
def get_absolute_url(self):
return reverse('post-by-author', args=[str(self.id)])
def __str__(self):
return self.user.username
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(PostAuthor, on_delete=models.CASCADE, null=True, blank=True)
updated_on = models.DateTimeField(auto_now=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
class Meta:
ordering = ['-created_on']
def get_absolute_url(self):
return reverse('post-detail', args=[str(self.id)])
def __str__(self):
return self.title
URLs file
urlpatterns = [
path('', views.IndexPage.as_view(), name='index'),
path('posts/', views.PostList.as_view(), name='all-posts'),
path('blog/<int:pk>', views.PostDetail.as_view(), name='post-detail'),
path('blog/<int:pk>', views.PostListbyAuthorView.as_view(), name='post-by-author'),
path('accounts/', include('django.contrib.auth.urls')),
]
Views file
class PostListbyAuthorView(generic.ListView):
model = Post
template_name = 'blog/post_list_by_author.html'
def get_queryset(self):
id = self.kwargs['pk']
target_author = get_object_or_404(PostAuthor, pk=id)
return Post.objects.filter(author=target_author)
def get_context_data(self, **kwargs):
context = super(PostListbyAuthorView, self).get_context_data(**kwargs)
context['blog'] = get_object_or_404(PostAuthor, pk=self.kwargs['pk'])
return context
class IndexPage(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'blog/index.html'
class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'blog/all_posts.html'
class PostDetail(generic.DetailView):
model = Post
template_name = 'blog/post_detail.html'
You are not passing the user's ID on your link, try this:
{% url 'post-by-author' pk=user.id %}

Reverse for 'post-detail' with keyword arguments '{'kwargs': {'slug': 'long-establis

I am trying to add comment fields to my post-detail view. But as soon i add redirect url after calling save(). This gives me error something like this.
Reverse for 'post-detail' with keyword arguments '{'kwargs': {'slug': 'long-established-fact-that-a-reader-will'}}' not found. 1 pattern(s) tried: ['post/(?P[^/]+)/$']
this is my code
posts/views.py
#login_required
def postDetail(request, slug):
post = get_object_or_404(Post, slug=slug)
latest_post = Post.objects.order_by('-timestamp')[0:4]
form = CommentForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
form.instance.user = request.user
form.instance.post = post
form.save()
return redirect('post-detail', kwargs = {
'slug': post.slug
})
context ={
'form': form,
'post': post,
'latest_post': latest_post
}
return render(request, 'posts/post_detail.html', context)
posts/urls.py
from django.urls import path, include
from django.conf.urls.static import static
from posts.views import index,postDetail, categoryDetail, blog, search
urlpatterns = [
path('', index, name="home"),
path('blog/', blog, name="blog"),
path('search/', search, name='search'),
path('post/<str:slug>/', postDetail, name='post-detail'),
path('category/<slug>/', categoryDetail, name='category-detail'),
]
posts/models.py
from tinymce import HTMLField
from django.db import models
from django.contrib.auth import get_user_model
from slugger import AutoSlugField
from django.urls import reverse
# Create your models here.
User = get_user_model()
def upload_location(instance, filename):
return "%s/%s" %(instance.slug, filename)
class Author(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return self.user.username
class Category(models.Model):
title = models.CharField(max_length=20)
slug = AutoSlugField(populate_from='title')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('category-detail', kwargs={'slug': self.slug})
class Post(models.Model):
title = models.CharField(max_length = 100)
slug = AutoSlugField(populate_from='title')
overview = models.CharField(max_length= 200)
timestamp = models.DateTimeField(auto_now_add=True)
content = HTMLField()
comment_count = models.IntegerField(default=0)
view_count = models.IntegerField(default=0)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
thumbnail = models.ImageField(
upload_to=upload_location,
null=True,
blank=True)
category = models.ManyToManyField(Category)
featured = models.BooleanField()
previous_post = models.ForeignKey('self', related_name= 'previous', on_delete=models.SET_NULL, blank=True, null=True)
next_post = models.ForeignKey('self', related_name= 'next', on_delete=models.SET_NULL, blank=True, null=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'slug': self.slug})
#property
def get_comments(self):
return self.comments.all().order_by('-timestamp')
class Comment(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)
content = models.TextField()
post = models.ForeignKey(Post, related_name='comments',on_delete=models.CASCADE)
def __str__(self):
return self.user.username
In your 4th path, you used <str:slug> - I don't believe the URL catching type str catches the dashes used in slugs.
Try this path instead: path('post/<slug:slug>/', postDetail, name='post-detail'),
EDIT
You are also missing a reverse in your postDetail() redirect:
#login_required
def postDetail(request, slug):
post = get_object_or_404(Post, slug=slug)
latest_post = Post.objects.order_by('-timestamp')[0:4]
form = CommentForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
form.instance.user = request.user
form.instance.post = post
form.save()
return redirect(reverse('main:post-detail', kwargs = {
'slug': post.slug
}))
context ={
'form': form,
'post': post,
'latest_post': latest_post
}
return render(request, 'posts/post_detail.html', context)
https://docs.djangoproject.com/en/2.1/topics/http/urls/#path-converters

Django One to Many relationship urls

I use to django for my web site. But ı have a question about blog/urls.py(my app name is blog )
I use to with one to many releationship in blog/models.py.
Category (1 => *) Subject (1 => *) Article.
class Category(models.Model):
name = models.CharField(max_length=200)
statement = models.TextField()
slug=models.SlugField()
page_name = models.ForeignKey('Page', on_delete=models.CASCADE)
def __str__(self):
return self.name
class Subject(models.Model):
name = models.CharField(max_length=200)
statement = models.TextField()
slug=models.SlugField()
category_name = models.ForeignKey('Category', on_delete=models.CASCADE)
def __str__(self):
return self.name
class Article(models.Model):
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
title = models.CharField(max_length=200)
slug=models.SlugField()
text = models.TextField()
created_date = models.DateTimeField(
default=timezone.now)
published_date = models.DateTimeField(
blank=True, null=True)
subject_name = models.ForeignKey('Subject', on_delete=models.CASCADE)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:detail', kwargs={'id' : self.id})
blog/views.py
def detail(request,article_slug):
article = get_object_or_404(Article, slug=article_slug)
article_list=Article.objects .all()
subject_list = Subject.objects.all()
context={
'article': article,
'article_list':article_list,
'subject_list': subject_list
}
return render(request, 'blog/detail.html', context)
blog/urls.py
url(r'^(?P<category_slug>[\w-]+)/(?P<subject_slug>[\w-]+)/(?P<article_slug>[\w-]+)/$', views.detail, name='detail'),
I want to see the url when I click on the links of my article
http://127.0.0.1:8000/myworkandresearch/category_slug/subject_slug/article_slug
blog / urls.py 'How can I edit?
edit my blog/models.py
class Article(models.Model):
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
title = models.CharField(max_length=200)
slug=models.SlugField()
text = models.TextField()
created_date = models.DateTimeField(
default=timezone.now)
published_date = models.DateTimeField(
blank=True, null=True)
subject_name = models.ForeignKey('Subject', on_delete=models.CASCADE)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:detail', args=[self.slug, self.subject.slug, self.subject.category.slug])
blog/views.py
def detail(request, category_slug, subject_slug, article_slug):
article = Article.objects.filter(
slug = article_slug,
subject__slug = subject_slug,
subject__category__slug = category_slug
)
subject_list = Subject.objects.all()
category_list = Category.objects.all()
context = {
'category_list': category_list,
'subject_list': subject_list,
'article': article
}
return render(request, 'blog/detail.html', context)
blog/urls.py
from django.conf.urls import include, url
from . import views
app_name = 'blog'
urlpatterns = [
url(r'^$', views.myworkandresearch, name='myworkandresearch'),
url(r'(?P<category_slug>[\w-]+)/$', views.subjects, name='subjects'),
url(r'^(?P<category_slug>[\w-]+)/(?P<subject_slug>[\w-]+)/(?P<article_slug>[\w-]+)/$', views.detail, name='detail'),
]
subjects.html
{% for article in subject.article_set.all %}}
<ul class="sidebar-items">
<li>{{article.title}}</li>
</ul>
{% endfor %}
[error continues.][2]
Page not found (404) Request Method: GET Request
URL: http://127.0.0.1:8000/myworkandresearch/machine_learning/python_dictionary/numpy/ Raised by: blog.views.subjects No Category matches the given query.
You're seeing this error because you have DEBUG = True in your Django
settings file. Change that to False, and Django will display a
standard 404 page.
I think you should have a detail view as
def detail(request, category_slug, subject_slug, article_slug):
article = Article.objects.filter(
slug = article_slug,
subject__slug = subject_slug,
subject__category__slug = category_slug
)
return render(request, 'blog/detail.html', {'article': article})
You need the following method on your article model
def get_absolute_url(self):
return reverse('detail', args=[self.slug, self.subject.slug, self.subject.category.slug])
When displaying your articles
{{article.title}}
Your url might look like this
url(r'^myworkandreseach/(?P<category_slug>[\w-]+)/(?P<subject_slug>[\w-]+)/(?P<article_slug>[\w-]+)/$', views.detail, name='detail'),
Be sure to import views

Categories