Before we get into creating CRUD with Django, let's get started with Bootstrap.
The HTML that we engineers make will be dull in terms of design. So I decided to use the CSS framework Bootstrap.
The documentation is in English, but with examples, you'll find what you want to do.
Bootstrap
Download it from the following, including the jQuery required by Bootstrap.
Create a directory called mybook / cms / static / cms / and place the downloaded file as follows.
- .map files are browser developer tools that provide the original line numbers when debugging JavaScript or looking at HTML elements to validate CSS. It works without it.
bootstrap.bundle.min.js contains (bundles) Popper.js.
mybook
└── cms
└── static
└── cms
├── css
│ ├── bootstrap.min.css
│ └── bootstrap.min.css.map
└── js
├── bootstrap.bundle.min.js
├── bootstrap.bundle.min.js.map
├── jquery-3.4.1.min.js
└── jquery-3.4.1.min.map
The reason why it is mybook / cms / static / cms / is
These are similar to how templates are found later, but are intended for independent reuse of the application. You don't have to know now. Think of it like that.
django-bootstrap4
For list HTML, handwrite the required class in Bootstrap, and for registration / modification form HTML, use a Python module called django-bootstrap4.
Installation is done with the pip command.
When running with
python manage.py runserver
, stop it with Ctrl + c before doing it. (env1) It is assumed that you are in a virtual environment.Unfortunately, the django-bootstrap-form I've been using seems to have stopped updating in Bootstrap3 and doesn't support 4. So I switched to this one.
$ pip install django-bootstrap4
At the moment, 1.1.1 is included.
$ pip freeze -l
asgiref==3.2.3
beautifulsoup4==4.8.2
Django==3.0.2
django-bootstrap4==1.1.1
pytz==2019.3
soupsieve==1.9.5
sqlparse==0.3.0
If you can confirm it, let's start it again with python manage.py runserver
.
Add'bootstrap4' to INSTALLED_APPS in mybook / settings.py
.
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'cms.apps.CmsConfig', #cms application
'bootstrap4', # django-bootstrap4
)
We need list, register, modify, and delete functions, so create a template in `cms / views.py'. Registration and correction are grouped together as an edit. (Register if book_id is not specified, correct if there is)
As a code style, if you do not open two lines before def, wavy lines will appear and it is noisy.
from django.shortcuts import render
from django.http import HttpResponse
def book_list(request):
"""List of books"""
return HttpResponse('List of books')
def book_edit(request, book_id=None):
"""Book editing"""
return HttpResponse('Book editing')
def book_del(request, book_id):
"""Delete books"""
return HttpResponse('Delete books')
The file cms / urls.py
does not exist, so create a new one.
Right-click on cms on the left and specify ʻurls.py` in New> Python File.
In this, the URL and the function of the view are linked.
The URL and function name do not have to match. This area is free.
from django.urls import path
from cms import views
app_name = 'cms'
urlpatterns = [
#Books
path('book/', views.book_list, name='book_list'), #List
path('book/add/', views.book_edit, name='book_add'), #Registration
path('book/mod/<int:book_id>/', views.book_edit, name='book_mod'), #Fix
path('book/del/<int:book_id>/', views.book_del, name='book_del'), #Delete
]
Then include cms / urls.py
in mybook / urls.py
for the entire project.
from django.contrib import admin
from django.urls import path, include # ←,add include
urlpatterns = [
path('cms/', include('cms.urls')), #← Add here
path('admin/', admin.site.urls),
]
The final URL will look like this: Please check with your browser.
http://127.0.0.1:8000/cms/book/
http://127.0.0.1:8000/cms/book/add/
http://127.0.0.1:8000/cms/book/mod/5/
http://127.0.0.1:8000/cms/book/del/7/
Let's write the view that displays the list properly.
Modify def book_list
in cms / views.py
as follows:
from django.shortcuts import render
from django.http import HttpResponse
from cms.models import Book
def book_list(request):
"""List of books"""
# return HttpResponse('List of books')
books = Book.objects.all().order_by('id')
return render(request,
'cms/book_list.html', #Template to use
{'books': books}) #Data to pass to the template
Create a template called book_list.html for use in the cms application of your mybook project. The position is as follows.
mybook/cms/templates/cms/book_list.html
Before that, let's create a template called base.html that will inherit from this.
Right-click cms on the left and specify
templates
in New> Directory Right-click on> template and specifycms
in New> Directory Right-click on cms and specifybase.html
in New> HTML File, and so on.
mybook/cms/templates/cms/base.html
The contents of base.html are as follows.
{% load i18n static %}
<!DOCTYPE html>{% get_current_language as LANGUAGE_CODE %}
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="{% static 'cms/css/bootstrap.min.css' %}">
{% block extra_css %}{% endblock %}
<title>{% block title %}My books{% endblock %}</title>
</head>
<body>
<div class="container">
{% block content %}
{{ content }}
{% endblock %}
</div>
<script src="{% static 'cms/js/jquery-3.4.1.min.js' %}"></script>
<script src="{% static 'cms/js/bootstrap.bundle.min.js' %}"></script>
{% block extra_js %}{% endblock %}
</body>
</html>
Now, let's inherit this base_html and create mybook / cms / templates / cms / book_list.html. Here, only the necessary parts will be written.
The class required by Bootstrap is specified in class.
{% extends "cms/base.html" %}
{% block title %}List of books{% endblock title %}
{% block content %}
<h4 class="mt-4 border-bottom">List of books</h4>
<a href="{% url 'cms:book_add' %}" class="btn btn-primary btn-sm my-3">add to</a>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Book title</th>
<th scope="col">the publisher</th>
<th scope="col">number of pages</th>
<th scope="col">operation</th>
</tr>
</thead>
<tbody>
{% for book in books %}
<tr>
<th scope="row">{{ book.id }}</th>
<td>{{ book.name }}</td>
<td>{{ book.publisher }}</td>
<td>{{ book.page }}</td>
<td>
<a href="{% url 'cms:book_mod' book_id=book.id %}" class="btn btn-outline-primary btn-sm">Fix</a>
<a href="{% url 'cms:book_del' book_id=book.id %}" class="btn btn-outline-danger btn-sm">Delete</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock content %}
Let's check it with a browser.
http://127.0.0.1:8000/cms/book/
Create a file called cms / forms.py
and write as follows.
Here, we will create a base form for adding and modifying Book models in cms / models.py
.
from django.forms import ModelForm
from cms.models import Book
class BookForm(ModelForm):
"""Book form"""
class Meta:
model = Book
fields = ('name', 'publisher', 'page', )
Modify def book_edit
in cms / views.py
as follows:
from django.shortcuts import render, get_object_or_404, redirect
from django.http import HttpResponse
from cms.models import Book
from cms.forms import BookForm
:
def book_edit(request, book_id=None):
"""Book editing"""
# return HttpResponse('Book editing')
if book_id: # book_id is specified(At the time of correction)
book = get_object_or_404(Book, pk=book_id)
else: # book_id not specified(At the time of addition)
book = Book()
if request.method == 'POST':
form = BookForm(request.POST, instance=book) #Create a form from POSTed request data
if form.is_valid(): #Form validation
book = form.save(commit=False)
book.save()
return redirect('cms:book_list')
else: #At the time of GET
form = BookForm(instance=book) #Create a form from a book instance
return render(request, 'cms/book_edit.html', dict(form=form, book_id=book_id))
Create mybook / cms / templates / cms / book_edit.html by inheriting mybook / templates / base_html.
{% extends "cms/base.html" %}
{% load bootstrap4 %}
{% block title %}Book editing{% endblock title %}
{% block content %}
<h4 class="mt-4 mb-5 border-bottom">Book editing</h4>
{% if book_id %}
<form action="{% url 'cms:book_mod' book_id=book_id %}" method="post">
{% else %}
<form action="{% url 'cms:book_add' %}" method="post">
{% endif %}
{% csrf_token %}
{% bootstrap_form form layout='horizontal' %}
<div class="form-group row">
<div class="offset-md-3 col-md-9">
<button type="submit" class="btn btn-primary">Send</button>
</div>
</div>
</form>
<a href="{% url 'cms:book_list' %}" class="btn btn-secondary btn-sm">Return</a>
{% endblock content %}
Pass the items defined in BookForm of cms / forms.py
to the template with a variable called form in cms / views.py
, and write {% bootstrap_form form layout ='horizontal'%}
form At the
part, the contents of the form are expanded in HTML.
Here, we also use the bootstrap_form
tag to convert it to Bootstrap format.
The book registration page is as follows.
Modify def book_del
in cms / views.py
as follows:
def book_del(request, book_id):
"""Delete books"""
# return HttpResponse('Delete books')
book = get_object_or_404(Book, pk=book_id)
book.delete()
return redirect('cms:book_list')
Now, try deleting the book by pressing the "Delete" button from the book list page.
It's gone suddenly, but it's actually better to bring up a Bootstrap modal dialog and get a confirmation message. This will be addressed later.
Continue to Introduction to Python Django (5).
Recommended Posts