I'm receiving a TemplateDoesNotExist error when I click on a particular link, and I've noticed from the 'template-loader postmortem' that Django is searching incorrect and non-existent paths.
I've recently moved half of the contents of a Django app called 'reviews' into another called 'accelerators'. My templates directory for each app follows the pattern: '"app name"/templates(folder)/"app name"/html templates'.
Having moved the template into the accelerators app (and having updated my settings and urls), Django should be looking for the template via 'accelerators/templates/accelerators/accelerator_form.html', but according to the error message it's instead searching: 'accelerators/templates/reviews/accelerator_form.html'.
I suspect this has something to do with the fact that I've just moved this template, alongside a number of other files, from the reviews app, but I can't figure out why this is happening. I've included my updated urls etc. below for reference.
Base directory urlpatterns
urlpatterns = [
path('admin/', admin.site.urls),
path('login/', auth_views.LoginView.as_view(template_name='accounts/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(template_name='accounts/logout.html'), name='logout'),
path('', include('accounts.urls')),
path('reviews/', include('reviews.urls')),
path('accelerators/', include('accelerators.urls')),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
accelerators/urls.py
from django.urls import path
from .views import (
AcceleratorListView,
accelerator_detail,
accelerator_reviews,
AcceleratorCreateView,
AcceleratorUpdateView,
AcceleratorDeleteView,
)
from . import views
urlpatterns = [
path('', AcceleratorListView.as_view(), name='accelerators'),
path('<int:pk>/', views.accelerator_detail, name='accelerator_detail'),
path('new/', AcceleratorCreateView.as_view(), name='accelerator_create'),
path('<int:pk>/update/', AcceleratorUpdateView.as_view(), name='accelerator_update'),
path('<int:pk>/delete/', AcceleratorDeleteView.as_view(), name='accelerator_delete'),
path('<int:pk>/reviews/', views.accelerator_reviews, name='accelerator_reviews'),
]
accelerators/views.py (view that I'm trying to access)
class AcceleratorCreateView(LoginRequiredMixin, CreateView):
model = Accelerator
fields = ['name', 'website', 'locations', 'bio', 'sector_focus', 'stage', 'deal', 'duration', 'logo']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
base.html template (relevant link)
<li><a class="dropdown-link" href="{% url 'accelerator_create' %}">Add Company</a></li>
That's happening because your Accelerator model is still coming from review app i.e. from review.models.
Django searches for template in templates/app_name/model_name_type.html if it not provided specifically.
2 Solutions: Follow any of them
Provide template_name specifically.
class AcceleratorCreateView(LoginRequiredMixin, CreateView):
model = Accelerator
template_name = 'accelerators/accelerator_form.html'
Move your Accelerator model to models file of accelerators app.
Related
ok polls tutorial is done and can enter questions, vote, etc. but from the admin pages View site aka localhost:8000 gives...
Page not found (404)
Request Method: GET
Request URL: http://localhost:8000/
Using the URLconf defined in mysite.urls, Django tried these URL patterns, in this order:
dose/
admin/
The empty path didn’t match any of these.
Now I have polls/views.py...
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.utils import timezone
from django.views import generic
from .models import Choice, Question
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list'
def get_queryset(self):
"""
Return the last five published questions (not including those set to be
published in the future).
"""
return Question.objects.filter(
pub_date__lte=timezone.now()
).order_by('-pub_date')[:5]
and mysite/urls.py set to ...
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls),
]
and polls/urls.py set to...
from django.urls import path
from . import views
app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
path('<int:question_id>/vote/', views.vote, name='vote'),
]
The only hint I can find is that all the imports show error highlights in VSCode with the Error "reportMissingModuleSources"
But python and django run perfectly well everywhere but index.html
No url at http://localhost:8000/ address is expected behaviour, where you want to go is http://localhost:8000/polls/.
If you want go directly to the desired View without writing polls/ prefix you should define your urls this way:
urlpatterns = [
path('', include('polls.urls')),
path('admin/', admin.site.urls),
]
So you place path() call without url prefix. Generally if you include any url group you define the beginning of address this way.
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 am currently working with my Django authentification app. My goal is once the user logged in successful I want to redirect it to the index page where my code shows a customised message:
messages.success(request, 'Login Successful', extra_tags='alert alert-dark')
My problem is I didn't manage to 'access' LoginView in my views.py.
I read about SuccessMessageMixin, but this LoginView won't work (Template Not Found):
class LoginView(auth_views.LoginView):
template_name = "accounts/login.html"
Do you have any idea how to solve this?
Only as long I include template_name in my urls.py it works, but I can't add the success message mixin there.
urls.py
from django.urls import path
from django.contrib.auth import views as auth_views
from . import views
app_name = 'accounts'
urlpatterns = [
path('login/', auth_views.LoginView.as_view(template_name='accounts/login.html'), name='login'),
]
You have a custom LoginView, but in the urls.py you call auth_views.LoginView.
To call your custom view you should do
from <module_name>.views import LoginView
urlpatterns = [
path('login/', LoginView.as_view(), name='login'),
]
It's a good idea to have a different name for your custom view, i.e.CustomLoginView.
You can add the followng snippet in the settings.py files:
LOGIN_REDIRECT_URL = '/'
You can add your own index page URL in 'LOGIN_REDIRECT_URL' variable
I am trying to use something like polls:detailin a class-based view, such as this:
class QuestionDetail(DetailView):
template_name = 'polls:result'
However, I get a TemplateDoesNotExist at /polls/2/result
polls:result error...
The urls.py is:
from django.conf.urls import url
from polls.views import IndexView, DetailView, ResultsView
from . import views
app_name = 'polls'
urlpatterns = [
url(r'^$', IndexView.as_view(), name='index'),
url(r'^(?P<pk>\d+)/$', DetailView.as_view(), name='detail'),
url(r'^(?P<pk>\d+)/result$', ResultsView.as_view(), name='result'),
url(r'^(?P<pk>\d+)/vote$', views.vote, name='vote'),
]
I guess the main question is, how do I use the names of URLs in class-based views, instead of explicitly providing the template name, such as polls/question_results.html?
Is there anything other than template_name?
I was reading that it's a good practice to use names in URLS so in case the URL itself changes, the rest of the code still works, so that's what I'm trying to do.
Url name and template name are very absolutely things.
template_name is a path to the .html file.
Url's name parameter you can use to reverse url from name using django.urls.reverse
You can use the name of URL like this:
django.urls.reverse('polls:detail', args=[object.id])
And you have to change the template_name settings as well and to create a template detail.html in your current template folder.
template_name = 'polls/detail.html'