I am a beginner in Django. I am building a Django app, named PhoneReview. It will store reviews related to the latest mobile phone. It will also display phone brands, along with the associated phone models. I have already created models for:
Brand – details on brand, such as, name, origin, manufacturing since, etc
Model – details on model, such as, model name, launch date, platform, etc
Review – review article on the mobile phone and date published, etc
Many-to-many relationship between Review and Model.
Now, I have to create views for the following:
a. An index page that display all Brands available for mobile phone in the
database
b. A phone model page that display model when a brand is selected.
c. A detail page when a model is selected that contain reviews and newslink
I have managed to create view for "a. An index page that display all Brands available for mobile phone in the database." However, I am stuck with "b. A phone model page that display model when a brand is selected."
I have managed to display the phone model page. However, the name of the phone model is not being displayed. So, I feel that there is a problem with either the views or templates. But I don't get any error while running the server. So, I am a bit confused.
Here are the codes of models.py of the PhoneReview app.
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)
def __str__(self):
return self.brand_name
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)
def __str__(self):
return self.model_name
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)
def __str__(self):
return self.review_article
Here are the codes of urls.py of the PhoneReview app:
from . import views
from django.urls import path
urlpatterns = [
path('index', views.BrandListView.as_view(), name='brandlist'),
path('phonemodel/<int:pk>/', views.ModelView.as_view(), name='modellist'),
]
Here are the codes of views.py of the PhoneReview app:
from django.views import generic
from .models import Brand, PhoneModel
class BrandListView(generic.ListView):
template_name = 'PhoneReview/brandlist.html'
context_object_name = 'all_brands'
def get_queryset(self):
return Brand.objects.all()
class ModelView(generic.DetailView):
model = PhoneModel
template_name = 'PhoneReview/phonemodel.html'
Here are the codes of base.html file. As the name suggests, this is the base page. It will be extended for being used by the other pages, like brandlist.html for showing phone brand list and phonemodel.html for showing phone models. It is located inside templates > GameReview folder:
<!DOCTYPE html>
<html lang="en">
<head>
<title>{% block title %} {% endblock %}</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
<style>
/* Remove the navbar's default margin-bottom and rounded borders */
.navbar {
margin-bottom: 0;
border-radius: 0;
}
/* Add a gray background color and some padding to the footer */
footer {
background-color: #f2f2f2;
padding: 25px;
}
</style>
</head>
<body>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Phone Radar</a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
<li class="active">#</li>
<li>Add Phone</li>
<li>Add Review</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li><span class="glyphicon glyphicon-log-in"></span> Login</li>
</ul>
</div>
</div>
</nav>
<div class="jumbotron">
<div class="container text-left">
{% block content %} {% endblock %}
</div>
</div>
</body>
</html>
Here are the codes of brandlist.html file, which displays the list of the phone brands. It located inside templates > GameReview folder. I have managed to display the phone brands at http://127.0.0.1:8000/index.
{% extends 'PhoneReview/base.html' %}
{% load static %}
{% block title%}
Brand List
{% endblock %}
{% block content %}
<!--Page content-->
<h1>This is Brand List Page</h1>
<ul>
{% for brand in all_brands %}
<li>{{ brand.brand_name }}</li>
{% endfor %}
</ul>
<img src="{% static "images/brandlist.jpg" %}" alt="Super Mario Odyssey" /> <!-- New line -->
{% endblock %}
Here are the codes of phonemodel.html file, which is supposed to display the phone brands. However, I can't display the output of {{ phonemodel.model_name }} at http://127.0.0.1:8000/phonemodel/1/. It just shows the H1 heading. The file is located inside templates > GameReview folder.
{% extends 'PhoneReview/base.html' %}
{% load static %}
{% block title%}
Phone Model Page
{% endblock %}
{% block content %}
<!--Page content-->
<h1>This is Phone Model Page</h1>
<ul>
{% for phonemodel in all_phonemodel %}
<li>{{ phonemodel.model_name }}</li>
{% endfor %}
</ul>
<img src="{% static "images/brandlist.jpg" %}" alt="Super Mario Odyssey" /> <!-- New line -->
{% endblock %}
I am stuck here. The phonemodel.html is supposed to display the phone brands. However, I can't display the output of {{ phonemodel.model_name }} at http://127.0.0.1:8000/phonemodel/1/. It just shows the H1 heading. There are no errors showing. I tried several hours to fix it. But being a Django beginner, I am facing a hard time fixing it.
Your phonemodel template is totally wrong. Not only do you not have anything called all_phonemodel in the template context, even if you did it wouldn't be iterable because this is a detail view, not a list view.
Remove the loop and just access object:
<ul>
<li>{{ object.model_name }}</li>
</ul>
Add this to your "class ModelView":
context_object_name = 'all_phonemodel'
def get_queryset(self):
return PhoneModel.objects.all()
Related
building a news aggregator. I am collecting reddit and twitter posts using their APIs, and then I create a model object for each post, which is stored in my database. I'm then passing in these post objects as context into my template, looping through the context in the template with the hope to display the posts 'html' attribute (A model field I created) onto the page, which in turn embeds the post onto the screen.
However, I can't figure out why my template page is still blank. No errors are thrown, and the model objects are being created because I can see them in the admin panel. I'll provide my models.py, views.py, and template to be taken a glance at. I appreciate and am grateful for any help/advice.
models.py
class Post(models.Model):
post_type = models.CharField(
max_length=20, null=True, blank=True)
root_url = models.CharField(max_length=200, default="")
html = models.TextField(default="")
created_at = models.DateTimeField(auto_now_add=True)
views.py
def main(request):
all_posts = Post.objects.all
context = {'posts': all_posts}
return render(request, "test.html", context)
template
{% block content %} {% autoescape off %}
<div class="container">
<div class="row">
<div class="col-6">
<h3 class='text-center'>Twitter News</h3>
{% for post in posts %}
{% if post.post_type == 'twitter' %}
<div class="mdl-card__media" id="timeline"></div>
{{ post.html }}
{% endif %}
<br>
{% endfor %}
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<div class="col-6">
<h3 class='text-center'>Reddit News</h3>
{% for post in posts %}
{% if post.post_type == 'reddit' %}
<div class="mdl-card__media" id="timeline"></div>
{{ post.html }}
{% endif %}
<br>
{% endfor %}
<script async src="//embed.redditmedia.com/widgets/platform.js" charset="UTF-8"></script>
</div>
</div>
</div>
{% endautoescape %}{% endblock %}
<script async src="//embed.redditmedia.com/widgets/platform.js" charset="UTF-8"></script>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.0-beta3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf" crossorigin="anonymous"></script>
In your views.py, your attempt to create a queryset is missing the parenthesis on the all method:
all_posts = Post.objects.all()
You have mentioned in the comments that the <br> tags within the {% for %} loops are being rendered. This would indicate that when you check for {% if post.post_type == 'twitter' %} (and the equivalent for reddit), there are no matches.
Check your Post model in Django admin to ensure you have records with post_type values that equal 'twitter' and 'reddit'.
im newbie in django. I have some question related to models. So, i was trying to display the model name and date to the views by iterating to all of them. But somehow they dont show up in the views, i tried to search in google but none fixed my problem. Im sorry if i asked some ridiculous question, but here is my code.
And also i already checked my models and theyre valid
Models
from django.db import models
from django.utils import timezone
from django.utils.text import slugify
class Post(models.Model):
title = models.CharField(max_length=30)
body = models.TextField()
time_post = models.DateTimeField(auto_now_add=True)
time_edit = models.DateTimeField(editable=False,blank = True)
slug = models.SlugField(editable=False, blank=True)
def save(self):
self.slug = slugify(self.title)
self.time_edit = timezone.now()
super(Post, self).save()
def __str__(self):
return "{}. {}".format(self.id, self.title)
urls
from django.shortcuts import render
from .models import Post
def blog(request):
posts = Post.objects.all(),
context = {
'title':'Blog ',
'contributor':'Chris',
'img':'blog/img/BlogBanner.jpg',
'Post':posts,
'nav': [
['/blog/recent','Recent'],
['/blog/news','News'],
['/blog','Blog'],
['/about','About'],
['/', 'Index']
]
}
return render(request,'blog/blog.html',context)
My blog.html
{% extends "base.html" %}
{% load static %}
{% block app_css %} <!-- Custom CSS per app !-->
<link rel="stylesheet" types="text/css" href = "{% static "blog/css/styleblog.css" %}"> <!-- CSS OVERIDE !-->
{% endblock app_css %}
{% block header %}
<h1 class="display-4">Welcome to {{title}} | ChrisDjango</h1>
<p class="lead">This was made in Django by {{contributor}}</p>
{% endblock header %}
{% block content1 %}
{% for post in Post %}
<h2>{{post.title}}</h2> #THE TITLE AND TIMEPOST DIDNT SHOW UP
<p>{{post.time_post}}</p>
{% endfor %}
{% endblock content1 %}
base.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{%include "snippets/styles.html"%} <!--Bootstrap!-->
{% block app_css %}
<link rel="stylesheet" types="text/css" href = "{% static "blog/css/styleblog.css" %}"> <!-- Custom CSS per app !-->
{% endblock app_css %}
<title>{{title}} | ChrisDjango</title>
<img id="banner" style="border-bottom: 15px solid #343A40;" src="{% static img %}" alt="Blog Banner">
</head>
<body>
{%include "snippets/navbar.html"%}
<div class="jumbotron">
<div class="container text-white text-center">
{% block header %}
{% endblock header %}
<hr class="my-4">
</div>
</div>
<div class="container-fluid">
<div class="container bg-white text-dark shadow" style="margin-top:-150px" id="myBody">
{% block content1 %}
{% endblock content1 %}
</div>
<div class="container bg-secondary text-white shadow">
{% block content2 %}
{% endblock content2 %}
</div>
</div>
{%include "snippets/scripts.html"%}
</body>
</html>
Sorry if my code looks really weird
Thank you
Let's start with this edit in urls:
posts = Post.objects.all(),
should be
posts = Post.objects.all()
Note the dropped comma.
I have made that mistake MANY times and it is really hard to spot sometimes. Here is what happens when you have a trailing comma (you get an iterable wrapper)
If you still have a problem LMK.
There is a trailing comma at the end of:
posts = Post.objects.all(),
# trailing comma ^
this means you wrap the item in a singleton tuple. It is thus a tuple with one element, the collection of object.
You should remove the comma at the end:
posts = Post.objects.all()
I would furthermore rename 'Post' to posts, since this gives a hit that it is a collection of items.
I'm a newbie and I've been battling with an error while trying to display the detail page of a post. I've checked other answers relating to this question but the solutions still don't work for me.
This is the error I'm getting:
Reverse for 'blog_post' with no arguments not found. 1 pattern(s) tried: ['blog\\/post/(?P<slug>[-\\w]+)/$']
This is my model:
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, unique_for_date='publish')
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES,
default='draft')
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post', args=[str(self.slug)])
View functions:
class BlogHomePageView(ListView):
model = Post
template_name = 'blog/index.html'
class PostDetailView(DetailView):
model = Post
template_name = 'blog/post.html'
slug_url_kwarg = 'slug'
query_pk_and_slug = True
Urlpatterns:
path('', BlogHomePageView.as_view(), name='blog_home'),
re_path(r'post/(?P<slug>[-\w]+)/$', PostDetailView.as_view(), name='blog_post'),
base.html
<!-- Navigation -->
<nav class="navbar navbar-expand-lg navbar-light fixed-top" id="mainNav">
<div class="container">
<a class="navbar-brand" href="index.html">Toluwalemi</a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse"
data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false"
aria-label="Toggle navigation">
Menu
<i class="fas fa-bars"></i>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="{% url 'blog_home' %}">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'blog_about' %}">About</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'blog_post' %}">Sample Post</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{% url 'blog_contact' %}">Contact</a>
</li>
</ul>
</div>
</div>
</nav>
detail page:
{% extends 'blog/base.html' %}
{% block title %}Post{% endblock %}
<!-- Page Header -->
{% block page_header %}
<div class="post-heading">
<h1>{{ post.title }}</h1>
<h2 class="subheading">Problems look mighty small from 150 miles up</h2>
<span class="meta">Posted by
{{ post.author }}
on {{ post.publish }}</span>
</div>
{% endblock %}
<!-- Post Content -->
<article>
{% block content %}
<p>{{ post.body }}</p>
list page:
{% extends 'blog/base.html' %}
{% block title %}Home{% endblock %}
<!-- Page Header -->
{% block page_header %}
<div class="site-heading">
<h1>Toluwalemi's Blog</h1>
<span class="subheading">Official Blog</span>
</div>
{% endblock %}
<!-- Main Content -->
{% block content %}
{% for post in object_list %}
<div class="post-preview">
<a href="{{ post.get_absolute_url }}">
<h2 class="post-title">
{{ post.title }}
</h2>
If you look at your URL definition, you can see that it expects an argument slug:
re_path(r'post/(?P<slug>[-\w]+)/$', PostDetailView.as_view(), name='blog_post'),
which, by the way, could also be expressed as as of Django 2.0:
path('post/<slug:slug>/', PostDetailView.as_view(), name='blog_post'),
Now, the error message from the image shows clearly that you are calling the URL template tag without said argument, it only has
href="{% url 'blog_post' %}"
and no slug argument is present.
You need to add the slug argument.
You have not even shown us the right template in your question where the line appears that is shown in the error message, so I cannot help further than this.
So guys, I finally figured it out. My slug url is now working perfectly.
The error was actually coming from my list page. The url to the detail view wasn't written well. I didn't include a namespace. So instead of <a href="{{ post.get_absolute_url }}"> it becomes <a href="{% url 'blog:blog_post' post.slug %}">
I also deleted redundant lines of codes in my models and my views page.
Here is what it looks like now.
models.py:
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, default="")
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
views.py
class BlogHomePageView(ListView):
model = Post
template_name = 'blog/index.html'
context_object_name = 'posts'
class PostDetailView(DetailView):
model = Post
template_name = 'blog/post.html'
context_object_name = 'post'
blog/urls.py:
urlpatterns = [
path('', BlogHomePageView.as_view(), name='blog_home'),
path('post/<slug:slug>/', PostDetailView.as_view(), name='blog_post'),
]
list page(index.html):
{% extends 'blog/base.html' %}
{% block title %}Home{% endblock %}
<!-- Page Header -->
{% block page_header %}
<div class="site-heading">
<h1>Toluwalemi's Blog</h1>
<span class="subheading">Official Blog</span>
</div>
{% endblock %}
<!-- Main Content -->
{% block content %}
{% for post in posts %}
<div class="post-preview">
<a href="{% url 'blog:blog_post' post.slug %}">
<h2 class="post-title">
{{ post.title }}
</h2>
So here's my code first and foremost. I'm new to Django and trying to create an ecommerce site. The way it works is that the admin creates products and users come on to the site and purchase them. The site uses Stripe to process payments.
views.py:
from django.shortcuts import render
from django.views import generic
from django.core.paginator import Paginator
from django.conf import settings
import stripe
import decimal
stripe.api_key = settings.STRIPE_SECRET_KEY
from .models import Product
# Create your views here.
class ProductListView(generic.ListView):
model = Product
paginate_by = 3
def get_context_data(self, **kwargs): # new
context = super().get_context_data(**kwargs)
context['key'] = settings.STRIPE_PUBLISHABLE_KEY
return context
def charge(request):
if request.method == 'POST':
charge = stripe.Charge.create(
amount=round(decimal.Decimal(request.POST['price'])),
currency='usd',
description='A Django charge',
source=request.POST['stripeToken']
)
return render(request, 'store/charge.html')
product_list.html:
{% extends 'home/base_generic.html' %}
{% load static %}
{% load cool_paginate %}
{% block add %}
<link rel="stylesheet" href="{% static 'store/css/products.css'%}">
{% endblock %}
{% block title %} <title> Store </title> {% endblock %}
{% block content %}
<div class="row">
{% for product in product_list %}
<div class="col-sm-4">
<div class="card" id="django-card" style="width: 300px; height: 350px;">
<img class="card-img-top" src="{{ product.image.url }}" height=150px width=150px>
<div class="card-body">
<h5 class="card-title">{{ product.name }}</h5>
<p class="card-text">
{{ product.description }} And only {{ product.price }}!
</p>
<form action="{% url 'charge' %}" method="post">
{% csrf_token %}
<script src="https://checkout.stripe.com/checkout.js" class="stripe-button"
data-key="{{ key }}"
data-description="A Django Charge"
data-amount= "{{ product.price_in_cents }}"
data-locale="auto">
</script>
<input type="hidden" name="price" value="{{ product.price_in_cents }}">
</form>
</div>
</div>
</div>
{% endfor %}
<div class="container-fluid">
<div style="margin-top: 50px;"> {% cool_paginate page_obj=product %}</div>
</div>
</div>
{% endblock %}
So, my question is, when the user selects a product to purchase, how do I tell the view to use that products price? The way I've been doing it is using a hidden html value field in the input. But this can't be secure. Thanks to all who take the time to respond.
Ok, after a few grueling hours of work I solved it. I opted to keep the hidden field form but instead of using price I used it to return the product primary key. Which I used in the view to grab the price and make charges.
I am kinda new with the MVC and MTV concept and i am trying to learn Python Django. I want to make catalog with books, must have add and delete functionality. I am trying to follow best practices and working with Generic views, but kinda stuck at the end, i feel that i am missing something very small but i cant figure it out - to be honest i am very exhausted at this moment and i dont have much time. So this is my code:
Models:
class Books(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=200)
isbn = models.CharField(max_length=200)
pages = models.IntegerField(default=0)
def __unicode__(self):
return self.title
class BooksForm(ModelForm):
class Meta:
model = Books
Views:
# coding: utf-8
from django.core.urlresolvers import reverse_lazy
from django.views.generic import ListView, UpdateView, CreateView, DetailView
from models import Book
class BooksDetailView(DetailView):
model = Book
template_name = "books_portal/details.html"
class BooksCreateView(CreateView):
model = Book
template_name = "books_portal/add.html"
success_url = reverse_lazy('books_portal')
class BooksUpdateView(UpdateView):
model = Book
template_name = "books_portal/add.html"
success_url = reverse_lazy('books_portal')
class BooksListView(ListView):
model = Book
context_object_name = 'books_list'
template_name = "books_portal/index.html"
def get_queryset(self):
return Book.objects.order_by('author')[:5]
Templates:
add.html
{% extends "books_portal/base.html" %}
{% block title %}Add books{% endblock %}
{% block extracss %}
<style>
.top-buffer { margin-top:20px; }
.bs-docs-nav { background-color: #563d7c; }
</style>
{% endblock extracss %}
{% block content %}
<form action="" method="post" class="form-horizontal" role="form">{% csrf_token %}
<div class="row top-buffer">
<div class="col-md-1">
{{form.title.label_tag}}
<input type="text" value="" class=""/>
</div>
</div>
<div class="row top-buffer">
<div class="col-md-1">
{{form.author.label_tag}}
<input type="text" value="" class=""/>
</div>
</div>
<div class="row top-buffer">
<div class="col-md-2 col-md-offset-1">
<input type="submit" value="Save" class="btn btn-primary btn-lg"/>
</div>
</div>
</form>
{% endblock %}
base.html
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{{title|default:"Book Library"}}{% endblock %}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
{% block extracss %}{% endblock extracss %}
</head>
<body>
<div class="container">
<div class="navbar-header">
Books Portal
</div>
{% block content %}
{% endblock %}
</div>
{% block extrajs %}{% endblock extrajs %}
</body>
</html>
details.html
{% extends "books_portal/base.html" %}
{% block title %}Details{% endblock %}
{% block extracss %}
<style>
.top-buffer { margin-top:20px; }
.bs-docs-nav { background-color: #4CD085; }
</style>
{% endblock extracss %}
{% block content %}
<div class="row top-buffer">
<div class="col-md-1">
<strong>Title:</strong>
</div>
<div class="col-md-2">
{{book.title}}
</div>
</div>
<div class="row top-buffer">
<div class="col-md-1">
<strong>Author:</strong>
</div>
<div class="col-md-2">
{{book.author}}
</div>
</div>
<div class="row top-buffer">
</div>
<div class="row">
<div class="col-md-1 col-md-offset-1 text-center">OK</div>
</div>
{% endblock %}
index.html
{% extends "books_portal/base.html" %}
{% block title %}Collection of books{% endblock %}
{% block extracss %}
<style>
.top-buffer { margin-top:20px; }
.bs-docs-nav { background-color: #563d7c; }
</style>
{% endblock extracss %}
{% block content %}
<table class="table table table-hover">
<tr>
<th class="text-center">Title</th>
<th class="text-center">Author</th>
<th class="text-center">Edit</th>
</tr>
{% for book in books_list %}
<tr>
<td class="text-center">{{ book.title }}</td>
<td class="text-center">{{ book.author }}</td>
<td class="text-center">Delete</td>
</tr>
{% endfor %}
</table>
<div class="row">
<div class="col-md-2 col-md-offset-5 text-center">Add</div>
</div>
{% endblock %}
Currently i cant add or delete any books, any help will be appreciated. Thank you.
I've cut and pasted all your code, plus a relevant urls.py, into a new project. The immediate problem is that you're not showing any form errors in your add.html. You can just add {{ form.errors }} at the top of the template.
Once you've done that, you'll see the actual issue: you're not providing all relevant fields when creating your book. In fact, Django can't see any fields, because you haven't given any of the inputs name attributes. Really, you shouldn't create the input elements manually: you should get Django to do that, because then it also takes responsibility for prepopulating the field with the existing value either when re-showing the form with errors, or when editing an existing Book. It should look like this:
{{ form.title.label_tag }}
{{ form.title }}
{{ form.title.errors }}
Then the outstanding issue is that you're not including the isbn or pages fields, which your model is treating as required. You can either set them as blank=False in the model, or use an exclude list in the ModelForm. Either way, you'll need null=False in the model field for pages.
Or, of course, you can add them to the form. To be honest, the easiest thing for you to do now, while you're learning, is to replace all the HTML inside your <form> tag with just {{ form.as_p }}, so that Django outputs everything for you.