Django: 20 html files: 20 TemplateViews and 20 URL patterns needed?

Viewed 238

I have 20 Django simple "foo.html" template files.

Do I need 20 TemplateViews and 20 entries in url_patterns or is there a simpler solution?

4 Answers

Using Django 2.1 and class-based views, your urls.py should be like this:

from django.urls import path

from your_app import views

app_name = 'your_app'

urlpatterns = [
    path('foo/<str:name>/', views.Foo.as_view(), name='foo'),
]

And your views.py like this:

from django.views import generic


class Foo(generic.TemplateView):

    def get_template_names(self)
        name = self.kwargs.get('name')
        # compute the template you want, for the example, I just take the name
        template_name = f'your_app/{name}.html'
        return [template_name]

And that's all ;)

You can have a path like path('pages/<str:page>, views.pages)

And then in the view do something similar to:

from django.template.loader import get_template
from django.template import TemplateDoesNotExist

def pages(request, page):
    template_name = f'your-app/{page}.html'
    try:
        get_template(template_name)
        return render(request, template_name)
    except TemplateDoesNotExist:
        # returns 404

A simpler solution with django 2.x.

Since you sound newer to django, this solution should be much easier. There's no reason to use f strings and try/except blocks with simple things. And I know when I started, class based views made no sense because there was no control flow.

urls.py

from django.urls import path
from . import views

app_name = 'article_app'

urlpatterns = [
    path('', views.article_list, name='article_list'),
    path('new/', views.article_new, name='article_new'),
    path('<int:art_pk>/', views.article_detail, name='article_detail'),
    path('<int:art_pk>/update/', views.article_update, name='article_update'),
    path('<int:art_pk>/delete/', views.article_delete, name='article_delete'),
    # and so on....
]

views.py

from django.shortcuts import render
from .models import Article

def article_detail(request, art_pk):
    article = Article.objects.get(pk=art_pk)
    return render(request, 'articles_app/article_detail.html', {'article': article})

template for article_detail.html

{% block maincontent %}

   <div class="article">
     <h2><u>{{ article.title }}</u></h2>
     <h3>By: {{ article.author }} --- Posted / Updated on: {{ article.date }}</h3>
     <p>{{ article.body }}</p>
     <p><a href="{% url 'article_app:article_update' article.pk %}">Update</a> | <a href="{% url 'article_app:article_delete' article.pk %}">Delete</a></p>
     <p><a href="{% url 'article_app:article_list' %}">Back to all articles</a></p>
   </div>

{% endblock maincontent %}



If you had something more complicated:

Lets say it's something that requires a few if/else statements to describe a Food model. Example:

models.py

class Food(models.Model):
    FLAVOR_CHOICES = (
        ('tasty', 'Very yummy'),
        ('disgusting', 'Nasty AF bro!'),
        ('super_sweet', 'For little kids'),
        ('bitter', 'Sure to grow hair on you balls!'),
    )
    food_choice = models.CharField(max_length=30, choices=FLAVOR_CHOICES, default='super_sweet')
    # and any other attribute for a Food

urls.py

app_name = 'food_app'

urlpatterns = [
    # ....
    path('<int:food_id>/', views.show_food, name='show_food'),
]

views.py

def show_food(request, food_id):
    food = Food.objects.get(id=food_id)
    if food.food_choice == 'tasty':
        return render(request, 'food_app/food_stats.html', {'tasty': 'Everyone likes tasty things'})
    elif food.food_choice == 'bitter':
        return render(request, 'food_app/food_stats.html', {'bitter': 'Girls do not want to have balls. Sure way to end the gene pool.'})
    # .... and so on with other choices
    else:
        return render(request, 'food_app/food_stats.html')

Then your food_stats.html template would look something like this

Note that this should be used instead of creating separate pages for 'bitter.html', 'tasty.html', 'super_sweet.html', etc.

{% block maincontent %}

  <h1>Your choice of food:</h1>

  {% if tasty %}
      <p>{{ tasty.food_choice }}</p>  {# this attribute would show the 2nd value for 'tasty' in the tuple of FLAVOR_CHOICES - 'Very yummy' #}
      <p>{{ tasty }}</p>   {# The value that shows here is the key I set in the view #}

  {% elif disgusting %}
      <p>{{ disgusting.food_choice }}</p>
      <p>{{ disgusting }}</p>

  {% elif super_sweet %}
      <p>{{ super_sweet.food_choice }}</p>
      <p>{{ super_sweet }}</p>

  {% elif bitter %}
      <p>{{ bitter.food_choice }}</p>
      <p>{{ bitter }}</p>

  {% else %}
      <p>No foods bro. You're lame.</p>

  {% endif %}

{% endblock maincontent %}

from django.conf.urls import url from .import views

urlpatterns = [ # url(r'^/$', views.function_name, name="Page")

url(r'^$', views.home, name="Home Page"),

]

use this patterns match to show your .html pages

Related