Greetings Pythonistas!
I’m writing a Django CMS for a low traffic philosophy society. It’s like a blog.
I’m building the navbar and url navigation. I’m using a DetailView CBV and a single template to handle these four basic pages:
- Home
- About
- Podcasts
- Contact
Pretty standard website layout / usecase. When a web visitor clicks on one of those list items from the navigation menu, the urls.py successfully routes the visitor to the right corresponding addresses such as:
http://localhost:8000/home
http://localhost:8000/about
http://localhost:8000/podcasts
http://localhost:8000/contact
So far so good.
My goal is to have Django serve the home page at the top level parent address http://localhost:8000/
without the “home” slug at the end (suffix). But right now, when I navigate to http://localhost:8000/
, Django serves a 404 and I can’t wrap my head around how to reconfigure my two urls.py to accomplish this desired outcome.
Here is my web app’s urls.py:
from django.contrib import admin
from django.urls import path, include
from .views import PageView
app_name= 'landings'
urlpatterns = [
path('<str:slug>/', PageView.as_view(),name='home'),
]
In the past, what I normally would do, for the first path()
argument, I’d substitute an empty string like it appears here: path('', views.home, name='home')
.Notice the empty string as fthe first paramer. So I tried placing this line - - path('', PageView.as_view(),name='home')
- - above the path() in the code snippet above but then Django throws an “AttributeError at / Generic detail view PageView must be called with either an object pk or a slug in the URLconf.” So that isn’t working in this case since I am exploring this new CBV approach to generate pages.
What do I need to change in my urls.py above (or any of my other project files below) to get Django to serve the home page at the top level address without a “/home” suffix appended to the end of the domain name?
Here is my project urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('landings.urls')),
path('articles/', include('articles.urls')),
path('contributors/', include('contributors.urls')),
]
_navbar.html:
{% load static %}
<!-- Header Section -->
<header class="header">
<div class="container container--narrow">
<a href="{% url 'landings:home' 'home' %}" class="header__logo">
<img src="Thelema_static_image_needed_here" alt="DevSearch Logo" />
</a>
<nav class="header__nav">
<input type="checkbox" id="responsive-menu" />
<label for="responsive-menu" class="toggle-menu">
<span>Menu</span>
<div class="toggle-menu__lines"></div>
</label>
<ul class="header__menu">
<li class="header__menuItem"><a href="/">Home</a></li>
<li class="header__menuItem"><a href="{% url 'landings:home' 'about' %}">About</a></li>
<li class="header__menuItem"><a href="{% url 'landings:home' 'podcasts' %}">Podcasts</a></li>
<li class="header__menuItem"><a href="{% url 'landings:home' 'contact' %}">Contact</a></li>
</ul>
</nav>
</div>
</header>
When clicking the first unordered list menu item hyperlink Home, the traceback in my Django terminal is simply:
Not Found: /
[05/Mar/2023 10:01:58] "GET / HTTP/1.1" 404 2467
The 404 showing in my browser, Django appears to be looking for the page but can’t find it and chokes at this line in my url routing: <str:slug>/ [name='home']
template:
{% extends 'base.html' %}
{% block content %}
{% if contents %}
{{ contents.body|safe }}
{% endif %}
{% endblock %}
Here is my concise CBV:
from django.views.generic import DetailView
from .models import PageContent
class PageView(DetailView):
model = PageContent
template_name = "landings/page_detail.html"
context_object_name = 'contents'
My web app models.py:
from django.db import models
from ckeditor.fields import RichTextField
# from django.template.defaultfilters import slugify
class PageContent(models.Model):
# title = models.CharField(max_length=200)
slug = models.SlugField(null=False, unique=True, blank=True)
page_type = models.CharField(max_length=20)
body = RichTextField(config_name='default',max_length=300000,blank=True, null=True)
def __str__(self):
return f'{self.page_type}'