I am a beginner learning Django through building an app, called PhoneReview. It will store reviews related to the latest mobile phone. It will also display phone brands, along with the associated phone models and their reviews.
I have already created models, views and the template files. Right now, I am facing a problem. While attempting to use slug, I am getting NoReverseMatch Error. It looks like this:
NoReverseMatch at /index
Reverse for 'modellist' with arguments '('',)' not found. 1 pattern(s) tried: ['phonemodel/(?P<slug>[-a-zA-Z0-9_]+)$']
However, I didn't face any problem with while using primary key in urls.py. The problem is occurring when I attempt to use slug in the URLs.
Here are my codes of models.py located inside PhoneReview folder:
from django.db import models
from django.template.defaultfilters import slugify
# Create your models here.
class Brand(models.Model):
brand_name = models.CharField(max_length=100)
origin = models.CharField(max_length=100)
manufacturing_since = models.CharField(max_length=100, null=True, blank=True)
slug = models.SlugField(max_length=150, null=True, blank=True)
def __str__(self):
return self.brand_name
def save(self, *args, **kwargs):
self.slug = slugify(self.brand_name)
super().save(*args, **kwargs)
class PhoneModel(models.Model):
brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
model_name = models.CharField(max_length=100)
launch_date = models.CharField(max_length=100)
platform = models.CharField(max_length=100)
slug = models.SlugField(max_length=150, null=True, blank=True)
def __str__(self):
return self.model_name
def save(self, *args, **kwargs):
self.slug = slugify(self.model_name)
super().save(*args, **kwargs)
class Review(models.Model):
phone_model = models.ManyToManyField(PhoneModel, related_name='reviews')
review_article = models.TextField()
date_published = models.DateField(auto_now=True)
slug = models.SlugField(max_length=150, null=True, blank=True)
link = models.TextField(max_length=150, null=True, blank=True)
def __str__(self):
return self.review_article
Here are my codes of urls.py located inside PhoneReview folder:
from . import views
from django.urls import path
app_name = 'PhoneReview'
urlpatterns = [
path('index', views.BrandListView.as_view(), name='brandlist'),
path('phonemodel/<slug:slug>', views.ModelView.as_view(), name='modellist'),
path('details/<slug:slug>', views.ReviewView.as_view(), name='details'),
]
Here are my codes of views.py located inside PhoneReview folder:
from django.shortcuts import render, get_object_or_404
from django.views import generic
from .models import Brand, PhoneModel, Review
class BrandListView(generic.ListView):
template_name = 'PhoneReview/index.html'
context_object_name = 'all_brands'
def get_queryset(self):
return Brand.objects.all()
class ModelView(generic.ListView):
template_name = 'PhoneReview/phonemodel.html'
context_object_name = 'all_model_name'
def get_queryset(self):
self.brand = get_object_or_404(Brand, slug=self.kwargs['slug'])
return PhoneModel.objects.filter(brand=self.brand)
class ReviewView(generic.DetailView):
model = Review
template_name = 'PhoneReview/details.html'
Here are my codes of apps.py located inside PhoneReview folder:
from django.apps import AppConfig
class PhonereviewConfig(AppConfig):
name = 'PhoneReview'
Here are my codes of index.html located inside templates folder:
{% extends 'PhoneReview/base.html' %}
{% load static %}
{% block title%}
Brand List
{% endblock %}
{% block content %}
<!--Page content-->
<h1>This is Brand List Page</h1>
<h2>Here is the list of the brands</h2>
<ul>
{% for brand in all_brands %}
<!-- <li>{{ brand.brand_name }}</li>-->
<li>{{ brand.brand_name }}</li>
{% endfor %}
</ul>
<img src="{% static "images/brandlist.jpg" %}" alt="Super Mario Odyssey" /> <!-- New line -->
{% endblock %}
Here are my codes of phonemodel.html located inside templates folder:
{% extends 'PhoneReview/base.html' %}
{% load static %}
{% block title%}
Phone Model Page
{% endblock %}
{% block content %}
<!--Page content-->
<h1>This is Phone Model Page</h1>
<h2>Here is the phone model</h2>
<ul>
{% for phonemodel in all_model_name %}
<li>{{ phonemodel.model_name }}</li>
{% endfor %}
</ul>
<img src="{% static "images/brandlist.jpg" %}" alt="Super Mario Odyssey" /> <!-- New line -->
{% endblock %}
Here are my codes of details.html located inside templates folder:
{% extends 'PhoneReview/base.html' %}
{% load static %}
<html>
<link rel="stylesheet" type="text/css" href="{% static "css/style.css" %}">
<html lang="en">
{% block title%}Details{% endblock %}
{% block content %}
<h1>This is the Details Page</h1>
<h2>Review:</h2>
<p>{{ review.review_article }}</p>
<h2>News Link:</h2>
<p>{{ review.link }}</p>
{% endblock %}
</html>
Am I doing anything wrong in index.html and phonemodel.html?
In your index.html instead of phonemodel.slug it should be brand.slug
{% for brand in all_brands %}
<!-- <li>{{ brand.brand_name }}</li>-->
<li>{{ brand.brand_name }}</li>
{% endfor %}
Same with your phonemodel.html
{% for phonemodel in all_model_name %}
<li>{{ phonemodel.model_name }}</li>
% endfor %}
Related
Data from database to html is not rendering. The static data is rendering but unfortunately the database data is not rendering no error occurs, and page is also rendering but data is not rendering from database to the page.
Html doc
{% extends "base.html" %}
{% load static %}
{% block title %}
All Tractors
{% endblock %}
{% block content%}
<section id="all_events">
<h1>All Tractors</h1>
<h1>{{posts.implementation}} hi</h1>
<br>
<ul>
{% for posts in post %}
{% include "tractor/includes/singlePost.html" %}
{% endfor %}
</ul>
</section>
{% endblock %}
Vews.py
from django import forms
from django.contrib.auth.models import User
from django.shortcuts import render, redirect
from .models import Post, Farmer
# Create your views here.
from django.http import HttpResponseRedirect
# Create your views here.
def starting_page(request):
return render(request,"tractor/index.html")
def posts(request):
qs = Post.objects.all()
context = {"posts":qs}
return render(request,"tractor/all-post.html",context)
This is the Models.py file:
from django.db import models
from django.core.validators import MinLengthValidator
from django.db.models.signals import pre_save
# Create your models here.
from .utils import unique_slug_generator
class Farmer(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
phone =models.CharField(max_length=10)
address = models.TextField(max_length=200)
email_address = models.EmailField()
def full_name(self):
return f"{self.first_name} {self.last_name}"
def __str__(self):
return self.full_name()
class Post(models.Model):
tractor_price = models.IntegerField(max_length=150)
implementation = models.CharField(max_length=50)
purchase_date = models.DateField(auto_now=False)
slug = models.SlugField(unique=True, db_index=True, null=True,blank=True)
tractor_company = models.CharField(max_length=50)
tractor_model = models.CharField(max_length=50)
description = models.TextField(validators=[MinLengthValidator(10)])
date = models.DateField(auto_now=False)
farmer = models.ForeignKey(
Farmer, on_delete=models.SET_NULL, null=True, related_name="posts")
def __str__(self):
return self.implementation
Try this:
{% load static %}
{% block title %}
All Tractors
{% endblock %}
{% block content%}
<section id="all_events">
<h1>All Tractors</h1>
<ul>
{% for post in posts %}
<h1>{{post.implementation}} hi</h1>
<br>
{% include "tractor/includes/singlePost.html" %}
{% endfor %}
</ul>
</section>
{% endblock %}
It should be {% for post in posts %}
I am learning Django by building an application, called TravelBuddies. It will allow travelers to plan their trip and keep associated travel items (such as bookings, tickets, copy of passport, insurance information, etc), as well as create alerts for daily activities. The application will also able to update local information such as weather or daily news to the traveler. Travelers can also share the travel information with someone or have someone to collaborate with them to plan for the trip.
I am facing a problem. When I go to http://127.0.0.1:8000/triplist/, I see this page:
When I click on Trip Name: Kuala Lumpur and taken to activity.html through this link: http://127.0.0.1:8000/triplist/kuala-lumpur/:
"john" and "williams" are two separate user names. They need to be separated by a comma (,). So it will look like this: Co-traveller: john, williams. How can I do it?
Here are my codes in models.py:
from django.contrib.auth.models import User
from django.db import models
from django.template.defaultfilters import slugify
# Create your models here.
class Trip(models.Model):
trip_name = models.CharField(max_length=100)
date = models.DateField()
planner_name = models.CharField(max_length=100)
add_coplanner = models.ManyToManyField(User)
slug = models.SlugField(max_length=150, default='null')
def __str__(self):
return self.trip_name
def save(self, *args, **kwargs):
self.slug = slugify(self.trip_name)
super().save(*args, **kwargs)
class Activity(models.Model):
trip = models.ForeignKey(Trip, on_delete=models.CASCADE)
activity_name = models.CharField(max_length=100)
date = models.DateField(auto_now=True)
time = models.TimeField(auto_now= True)
location = models.CharField(max_length=100)
item_type = models.CharField(max_length=100)
item_number = models.CharField(max_length=100)
add_cotraveller = models.ManyToManyField(User)
slug = models.SlugField(max_length=150, default='null')
def __str__(self):
return self.activity_name
def save(self):
super(Activity, self).save()
self.slug = '%i-%s' % (
self.id, slugify(self.trip.trip_name)
)
super(Activity, self).save()
Here are my codes in views.py:
from django.views import generic
from .models import Trip, Activity
class TripListView(generic.ListView):
template_name = 'trips/triplist.html'
context_object_name = 'all_trips'
def get_queryset(self):
return Trip.objects.all()
class ActivityView(generic.DetailView):
model = Trip
template_name = 'trips/activity.html'
Here are my codes in urls.py:
from . import views
from django.urls import path
app_name = 'trips'
urlpatterns = [
path('triplist/', views.TripListView.as_view(), name='triplist'),
path('triplist/<slug:slug>/', views.ActivityView.as_view(), name='activity'),
]
Here are my codes in apps.py:
from django.apps import AppConfig
class TripsConfig(AppConfig):
name = 'trips'
Here are my codes in triplist.html:
<!DOCTYPE html>
{% extends 'trips/base.html' %}
{% load static %}
<html lang="en">
<link rel="stylesheet" type="text/css" href="{% static "css/style.css" %}">
<head>
<meta charset="UTF-8">
{% block title%}Trip list{% endblock %}
<title>Trip list</title>
</head>
<body>
{% block content %}
<!--Page content-->
<h1>This is Trip List Page</h1>
<ol>
{% for trip in all_trips %}
<ol>
<li>Trip name: {{ trip.trip_name }}</li>
Date: {{ trip.date }}<br>
Planner: {{ trip.planner_name }}<br>
Coplanners:
{% for user in trip.add_coplanner.all %}
{{user.username}}
{% endfor %}<br>
<!-- Co-planner: {{ trip.add_coplanner.all }}<br>-->
</ol>
{% endfor %}
</ol>
<img src="{% static "images/botanical-garden.jpg" %}" alt="Botanical Garden" />
<!-- New line -->
{% endblock %}
</body>
</html>
Here are my codes in activity.html:
{% extends 'trips/base.html' %}
{% block title%}
Detail
{% endblock %}
{% block content %}
<h3>Activities for {{trip.trip_name}} </h3>
{% for trip_item in trip.activity_set.all %}
<!--<p>Activity name: {{ trip_item.activity_name }}</p>-->
<ol>
<li>Activity name: {{ trip_item.activity_name }}</li>
Date: {{ trip_item.date }}<br>
Time: {{ trip_item.time }}<br>
Location: {{ trip_item.location }}<br>
Item Type: {{ trip_item.item_type }}<br>
Item No: {{ trip_item.item_number }}<br>
Co-traveller:
{% for user in trip_item.add_cotraveller.all %}
{{user.username}}
{% endfor %}<br>
<!-- Co-traveller: {{ trip_item.add_cotraveller.all }}-->
</ol>
{% endfor %}
{% endblock %}
Do I have to make any change in models.py?
Co-traveller:
{% for user in trip_item.add_cotraveller.all %}
{% if forloop.last %}
{{user.username}}
{% else %}
{{user.username}} ,
{% endif %}
{% endfor %}<br>
you can use this. do give a space after ,
You can separate user with comma like this:
Co-traveller:
{% for user in trip_item.add_cotraveller.all %}
{{user.username}}{% if not forloop.last %}, {% endif %}
{% endfor %}<br>
One more way is to create a instance method and return a string from your model.
For eg.
class Activity(models.Model):
#fields
add_cotraveller = models.ManyToManyField(User)
def __str__(self):
return self.activity_name
def get_cotravellers(self):
return ", ".join(u.username for u in self.add_coplanner.all())
and in template you can access it like:
Coplanners: {{ trip_item.get_cotravellers }}
I use a generic view to list my categories.
I would also like to display the title of each items belonging to these categories.
I understand the principle of ListView and DetailView but what about some details in lists ?
Here are my different files:
Models.py
class categories(models.Model):
name = models.CharField(max_length=50,unique=True)
slug = models.SlugField(max_length=100,unique=True)
def __str__(self):
return self.name
class details(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=42)
category = models.ForeignKey('categories', on_delete=models.CASCADE)
def __str__(self):
return self.title
Views.py
class IndexView(generic.ListView):
model = categories
context_object_name = "list_categories"
template_name='show/index.html'
Urls.py
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
]
Index.html
{% load static %}
<p>These is a list of categories</p>
{% for category in list_categories %}
<div class="article">
<h3>{{ category.name }}</h3>
{% for title in category.detail %}
<p> {{title}} </p>
{% endfor %}
</div>
{% endfor %}
You need to first reverse call the details with related name i.e "categories".
{% load staticfiles %}
<p>These is a list of categories</p>
{% for category in list_categories %}
<div class="article">
<h3>{{ category.name }}</h3>
{% for detail in category.categories.all %}
<p> {{detail.title}} </p>
{% endfor %}
</div>
Be careful you must use all after reverse all because there could be more then one reverse relation.
Still have any doubts comment it below.
I am stuck with this issues for a while now. It goes like this: I have a model with lectures. I want that for every lecture to be able to upload multiple files, so I created a model that has FileField. So in my template, I want that for every lecture, the files would be displayed and downloadable as well. The Issue is that every lecture displays all the files that have ever been uploaded in the admin panel. Here is my code:
class Lecture(models.Model):
course = models.ForeignKey('Course', on_delete=models.CASCADE, default='', related_name='lectures')
lecture_category = models.IntegerField(choices=((0, "Classes "),
(1, "Seminars"),
), default=0)
lecture_title = models.CharField(max_length=100)
content = models.TextField()
files = models.OneToOneField('FileUpload', on_delete=models.CASCADE, null=True, blank=True, )
def __str__(self):
return str(self.lecture_category)
class FileUpload(models.Model):
files = models.FileField(upload_to='documents', null=True, blank=True)
def __str__(self):
return str(self.files)
def file_link(self):
if self.files:
return "<a href='%s'>download</a>" % (self.files.url,)
else:
return "No attachment"
file_link.allow_tags = True
file_link.short_description = 'File Download'
<ul>
{% regroup lectures by get_lecture_category_display as category_list %}
<h3>Lectures</h3>
<ul>
{% for category in category_list %}
<strong>
<li>{{ category.grouper }}</li>
</strong>
<ul>
{% for c in category.list %}
.............
<li>{{ c.lecture_title }}</li>
<li>{{ c.content }}</li>
{% for file in files %}
{% if file.files %}
<li><a href='{{ MEDIA_URL }}{{ file.files.url }}'>download</a></li>
{% endif %}
{% endfor %}
{% endfor %}
</ul>
{% endfor %}
</ul>
</ul>
def courses(request, slug):
query = Course.objects.get(slug=slug)
context = {'courses': Course.objects.filter(slug=slug),
'lectures': query.lectures.order_by('lecture_category'),
'files': FileUpload.objects.all(),
}
return render(request, 'courses/courses.html', context)
Here is the current output: https://i.imgur.com/Hu2NcHJ.png
Stop fetching the files as a separate queryset:
def courses(request, slug):
query = Course.objects.get(slug=slug)
context = {'courses': Course.objects.filter(slug=slug),
'lectures': query.lectures.order_by('lecture_category'),
}
return render(request, 'courses/courses.html', context)
You can then follow the one-to-one field from lecture to files.
{% for lecture in category.list %}
<li>{{ lecture.lecture_title }}</li>
<li>{{ lecture.content }}</li>
{% if lecture.files %}
<li><a href='{{ MEDIA_URL }}{{ lecture.files.files.url }}'>download</a></li>
{% endif %}
{% endfor %}
Since it's a one-to-one field to a single file upload, it would make more sense to name the field file instead of files:
file = models.OneToOneField('FileUpload', on_delete=models.CASCADE, null=True, blank=True)
You would then have to update the template to use lecture.file instead.
I have a basic start to a blog, it lists out blog articles from the database in post_list.html that extends from header.html. I am trying also to get a variable in the header as a slogan but this is not working.
header.html - this renders without the "propaganda.slogan" which is entered from the admin pages and has content:
<!DOCTYPE html>
<html lang="en">
<head>
<title>hey!</title>
<meta charset="utf-8" />
{% load staticfiles %}
<link rel="stylesheet" href="{% static 'blog/css/bulma.css' %}" type="text/css"/>
</head>
<body>
<section class="hero is-success is-bold">
<div class="hero-body">
<div class="container">
{% block slogan %}
<ul>
{% for propaganda in propagandas %}
<li>{{ propaganda.slogan }}</li>
{% endfor %}
</ul>
{% endblock %}
<h1 class="title">
My weblog
</h1>
</div>
</div>
</section>
{% block content %}
{% endblock %}
</body>
</html>
post_list.html extends header.html and displays a list of posts from models.py:
{% extends "blog/header.html" %}
{% block content %}
{% for post in posts %}
<section class="section">
<div class="container">
<h1 class="title">{{ post.title }}</h1>
<p>{{ post.summary|linebreaksbr }}</p>
<p>published: {{ post.last_edited }}</p>
</div>
</section>
{% endfor %}
{% endblock %}
models.py looks like this:
from django.db import models
from django.utils import timezone
# Create your models here.
class Propaganda(models.Model):
slogan = models.CharField(max_length=140, blank=True, null=True)
def __str__(self):
return self.slogan
class Post(models.Model):
title = models.CharField(max_length=140, blank=False, null=False)
content = models.TextField()
summary = models.CharField(max_length=500)
created_date = models.DateTimeField()
last_edited = models.DateTimeField()
def __str__(self):
return self.title
finally, views.py is:
from django.shortcuts import render
from .models import Post, Propaganda
# Create your views here.
def post_list(request):
posts = Post.objects.all()
return render(request, 'blog/post_list.html', {'posts': posts})
def header(request):
propagandas = Propaganda.objects.all()
return render(request, 'blog/header.html', {'propagandas': propagandas})
So why can I get the list of post titles, summary and date in the post_list.html but I can't get a list of propagandist slogans in the header?
to me it looks like the same code, almost?
I get no error from the dev server or in the browser :(
You'll need to pass the list of propagnadas to the context of the current template; including a template has little or nothing to do with the associated (if this makes any sense in the first place) view of the included template:
def post_list(request):
posts = Post.objects.all()
propagandas = Propaganda.objects.all()
return render(request, 'blog/post_list.html', {'posts': posts, 'propagandas': propagandas})