[Django3.0]SQLite3ではなくMySQLを使いたい

// ubuntu bionicに入っているmysqlのバージョンを確認し、dbを作る
$ mysql –version
mysql Ver 14.14 Distrib 5.7.31, for Linux (x86_64) using EditLine wrapper
$ mysql -u root -p
Enter password:
mysql> show databases;
mysql> create database myapp;
Query OK, 1 row affected (0.01 sec)

OK
それではテスト用のDjangoのappを作ります

$ mkdir test
$ cd test
$ django-admin startproject testapp
$ cd testapp
$ python manage.py startapp myapp

/myapp/settings.py の DATABASESがデータベースの設定
defaultではsqlite3になっている

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

ここをmysqlに変更します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',
]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myapp',
        'USER': 'root',
        'PASSWORD': '*****',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

myqpp/models.py

from django.db import models

class Friend(models.Model):
	name = models.CharField(max_length=100)
	mail = models.EmailField(max_length=200)
	gender = models.BooleanField()
	age = models.IntegerField(default=0)
	birthday = models.DateField()

	def __str__(self):
		return '<Friend:id=' + str(self.id) + ', ' + self.name + '(' + str(self.age) + ')>'

$ python manage.py makemigrations testapp
Traceback (most recent call last):
File “/usr/local/lib/python3.8/dist-packages/django/db/backends/mysql/base.py”, line 16, in
import MySQLdb as Database
ModuleNotFoundError: No module named ‘MySQLdb’

The above exception was the direct cause of the following exception:
// 省略
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
Did you install mysqlclient?

$ sudo apt-get install python3.8-dev
$ sudo apt-get install -y libmysqlclient-dev
$ pip install mysqlclient

$ python manage.py makemigrations testapp
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial… OK
Applying auth.0001_initial… OK
Applying admin.0001_initial… OK
Applying admin.0002_logentry_remove_auto_add… OK
Applying admin.0003_logentry_add_action_flag_choices… OK
Applying contenttypes.0002_remove_content_type_name… OK
Applying auth.0002_alter_permission_name_max_length… OK
Applying auth.0003_alter_user_email_max_length… OK
Applying auth.0004_alter_user_username_opts… OK
Applying auth.0005_alter_user_last_login_null… OK
Applying auth.0006_require_contenttypes_0002… OK
Applying auth.0007_alter_validators_add_error_messages… OK
Applying auth.0008_alter_user_username_max_length… OK
Applying auth.0009_alter_user_last_name_max_length… OK
Applying auth.0010_alter_group_name_max_length… OK
Applying auth.0011_update_proxy_permissions… OK
Applying sessions.0001_initial… OK

mysql> show tables;
+—————————-+
| Tables_in_myapp |
+—————————-+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
| myapp_friend |
+—————————-+
11 rows in set (0.00 sec)

mysql> describe myapp_friend
-> ;
+———-+————–+——+—–+———+—————-+
| Field | Type | Null | Key | Default | Extra |
+———-+————–+——+—–+———+—————-+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(100) | NO | | NULL | |
| mail | varchar(200) | NO | | NULL | |
| gender | tinyint(1) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
| birthday | date | NO | | NULL | |
+———-+————–+——+—–+———+—————-+
6 rows in set (0.00 sec)

mysqlにマイグレーションできてることは確認できました。
auth_* のテーブルが結構あるけど、やりたい事としてはusersテーブルで、email, name, password, department, (created), (updated)を管理したい。

Djangoのuser管理がどうなってるか理解する必要があるな。

[Django3.0]レイアウト用テンプレートでインクルード

layout.htmlを作成し、編集箇所を{% block * %}{% endblock %}で囲む。
includeする側は{% extends ‘sales/layout.html’ %}で読み込む。
{% load static %}は、読み込むhtml側に記載しないとErrorになる

sales/templates/sales/layout.html

{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>{% block title %}{% endblock %}</title>
	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
	{% block description %}{% endblock %}
	<meta name="Description" content="見積管理、在庫管理、販売管理はhanbai">

	{% block header_script %}{% endblock %}
</head>
<body>
	<div class="wrapper">

		<nav class="navbar navbar-expand-md navbar-dark fixed-top" style="background-color:#1e90ff">
			<a class="navbar-brand" href="/top.html">Hanbai</a>
			<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
				<span class="navbar-toggler-icon"></span>
			</button>
			<div class="collapse navbar-collapse" id="navbarCollapse">
				<ul class="navbar-nav mr-auto">
					<li class="nav-item dropdown  active">
						<a class="nav-link dropdown-toggle" href="/estimate" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">見積管理</a>
						<div class="dropdown-menu" aria-labelledby="navbarDropdown">
							<a class="dropdown-item" href="/estimate">見積一覧</a>
							<hr>
							<a class="dropdown-item" href="/estimate/input">見積登録</a>
						</div>
					</li>
					<li class="nav-item dropdown active">
						<a class="nav-link dropdown-toggle" href="/order" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">受注管理</a>
						<div class="dropdown-menu" aria-labelledby="navbarDropdown">
							<a class="dropdown-item" href="/order">受注一覧</a>
							<hr>
							<a class="dropdown-item" href="/order/input">受注登録</a>
						</div>
					</li>
					<li class="nav-item dropdown active">
						<a class="nav-link dropdown-toggle" href="/stock" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">在庫管理</a>
						<div class="dropdown-menu" aria-labelledby="navbarDropdown">
							<a class="dropdown-item" href="/stock">在庫一覧</a>
							<hr>
							<a class="dropdown-item" href="/stock/input">在庫登録</a>
						</div>
					</li>
					<li class="nav-item dropdown active">
						<a class="nav-link dropdown-toggle" href="/client" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">得意先管理</a>
						<div class="dropdown-menu" aria-labelledby="navbarDropdown">
							<a class="dropdown-item" href="/client">得意先一覧</a>
							<hr>
							<a class="dropdown-item" href="/client/input">得意先登録</a>
						</div>
					</li>
					<li class="nav-item dropdown active">
						<a class="nav-link dropdown-toggle" href="/master" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">その他</a>
						<div class="dropdown-menu" aria-labelledby="navbarDropdown">
							<a class="dropdown-item" href="/master">自社基本情報</a>
						</div>
					</li>
				</ul>
				<ul class="navbar-nav">
					<li class="nav-item">
						<a class="nav-link" href="">ログアウト</a>
					</li>
				</ul>
			</div>
		</nav>

		<div class="container">
			{% block content %}{% endblock %}
				
		</div>
		<footer>
			<p>&copy; Hanbai All Right Reserved.</p>
		</footer>
	</div>

	{% block script %}{% endblock %}
	
</body>
</html>

sales/templates/sales/index.html

{% extends 'sales/layout.html' %}
{% load static %}

{% block title %}Top | hanbai - トップページを表示しています{% endblock %}

{% block description %}<meta name="Description" content="見積管理、在庫管理、販売管理はhanbai">{% endblock %}

{% block header_script %}
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

	<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

	<link rel="stylesheet" href="{% static 'sales/css/styles.css' %}">
	<script src="/js/main.js"></script>
{% endblock %}

	
{% block content %}
			<div class="top">
				<nav aria-label="パンくずリスト">
					<ol class="breadcrumb">
	  					<li class="breadcrumb-item active" aria-current="page">ホーム</li>
					</ol>
				</nav>
				// 省略
{% endblock %}

{% block script %}
	// 省略
{% endblock %}

Sugeeeeeeeee 上手く表示されています。

これをログイン以外のページも、block, endblockの中に流し込んでいきます。

{% extends 'sales/layout.html' %}
{% load static %}

{% block title %}{% endblock %}

{% block description %}{% endblock %}

{% block header_script %}
{% endblock %}

	
{% block content %}
{% endblock %}

{% block script %}
{% endblock %}

なかなか面白い。

[Django3.0]urls.pyとviews.py

フロントに沿って、urls.py、views.py、*.htmlを作ってきます。
editはパラメータの書き方が異なるので、モデルを作った後に作ります。

/sales/urls.py

urlpatterns = [
	path('login/', views.login, name='login'),
	path('', views.index, name='index'),
	path('client/', views.client, name='client'),
	path('client/input', views.client_input, name='client_input'),
	path('client/detail', views.client_detail, name='client_detail'),
	path('master/edit', views.master, name='master'),
	path('estimate/', views.estimate, name='estimate'),
	path('estimate/input', views.estimate_input, name='estimate_input'),
	path('order/', views.order, name='order'),
	path('order/input', views.order_input, name='order_input'),
	path('stock', views.stock, name='stock'),
	path('stock/input', views.stock_input, name='stock_input'),
]

/sales/views.py

from django.shortcuts import render
from django.http import HttpResponse

def login(request):
	return render(request, 'sales/login.html')

def index(request):
	return render(request, 'sales/index.html')

def client(request):
	return render(request, 'sales/client.html')

def client_input(request):
	return render(request, 'sales/client_input.html')

def client_detail(request):
	return render(request, 'sales/client_detail.html')

def master(request):
	return render(request, 'sales/master.html')

def estimate(request):
	return render(request, 'sales/estimate.html')

def estimate_input(request):
	return render(request, 'sales/estimate_input.html')

def order(request):
	return render(request, 'sales/order.html')

def order_input(request):
	return render(request, 'sales/order_input.html')

def stock(request):
	return render(request, 'sales/stock.html')

def stock_input(request):
	return render(request, 'sales/stock_input.html')

ヘッダとログインページ以外のナビゲーションは共通なので、続いて、共通箇所をインクルードにして一括管理したい。

[Django]templatesを一気に作る

### 画面遷移図

### URL一覧

まずtemplateのhtmlを流し込む前に、urls.pyとviews.pyの一覧を作ってからhtmlを流し込めば良いのか?
いや、urls.pyに記載してもviews.pyに記載がないとAttributeErrorになるので、urls.py -> views.py -> *.html をループさせた方が作業効率は良さそうである。

/sales/urls.py

urlpatterns = [
	path('login/', views.login, name='login'),
	path('', views.index, name='index'),
]

/sales/views.py

def index(request):
	return render(request, 'sales/index.html')

/sales/templates/sales/index.html

// 省略

load staticを毎ページ修正するのは面倒ではある。

[Django]staticフォルダにstyle.cssを置こう

まずsales配下にstaticフォルダ、その配下にsalesフォルダ、更にその下にcssフォルダを作成します。

/sales/static/sales/css/style.css
// 省略 ※webpackでsassから作ったcssを置く

/templates/sales/login.html

{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>ログイン | hanbai - メールアドレス、パスワードを入力してください</title>
	// 省略

	<link rel="stylesheet" href="{% static 'sales/css/styles.css' %}">
	<script src="/js/main.js"></script>
</head>
// 省略

imgフォルダも作ります。

<img id="profile-img" class="profile-img-card" src="{% static 'sales/img/avatar.png' %}">

Wow!! なるほど、Djangoオモロイ!
取り敢えずこれはモデルの前に先に全部のurlspatternとtemplate嵌め込みをやれば良いのかな。順番がよくわからないが、フロント部分から手を付けた方が効率的そう。

djangoでテンプレートにはめ込もう

/hanbai/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'sales',
]

/sales/templates/sales/login.html

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>ログイン | hanbai - メールアドレス、パスワードを入力してください</title>
	<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
	<meta name="Description" content="見積管理、在庫管理、販売管理はhanbai">

	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

	<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

	<link rel="stylesheet" href="css/style.css">
	<script src="/js/main.js"></script>
</head>
<body>
	<div class="wrapper">

		<nav class="navbar navbar-expand-md navbar-dark fixed-top" style="background-color:#1e90ff">
			<a class="navbar-brand disabled" href="">Hanbai</a>
		</nav>

		<div class="container">
			<div class="login">
				<div class="row">
					<div class="card card-container">
						<h1 class="text-center login-title">Hanbai</h1>
						<img id="profile-img" class="profile-img-card" src="/img/avatar.png">
						<div class="account-wall">
							<form class="form-signin">
								<input type="email" id="inputEmail" class="form-control" placeholder="Email" required autofocus>
								<input type="password" id="inputPassword" class="form-control" placeholder="Password" required>
								<button class="btn btn-lg btn-primary btn-block btn-signin" type="submit">
								ログイン</button>
								・ログインパスワードをお忘れの方は
								<a href="#">こちら</a><span class="clearfix"></span>
								・アカウントをお持ちでない方は
								<a href="#">こちら</a><span class="clearfix"></span>
							</form>
						</div>
					</div>
				</div>
			</div>
		</div>
		<footer>
			<p>&copy; Hanbai All Right Reserved.</p>
		</footer>
	</div>
</body>
</html>

/sales/urls.py

from django.urls import path
from . import views

urlpatterns = [
	path('/login', views.login, name='login'),
]

/sales/views.py

from django.shortcuts import render
from django.http import HttpResponse

def login(request):
	return render(request, 'sales/login.html')

cssと画像が効いていませんが、基本型はできました。

djangoでappを始めよう

$ python -V
Python 3.8.0
$ django-admin startproject hanbai
$ python manage.py runserver 192.168.33.10:8000

### アプリケーションの作成
$ python manage.py startapp sales
$ git init

/sales/views.py

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
	return HttpResponse("Hello Django!")

/hanbai/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('sales.urls')),
]

/sales/urls.py

from django.urls import path
from . import views

urlpatterns = [
	path('', views.index, name='index'),
]

urlパターンはpath(‘/’)とするとエラーになるので、path(”)とする必要があります。
これからfrontで作成したviewを組み込んで行きます。

初めての半田ゴテ

Arduinoやラズパイを触ると、無精に触りたくなります。
ということで、半田ごてセットを購入しました。

dav

机に直置きは怖いので、タオルの上で作業します。

dav

はんだ線を付けても全く溶解しなかったので不可解に思いましたが、ハンダゴテの金属が加熱するのに数分程度時間がかかるようで、少し時間をおいたらハンダ線が溶け始めました。

dav

なんやこの臭いは? 臭いが強烈
作業は室内より室外の方が向いているように思いました。

しかし半田ごてはやりたかったことの一つ。
まあ、一歩前進はしました。

トランジスタとは?

トランジスタとは電子回路において信号を増幅またはスイッチングすることができる半導体素子

– 信号を増幅する
– 回路をオンオフする
– NPNやPNPという順番で半導体を挟んでいる(Eエミッタ、Bベース、Cコネクタ)
– バイポーラ型トランジスタ、ユニポーラ型トランジスタ、フォトトランジスタ、サイリスタなどの種類がある

dav

### トランジスタの使い方
微弱な電流を流してコレクタ電流を増幅させる

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(8,OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.println("HIGH");
  digitalWrite(8,HIGH);
  delay(2500);

  Serial.println("LOW");
  digitalWrite(8,LOW);
  delay(2500);
}
dav