django単語帳(備忘録)
djangoの基本的なコマンドを使って単語帳を作る。
プロジェクト生成
django-admin startproject prj
cd prj
python manage.py startapp vocaApp
次のような構造になる。
C:.
│ manage.py
│
├─prj
│ │ settings.py
│ │ urls.py
│ │ wsgi.py
│ │ __init__.py
│ │
│ └─__pycache__
│ settings.cpython-36.pyc
│ __init__.cpython-36.pyc
│
└─vocaApp
│ admin.py
│ apps.py
│ models.py
│ tests.py
│ views.py
│ __init__.py
│
└─migrations
__init__.py
設定
settings.pyを変更。
defaultはsqliteになっているがpostgresqlを使う。
postgresqlなかったらインストールし、
pip install psycopg2でpsycopg2を手に入れる。
INSTALLED_APPS = [
'vocaApp.apps.VocaappConfig',
...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': '...',
'HOST': 'localhost',
'PORT': '5432',
}
}
...
TIME_ZONE = 'Asia/Tokyo'
...
from django.urls import path, include
urlpatterns = [
path('', include('vocaApp.urls')),
...
モデル
モデルー>DB
migrateするとvocaApp_prjのようなテーブルが生成される。
class Vocabulary(models.Model):
# 自動増加id
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50)
mean = models.TextField(max_length=100)
example = models.TextField(max_length=300, blank=True, null=True)
mem_count = models.IntegerField(blank=True, null=True, default=0)
check = models.NullBooleanField(blank=True, null=True, default=False)
# 生成時のtimestamp
created_date = models.DateTimeField(auto_now_add=True)
# 変更時のtimestamp
modified_date = models.DateTimeField(auto_now=True)
DB->モデル(djangoを使うならモデルー>DBの方が良い、既存のテーブルからdjangoにするとき使う。)
先にpgadminなどでテーブルを作った後inspectdbでmodelスクリプトを得てmodels.pyにコピー
python manage.py inspectdb vocaApp_prj
フォーム
データを受けるModelFormを作成
from django import forms
from .models import *
class VocaForm(forms.ModelForm):
class Meta:
model = Vocabulary
fields = '__all__'
ビュー
ビジネスロジックとhtmlにrenderするviews.py
from django.views import generic
from django.shortcuts import render, redirect
from django.views.decorators.http import require_http_methods
from .forms import *
from .models import *
# Create your views here.
class Voca(generic.FormView):
template_name = "index.html"
form_class = VocaForm
success_url = '/'
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['vocabulary'] = Vocabulary.objects.all().order_by("created_date")
return ctx
def form_valid(self, form):
form.save()
return super().form_valid(form)
@require_http_methods(["POST"])
def update(req):
form = VocaForm(req.POST)
name = form["name"].value()
result = Vocabulary.objects.filter(name=name)
if result:
try:
if form.is_valid():
result[0].name = name
result[0].mean = form["mean"].value()
result[0].example = form["example"].value()
result[0].mem_count = int(form["mem_count"].value())
result[0].check = bool(form["check"].value())
result[0].save()
return redirect("/")
else:
raise Exception("Form validation failed")
except Exception as e:
return render(req, 'index.html', {"form" : form,
"vocabulary" : Vocabulary.objects.all().order_by("created_date")})
else:
error_msg = "There is no vocabulary that name is %s"%name
return render(req, 'error.html', {"error_msg" : error_msg})
@require_http_methods(["GET"])
def delete(req):
id = req.GET["id"]
Vocabulary.objects.filter(pk=id).delete()
return redirect("/")
URL
from django.urls import path
from . import views
urlpatterns = [
path('', views.Voca.as_view()),
path('update', views.update),
path('delete', views.delete)
]
テンプレート
html templateの作成
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Voca</title>
{% load static %}
<script src="{% static 'js/jquery-3.3.1.min.js' %}"></script>
</head>
<body>
<table border="1" style="border-collapse: collapse;">
<thead>
<tr>
<th id="name">単語</th>
<th id="mean">意味</th>
<th id="example">例文</th>
<th>記憶カウント</th>
<th>チェック</th>
<th>削除ボタン</th>
</tr>
</thead>
<tbody>
<!-- None処理してないのでvocabularyを何も登録しないとエラー発生 -->
{% for voca in vocabulary %}
<tr>
<td><span class="c1">{{ voca.name }}</span></td>
<td><span class="c2">{{ voca.mean }}</span></td>
<td><span class="c3">{{ voca.example }}</span></td>
<td><span class="c4">{{ voca.mem_count }}</span></td>
<td><span class="c5">{{ voca.check }}</span></td>
<td><input type="button" value="削除" onclick="deleteById({{ voca.id }})"></td>
</tr>
{% endfor %}
</tbody>
</table>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="reset" value="リセット">
<input type="submit" value="挿入">
<input type="button" value="修正" onclick="update()">
</form>
<script src="{% static 'js/local.js' %}"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Error</title>
</head>
<body>
{{ error_msg }}
</body>
</html>
Javascript
static javascript
// thを押して単語の意味などを隠す
var nameVisable = true
var meanVisable = true
var exampleVisable = true
$("#name, #mean, #example").click(function() {
if ($(this).attr("id") === "name") {
if (nameVisable) {
$(".c1").hide()
nameVisable = false
} else {
$(".c1").show()
nameVisable = true
}
} else if ($(this).attr("id") === "mean") {
if (meanVisable) {
$(".c2").hide()
meanVisable = false
} else {
$(".c2").show()
meanVisable = true
}
} else if ($(this).attr("id") === "example") {
if (exampleVisable) {
$(".c3").hide()
exampleVisable = false
} else {
$(".c3").show()
exampleVisable = true
}
};
})
// 単語の名前を押すとFormに値をセット
$(".c1").click(function() {
$("input[name='name']").val($(this).html())
var i = 0
$.each($(this).parent().siblings(), function() {
if (i === 0) {
$("textarea[name='mean']").val($(this).find("span").html())
} else if (i === 1) {
$("textarea[name='example']").val($(this).find("span").html())
} else if (i === 2) {
$("input[name='mem_count']").val($(this).find("span").html())
} else if (i === 3) {
if ($(this).find("span").html() === "True") {
$("select[name='check'] option[value='2']").attr('selected','selected');
} else if ($(this).find("span").html() === "False") {
$("select[name='check'] option[value='3']").attr('selected','selected');
}
}
i++
})
})
// delete 単語
function deleteById(id) {
$.get("/delete", {"id" : id})
location.href = "/"
}
// update 単語
function update() {
$("form").attr("action", "/update").submit()
}
最終フォルダーのtree構造
最後にprjのtree構造は以下のようになる。
C:.
│ manage.py
│ run.py
│
├─vocaApp
│ │ admin.py
│ │ apps.py
│ │ forms.py
│ │ models.py
│ │ tests.py
│ │ urls.py
│ │ views.py
│ │ __init__.py
│ │
│ ├─migrations
│ │ │ 0001_initial.py
│ │ │ __init__.py
│ │ │
│ │ └─__pycache__
│ │ 0001_initial.cpython-36.pyc
│ │ __init__.cpython-36.pyc
│ │
│ ├─static
│ │ └─js
│ │ jquery-3.3.1.min.js
│ │ local.js
│ │
│ ├─templates
│ │ error.html
│ │ index.html
│ │ __init__.py
│ │
│ └─__pycache__
│ admin.cpython-36.pyc
│ apps.cpython-36.pyc
│ forms.cpython-36.pyc
│ models.cpython-36.pyc
│ urls.cpython-36.pyc
│ views.cpython-36.pyc
│ __init__.cpython-36.pyc
│
└─vocabulary
│ settings.py
│ urls.py
│ wsgi.py
│ __init__.py
│
└─__pycache__
settings.cpython-36.pyc
urls.cpython-36.pyc
wsgi.cpython-36.pyc
__init__.cpython-36.pyc
Build & Run
build & run
python manage.py makemigrations
python manage.py migrate
python manage.py runserver
Fake Migrate
テーブルがおかしくなりやり直したいとき
python manage.py migrate --fake vocaApp zero