I am working on a simple Django project and suffice to say I am just a beginner. I have 2 classes
in models.py
:
from django.db import models
from django.db.models.deletion import CASCADE
class Category(models.Model):
category_name=models.CharField(max_length=225,null=True)
def __str__(self):
return f"ID: {self.category_name}"
class Book(models.Model):
cover_img = models.URLField(max_length=200, null=True)
author=models.CharField(max_length=128,null=True)
summery=models.TextField(max_length=1000,null=True)
category = models.ForeignKey(Category,related_name="book_categories",on_delete=CASCADE,null=True)
def __str__(self):
return f"{self.cover_img} ,{self.author},{self.summery}"
On the first page of my website(Menu.html
), I create a button for each category using jinja
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg OMhuP IlRH9sENBO0LRn5q 8nbTov4 1p" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/[email protected]/dist/umd/popper.min.js" integrity="sha384-7 zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG 2QOK9T ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
<title>Menu</title>
</head>
<body>
{% for cat in categories %}
<a type="button" class="btn btn-danger" href="{% url 'cat_detail' cat.id %}">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-book" viewBox="0 0 16 16">
<path d="M1 2.828c.885-.37 2.154-.769 3.388-.893 1.33-.134 2.458.063 3.112.752v9.746c-.935-.53-2.12-.603-3.213-.493-1.18.12-2.37.461-3.287.811V2.828zm7.5-.141c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z"/>
</svg>{{cat.category_name}}
</a>
{% endfor %}
</body>
</html>
Then If the user clicks on one of these buttons he/she will be redirected to a page that contains all the books with the same category
. In the second part of my project, I want to implement a method
for adding
objects
to my Database
.
my views.py
:
from django.shortcuts import redirect, render
from .models import *
# Create your views here.
def first_page(request):
context = {"categories" : Category.objects.all}
return render(request, 'Menu.html', context)
def category_detail(request, id):
try:
my_object_base_category = Book.objects.filter(category__id=id)
except Book.DoesNotExist:
my_object_base_category = None
return render(request, "Book.html", {'key':my_object_base_category})
def add_a_new_book(request):
context = {"categories" : Category.objects.all}
if request.method == "POST":
cover_img = request.POST.get('cover_img')
author = request.POST.get('author')
summery = request.POST.get('summery')
category = request.POST.get('category__category_name')
myobj = Book(cover_img = cover_img , author = author , summery = summery, category = category)
myobj.save()
return render(request, "Menu.html")
elif request.method == "GET":
# print("Get in Create")
return render(request, 'AddBook.html',context)
And here is my form
in AddBook.html
:
<form action="{% url 'Blog:add_book' %}" method="POST">
{% csrf_token %}
<div class="form-row">
<div class="form-group col-md-6">
<label for="author">Author</label>
<input type="text" class="form-control" id="author" placeholder="Author">
</div>
<div class="form-group col-md-6">
<label for="cover_img">Cover Image Link</label>
<input type="url" class="form-control" id="cover_img" placeholder="Cover Image Link">
</div>
</div>
<div class="form-group">
<label for="summery">Summary</label>
<input type="text" class="form-control" id="summery" placeholder="Summary">
</div>
<div class="form-group col-md-4">
<label for="category">Category</label>
<select id="category" class="form-control">
{% for i in categories %}
<option value="{{ i.category_name }}">{{ i.category_name }}</option>
{% endfor %}
</select>
</div>
<br><br><br><br><br><br><br><br><br>
<input type="submit" class="btn btn-primary" value="add">
</form>
But there are two problems with my codes. The first one is that after I add a new object, it saves all the values equal to NULL
. And the second one is that after clicking on the add
button, it does not redirect to another page. Here is my urls.py
file in my application:
from django.urls import path
from . import views
app_name = 'Blog'
urlpatterns = [
path('Menu/', views.first_page, name='category_buttons'),
path('<int:id>/', views.category_detail, name='cat_detail'),
path('add', views.add_a_new_book, name='add_book')
]
I will be really grateful for any help or advice. Thanks.
CodePudding user response:
Your html form input fields all need to have a name
attribute in order to get their values from a POST
request. If an input in your form does not have a name
attribute its value isn't even passed along in the request at all.
For example your author input field should be something like:
<input type="text" class="form-control" id="author" name="author" placeholder="Author">
The reason why all the values are being stored as Null in your database is because when you are trying to get a value from your request in the view, the request can't find a value for the key you are looking for so it returns None. For example, your line in your view
author = request.POST.get('author')
is returning None because it cannot find a key that has the name 'author' because none of your inputs in the html are named 'author'.
Edit to answer your other question from the comments:
This is assuming your category names are all unique. In your form you need to change your select option to have a name. Something like this:
<select id="category" class="form-control" name="category">
In your view to get the category object that you want you should do something like this:
category = request.POST.get('category')
category_object = Category.objects.get(category_name=category)
Then you pass the category_object
variable in to your new book object when you are creating it.
myobj = Book(cover_img = cover_img , author = author , summery = summery, category = category_object)
myobj.save()