djangoでブログを作ってみる

2022年5月3日

djangoでblogを作ってみる

「django」の勉強のために基本的な「CRUD」を使用したブログを作成してみました。

階層


.
├── app
│   ├── forms.py
│   ├── models.py
│   ├── urls.py
│   └── views.py
├── config
├── manage.py
├── static
│   ├── css
│   │   └── style.css
│   └── js
│       ├── app.js
│       └── jquery-3.5.1.min.js
└── templates
    └── app
        ├── base.html
        ├── create_blog.html
        ├── display_blog.html
        ├── display_blogs.html
        ├── edit_blog.html
        └── index.html

models.py


from django.db import models
class Blog(models.Model):
    title = models.CharField(blank=False, null=False, max_length=150)
    text  = models.TextField(blank=True)
    created_datetime = models.DateTimeField(auto_now_add=True)
    updated_datetime = models.DateTimeField(auto_now=True)
    def __str__(self):
        return self.title

forms.py


from django.forms import ModelForm
from .models import Blog
class BlogForm(ModelForm):
    class Meta:
        model = Blog
        fields = ("title", "text")

urls.py


from django.urls import path
from . import views
app_name = 'app'
urlpatterns = [
        path('display_blogs/', views.display_blogs, name='display_blogs'),
        path('display_blog/<int:blog_id>/', views.display_blog, name='display_blog'),
        path('edit_blog/<int:blog_id>/', views.edit_blog, name='edit_blog'),
        path('create_blog/', views.create_blog, name='create_blog'),
        path('delete_blogs/', views.delete_blogs, name='delete_blogs'),
]

views.py


#--インポート------------------------------------------
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import get_object_or_404
#--デコレーター----------------------------------------
from django.views.decorators.http import require_POST
#--モデル----------------------------------------------
from app.models import Blog
#--フォーム--------------------------------------------
from app.forms import BlogForm
#--ブログ----------------------------------------------
def index(request):
    return render(request, 'app/index.html')
def display_blogs(request):
    blogs = Blog.objects.all().order_by('created_datetime')
    context = {
        'blogs' : blogs
    }
    return render(request, 'app/display_blogs.html', context)
def display_blog(request, blog_id):
    blog = Blog.objects.get(id=blog_id)
    context = {
        'blog' : blog
    }
    return render(request, 'app/display_blog.html', context)
def edit_blog(request, blog_id):
    blog = get_object_or_404(Blog, id=blog_id)
    if request.method == "POST":
        form = BlogForm(request.POST, instance=blog)
        if form.is_valid():
            form.save()
            context = {
                'blog': blog,
                'form': form,
            }
            return redirect('app:display_blogs')
    else:
        form = BlogForm(instance=blog)
        context = {
            'blog': blog,
            'form': form,
        }
        return render(request, 'app/edit_blog.html', context)
def create_blog(request):
    if request.method == 'POST':
        form = BlogForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('app:display_blogs')
    else:
        form = BlogForm
        context = {
            'form': form
        }
        return render(request, 'app/create_blog.html', context)
@require_POST
def delete_blogs(request):
    delete_ids = request.POST.getlist('delete_ids')
    Blog.objects.filter(pk__in=delete_ids).delete()
    return redirect('app:display_blogs')

base.html


{% load static %}
<!DOCTYPE html>
<html>
<head>
    <title>Django Practice</title>
</head>
<body>
    <h1><a href="{% url 'app:index' %}" class='white_link'>Django Practice</a></h1>
    <script src="{% static 'js/jquery-3.5.1.min.js' %}"></script>
    <script src="{% static 'js/app.js' %}"></script>
    <link rel="stylesheet" type="text/css" href="{% static 'css/style.css' %}">
    <div class="container">
        {% block content %}{% endblock %}
    </div>
</body>
</html>

display_blogs.html


{% extends 'app/base.html' %}
{% block content %}
<!--DELETE---------------------------------------->
<form method="post" action="{% url 'app:delete_blogs' %}" id="delete_blogs">{% csrf_token %}</form>
<div class="float_right"><button type="submit" class="negative_button" form="delete_blogs" onclick='return confirm("選択した項目を削除します。\nよろしいですか?");'>delete</button></div>
<!--CREATE---------------------------------------->
<form method="get" action="{% url 'app:create_blog' %}" id="create_blog"></form>
<div class="float_right"><button type="submit" class="positive_button" form="create_blog">create</button></div>
<!--TABLE----------------------------------------->
<table class = "data_record">
    <tr>
        <th>title</th>
        <th>create date</th>
        <th></th>
        <th></th>
    </tr>
    {% for blog in blogs %}
    <tr>
        <td><a href="{% url 'app:display_blog' blog.id %}">{{ blog.title }}</a></td>
        <td>{{ blog.created_datetime }}</td>
        <td>
        <form method="get" action="{% url 'app:edit_blog' blog.id %}">
            <button type="submit" class="neutral_button">edit</button>
        </form>
        </td>
        <td>
            <div class="checkbox_container">
                <input type="checkbox" name="delete_ids" value="{{ blog.id }}" form="delete_blogs" class="checkbox">
            </div>
        </td>
    </tr>
    {% endfor %}
</table>
{% endblock %}                                                                                                                                                                           

display_blog.html


{% extends 'app/base.html' %}
{% block content %}
{% load widget_tweaks %}
<table class = "blog_record">
    <tr>
        <th>title:</th>
        <td>{{ blog.title }}</td>
    </tr>
    <tr>
        <th>body:</th>
        <td><div class="text_align_left">{{ blog.text | linebreaks | urlize }}</td>
    </tr>
</table>
{% endblock %}

create_blog.html


{% extends 'app/base.html' %}
{% block content %}
{% load widget_tweaks %}
<form action="{% url 'app:create_blog' %}" method="POST">{% csrf_token %}
    <table>
        <tr>
            <td>title:</td>
            <td>{{ form.title |add_class:"input_box" }}</td>
        </tr>
        <tr>
            <td>body:</td>
            <td>{{ form.text |add_class:"input_box" }}</td>
        </tr>
        <tr>
            <td></td>
            <td><button type="submit" class="positive_button">save</button></td>
        </tr>
    </table>
</form>
{% endblock %}

edit_blog.html


{% block content %}
{% load widget_tweaks %}
<form action="{% url 'app:edit_blog' blog.id %}" method="POST">{% csrf_token %}
    <table>
        <tr>
            <td>title:</td>
            <td>{{ form.title |add_class:"input_box" }}</td>
        </tr>
        <tr>
            <td>body:</td>
            <td>{{ form.text |add_class:"input_box" }}</td>
        </tr>
        <tr>
            <td></td>
            <td><button type="submit" class="positive_button">save</button></td>
        </tr>
    </table>
</form>
{% endblock %}

はまったところ

「form」の入れ子を解消するために「form属性」を使用したのですが、ループ内の「formタグ」にも指定してしまうと、一番上の「form」しか利かなくなってしまうみたいです。
今度記事にまとめたいと思います。

CSSのチェックボックスの細かいところに時間がかかってしまいました。やっぱり機能を作ったらデザインもつけてあげたほうが達成感が出ますね。
今後は簡単でもよいので横着せずにデザインもやっていこうと思います。

2022年5月3日