In my urls.py I have a ListView and a CreateView. When I have both the views in the urls patterns, the CreateView shows the html linked to the ListView. But when I remove the ListView from the url patterns, then the CreateView shows the correct html.
urls.py
If I have it like this, CreateView shows ListView html
urlpatterns = [
path("", views.TopicListView.as_view(), name="topic"),
path("<topic>/", views.PostListView.as_view(), name="post"),
path("create/", views.CreatePostView.as_view(), name="create_post")
]
This way, the CreateView behaves like I want it to. Shows the correct HTML
urlpatterns = [
path("", views.TopicListView.as_view(), name="topic"),
path("create/", views.CreatePostView.as_view(), name="create_post")
]
views.py
class PostListView(ListView):
model = models.ForumPost
template_name = "forum/post_list.html"
def get_context_data(self):
context = super().get_context_data()
return context
def get_queryset(self):
query_set = super().get_queryset()
return query_set
class CreatePostView(CreateView):
model = models.ForumPost
fields = ("title", "description")
template_name = "forum/create_post.html"
The reason as urls are checking one by one from up to down. So when you have 3 urls:
urlpatterns = [
path("", views.TopicListView.as_view(), name="topic"),
path("<topic>/", views.PostListView.as_view(), name="post"),
path("create/", views.CreatePostView.as_view(), name="create_post")
]
And try to use create/ it actually matches <topic>/ pattern as a string were passed. So what I recommend is to place it to very down:
urlpatterns = [
path("", views.TopicListView.as_view(), name="topic"),
path("create/", views.CreatePostView.as_view(), name="create_post")
path("<topic>/", views.PostListView.as_view(), name="post"),
]
But also it would be better if you add some additional path to urls in order it won't be double-minded like list/<topic>/.
Related
I am trying to simply add a new 'blog' page in Django, which should replicate the home page. The home page is working fine, and if I view the URLs for my app, it looks like the following:
urlpatterns = [
path('', views.PostList.as_view(), name='home'),
path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'),
]
In my understanding of Django, I could add a 'blog' page by adding the following:
urlpatterns = [
path('', views.PostList.as_view(), name='home'),
path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'),
path('blog/', views.PostList.as_view(), name='blog'), #ADDED LINE
]
However going to my http://127.0.0.1:8000/blog/ page returns a 404 error. With Django debugging enabled, I get the following message:
Page not found (404) Request Method: GET Request
URL: http://127.0.0.1:8000/blog/ Raised
by: main_site_app.views.PostDetail
From what I can observe, there is nothing additional that the index page has that the blog doesn't. Is there a step I'm missing here that is preventing the /blog/ page from showing up?
EDIT:
views.py
from django.http import HttpResponse
from django.shortcuts import render
from django.views import generic
from .models import Post
class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'index_2.html'
class PostListLimited(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')[:2]
template_name = 'index_2.html'
class PostDetail(generic.DetailView):
model = Post
template_name = 'post_detail.html'
I would like to support the above views in a single view in url ...in my search I came across this post which is no longer supported and all the tutorials i've found have been outdated, which demonstrate how to accomplish the task in django 1.8.3.
In 'products/views.py' I have created a views for products and details. ProductListView will display all products, while ProductDetailView will display a single product detail (title, description, price etc).
products/views.py
class ProductListView(ListView):
queryset = Product.objects.all()
template_name = "products/list.html"
class ProductDetailView(DetailView):
queryset = Product.objects.all()
template_name = "products/detail.html"
products/urls.py include path to the views for ProductListView and ProductDetailView. ProductListView appears to be correct. ProductDetailView is incorrect! I'm getting the following warnings:
WARNINGS: ?: (2_0.W001) Your URL pattern '^products/(?P\d+)/$'
[name='details'] has a route that contains '(?P<', begins with a '^',
or ends with a '$'. This was likely an oversight when migrating to
django.urls.path().
ecommerce.py/urls.py is where i've included products and details urls
ecommerce/urls.py:
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include
from .views import home, about, contact
urlpatterns = [
path('admin/', admin.site.urls),
path('', home, name='home'),
path('about/', about, name='about'),
path('products/', include('products.urls'), name='products'),
path('products/', include('products.urls'), name='details'),
path('contact/', contact, name='contact'),
path('account/', include('allauth.urls'), name='login'),
path('register/', include('allauth.urls'), name='register'),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
products/urls.py
from django.urls import path
from .import views
urlpatterns = [
path('', views.ProductListView.as_view(), name='products'),
path(r'^products/(?P<id>\d+)/$', views.ProductDetailView.as_view(), name='details')
]
You've got that warning because Django unable to match the url to any of your urlpattern. Shortly you can use this to solve your problem:
# products/urls.py
from django.urls import path
from .import views
urlpatterns = [
path('', views.ProductListView.as_view(), name='products'),
path('products/<int:pk>/$', views.ProductDetailView.as_view(), name='details')
]
or if you want to use regex to match your url then:
# products/urls.py
from django.urls import path
from .import views
urlpatterns = [
path('', views.ProductListView.as_view(), name='products'),
re_path(r'^products/(?P<pk>\d+)/$', views.ProductDetailView.as_view(), name='details')
]
The reason is because your ProductDetailView are inheriting from DetailView of Django. That View already implemented some mixin to get the object from pk key instead of id that's why when you change to use <int:pk> it'll works.
You can take a look at the source code to see how Django implementing to query the object. (Keep you eyes on SingleObjectMixin mixin and property pk_url_kwarg = 'pk'.
I also recommend you to change the value of pk_url_kwarg in ProductDetailView view and also remember to change pk in the urlpattern into the new value which match with pk_url_kwarg value.
I have this structure of urls:
page/section/subsection/article, where section, subsection and article are user-generated slug names.
How can I write the urlpatterns?
I do this, but may be exist better method?
urlpatterns = [
url(r'^$', views.index),
url(r'^(?P<slug>[-\w]+)/$', views.section),
url(r'^(?P<slug>[-\w]+)/(?P<subslug>[-\w]+)/$', views.subsection),
url(r'^(?P<slug>[-\w]+)/(?P<subslug>[-\w]+)/(?P<articleslug>[-\w]+)/$', views.article)
]
My views:
def index(request):
return render(request, 'MotherBeeApp/index.html', {})
def section(request, slug):
sections = Section.objects.filter(page=slug)
if sections:
return render(request, 'MotherBeeApp/section.html', {'Sections': sections})
else:
return render(request, 'MotherBeeApp/404.html', status=404)
def subsection(request, slug, subslug):
subsection = Section.objects.get(link_title=subslug)
articles = Article.objects.filter(section=subsection.pk)
page_title = subsection.title
return render(request, 'MotherBeeApp/subsection.html', {'Articles': articles, 'PageTitle': page_title})
def article(request, slug, subslug, articleslug):
article = Article.objects.get(link_title=articleslug)
return render(request, 'MotherBeeApp/article.html', {'Article': article})
If you are using Django version older than Django 2.0 (< 2.0) than you are doing right thing and you are already using optimistic way. but if your Django version is later than or equals to Django 2.0 you could write urlpatterns as shown here.
Maybe you can upgrade your Django to 2.0+, and then use code as follows:
from django.urls import path, include
urlpatterns = [
path('', views.index),
path('<slug:slug>/', include([
path('', views.section),
path('<slug:subslug>/', views.subsection),
path('<slug:subslug>/<articleslug>/', views.article),
])),
]
the below code is working only for index page but it's not working for my DetailView. Please help me to fix (Using Django 2.0.2)
The below is my class for view:
from django.views import generic
from .models import Album
class IndexView(generic.ListView):
template_name = "newboston/index.html"
context_object_name = "all_album"
def get_queryset(self):
return Album.objects.all()
class DetailView(generic.DetailView):
model = Album
template_name = 'newboston/detail.html'
The below is my urls.py under my application.
from . import views
from django.urls import path
urlpatterns = [
path('', views.IndexView.as_view(), name='home'),
path('<slug:slug>/', views.DetailView.as_view(), name='detail'),
]
This is how you should refer to the primary key using pk in the urls.py file ...
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
Further details are in the documentation near the end of the page, or search for "polls/urls.py".
I am using class based views in my app but I am stuck at one point. I am using ListView and created two classes which are sub-classes of ListView.
views.py
class blog_home(ListView):
paginate_by = 3
model= Blog
context_object_name = 'blog_title'
template_name = 'blog.html'
class blog_search(ListView):
paginate_by = 4
context_object_name = 'blog_search'
template = 'blog_search.html'
def get_queryset(self):
self.search_result = Blog.objects.filter(title__contains = 'Static')
return self.search_result
urls.py
urlpatterns = [
url(r'^$', index, name='index'),
url(r'^grappelli/', include('grappelli.urls')),
url(r'^blog/', blog_home.as_view(), name='blog_home'),
url(r'^admin/', include(admin.site.urls)),
url(r'^blog/search/',blog_search.as_view(),name='blog_search'),
]
In my above code in blog_Search(), get_queryset() method is not getting called. I mean it's not working. If I use same same method in blog_home it does work.
blog_search not filtering. I added print statement also but not get called.
Can I create two classes with ListView in same file? Is this the problem?
You need to terminate your blog/ URL entry. Without termination, it matches all URLs beginning with "blog/", including "blog/search", so no requests ever make it to the blog_search view.
url(r'^blog/$', blog_home.as_view(), name='blog_home'),
url(r'^admin/', include(admin.site.urls)),
url(r'^blog/search/$',blog_search.as_view(),name='blog_search'),