[Django3.0] MySQL8にrootでmigrationしようとしてAccess deniedとなる時

bionicからfocal(Ubuntu20.04)で作り直している手順で、mysql8にmigrationしようとすると、Access denied for user ‘root’@’localhost'”となった。

### focalにMySQL 8.20 インストール
$ sudo apt install -y mysql-server
$ mysqld –version
$ sudo service mysql start
$ sudo mysql_secure_installation
$ sudo mysql -u root -p

### Django
$ pip3 install Django==3.0.4

### library インストール
// 省略

### git clone
$ git clone https://github.com/*/${appName}.git
$ cd ${appName}
$ git branch dev
$ git checkout dev

### init.py追記

import pymysql
pymysql.install_as_MySQLdb()

$ pip3 install PyMySQL

### migration
$ python3 manage.py makemigrations sales

->django.db.utils.OperationalError: (1698, “Access denied for user ‘root’@’localhost'”)

なんですと???
MySQL8はrootユーザで外部からアクセスできないらしい。
という事で、Django用のユーザを作ってあげる必要がある。

$ sudo mysql –u root -p
mysql> SHOW VARIABLES LIKE ‘validate_password%’;
mysql> set global validate_password.length=6;
mysql> set global validate_password.policy=LOW;
mysql> CREATE USER ‘django’@’%’ IDENTIFIED BY ‘hogehoge’;
mysql> GRANT ALL PRIVILEGES ON . TO ‘django’@’%’ WITH GRANT OPTION;
mysql> FLUSH PRIVILEGES;

settings.pyを修正して再度migration
$ python3 manage.py makemigrations sales
$ python3 manage.py migrate
$ python3 manage.py createsuperuser
$ python3 manage.py runserver 192.168.33.10:8000
動作確認

ヒョーーーーー、とりあえず20.04、centos8を普段使いの環境にしたから一安心^^

[Django3.0]親モデルからForeignKeyの子モデルを逆参照して各アイテムの関連レコード数をforループで表示したい

現在Djangoで、見積モデル(Estimates)と受注モデル(Orders)が、それぞれ顧客モデル(Clients)をForeignKeyで参照しています。
顧客一覧ページで、各顧客ごとの見積数および受注数を表示する為、顧客モデル(Clients)から見積モデル(Estimates)および受注モデル(Orders)を逆参照して、顧客ごとの見積件数、受注件数を表示したい
モデルの関係は以下の通りです。

models.py

class Clients(models.Model):
	name = models.CharField(max_length=255)
	name_kana = models.CharField(max_length=255, null=True, blank=True)
        // 省略

class Estimates(models.Model):
	client = models.ForeignKey(Clients, null=True, blank=True, on_delete=models.PROTECT)
	estimate_date = models.DateField()
        // 省略

class Orders(models.Model):
	client = models.ForeignKey(Clients, null=True, blank=True, on_delete=models.PROTECT)
	order_date = models.DateField()
        // 省略

顧客一覧ページのUIは以下の通りで、Clientsモデルからデータを取得しforループで表示させています。

views.py

data = Clients.objects.all()
page = Paginator(data, 3)
params = {
	'data' : page.get_page(num)
}
return render(request, 'sales/client.html', params)

template

{% for item in data %}
						<tr>
							<td>{{item.id}}</td>
							<td class="text-nowrap">{{item.name}}</td>
							<td class="text-nowrap">〒{{item.zipcode}} {{item.prefecture}}{{item.address|truncatechars:20}}</td>
							<td>5</td>
							<td>6</td>
							<td class="text-nowrap"><button class="btn btn-light" onclick="location.href='/client/detail/{{item.id}}'">詳細</button> <button class="btn btn-light" onclick="location.href='/client/edit/{{item.id}}'">編集</button> <a href="#modal"><button class="btn btn-light del" id="{{item.id}}" value="{{item.name}}">削除</button></a></td>
						</tr>
						{% endfor %}

やり方を色々調べたが、同じようなことをやってるトラブルシューティングがなく、大苦戦。。。。
だが、さらに調べていると、どうやら「1データを基準にするだけなら *.${modelName}_set という書き方で逆参照可能」らしい。
逆参照は、forループを回しているテンプレート側でやると上手くいかなかったので、views.py側で処理をする事にした。
具体的には、Clientsモデルから顧客データを取得し、forループで各顧客データごとの見積数、受注数を逆参照して、配列に追加し、テンプレート側では呼び出すだけにした。
client.estimates_set.count()、client.orders_set.count()で、レコード数を取得している。

		data = Clients.objects.all()
		i = 0
		for item in data:
			client = Clients.objects.get(id=item.id)
			data[i].estimate = client.estimates_set.count()
			data[i].order = client.orders_set.count()
			i += 1
		page = Paginator(data, 3)
		params = {
			'data' : page.get_page(num)
		}
	return render(request, 'sales/client.html', params)
{% for item in data %}
						<tr>
							<td>{{item.id}}</td>
							<td class="text-nowrap">{{item.name}}</td>
							<td class="text-nowrap">〒{{item.zipcode}} {{item.prefecture}}{{item.address|truncatechars:20}}</td>
							<td>{{item.estimate}}</td>
							<td>{{item.order}}</td>
							<td class="text-nowrap"><button class="btn btn-light" onclick="location.href='/client/detail/{{item.id}}'">詳細</button> <button class="btn btn-light" onclick="location.href='/client/edit/{{item.id}}'">編集</button> <a href="#modal"><button class="btn btn-light del" id="{{item.id}}" value="{{item.name}}">削除</button></a></td>
						</tr>
						{% endfor %}

おおおおおおおおお、上手くいきました。
疲れたわ。。😇😇😇

[Django3.0] PDFの見積書ダウンロード機能を作る

まずviewから

### template
対象の見積書のidを渡します。

<tbody>
						{% for item in data %}
						<tr>
							// 省略
							<td class="text-nowrap"><button class="btn btn-danger" onclick="location.href='/pdf/{{item.id}}'">PDF</button></td>
							// 省略
						</tr>
						{% endfor %}
					</tbody>

### urls.py
views.pyにint:idを渡します。

urlpatterns = [
	// 省略
	path('pdf/<int:id>', views.pdf, name="pdf"),
]

### views.py
reportlabを読み込んで、対象IDの見積データおよび自社情報をmodelから引っ張ってきて見積書pdfをmake()し、作成したpdfをreturnする
modelから引っ張ってくるところ以外はdjangoを使わずにローカルでテストした書き方と同じ
3桁でカンマをつけるには”{:,d}”.format()と書く

from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
from reportlab.lib.pagesizes import A4, portrait
from reportlab.platypus import Table, TableStyle
from reportlab.lib.units import mm
from reportlab.lib import colors

def pdf(request, id):
	make(id)
	response = HttpResponse(open('./sales/static/sales/estimate.pdf','rb').read(), content_type='application/pdf')
	response["Content-Disposition"] = "filename=app.pdf"
	return response


def make(id): # ファイル名
    pdf_canvas = set_info(filename="estimate") # キャンバス名
    print_string(pdf_canvas, id)
    pdf_canvas.save() # 保存

def set_info(filename):
	pdf_canvas = canvas.Canvas("./sales/static/sales/{0}.pdf".format(filename))
	pdf_canvas.setAuthor("hpscript")
	pdf_canvas.setTitle("見積書")
	pdf_canvas.setSubject("見積書")
	return pdf_canvas

def print_string(pdf_canvas, id):
	try:
		data = Estimates.objects.get(id=id)
		master = Master.objects.get(id=1)
        // 省略
        except Estimates.DoesNotExist:
		return redirect('/estimate/1')

見積書のレイアウトを作るところが少し時間がかかるが、結構達成感あるね
うむ、OK 続いて受注管理を作っていこう

[Django3.0]datepickerの範囲指定で検索して表示する

見積一覧ページで、「日付」「会社名」「件名」でページ内検索できるようにする。
なお、日付は、範囲指定か、以上以下で検索できるようにする

画面

### template

<form action="/estimate/1" method="post">
				{% csrf_token %}
				<div class="form-group row">
						<label for="datepicker_s" class="col-md-1 col-form-label">日付</label>
						<div class="col-md-2">
							<input name="datepicker_s" type="text" class="form-control align-bottom" id="start" placeholder="開始">
						</div>
						<div class="col-md-2">
							<input name="datepicker_e" type="text" class="form-control" id="end" placeholder="終了">
						</div>
						<label for="client_name" class="col-md-1 col-form-label">会社名</label>
						<div class="col-md-6">
							<input name="client_name" type="text" class="form-control" id="tel" placeholder="得意先会社名">
						</div>
				</div>

				<div class="form-group row">
						<label for="title" class="col-md-1 col-form-label">見積件名</label>
						<div class="col-md-11">
							<input type="text" class="form-control align-bottom" name="title" id="title" placeholder="見積件名">
						</div>
				</div>

				<div class="">
						<button class="btn search-btn text-center" type="submit">検索</button>
				</div>
			</form>

			<span>{{ query }}</span>

JS

$(function(){
			var format = 'yy-mm-dd';

			var start = $("[name=datepicker_s]").datepicker({
				dateFormat: 'yy-mm-dd'
			}).on("change", function(){
				end.datepicker("option", "minDate", getDate(this));
			});

			var end = $("[name=datepicker_e]").datepicker({
				dateFormat: 'yy-mm-dd'
			}).on("change", function(){
				start.datepicker("option", "maxDate", getDate(this));
			});

			function getDate(element){
				var date;
				try {
					date = $.datepicker.parseDate(format, element.value);
				} catch(error){
					date = null;
				}
				return date;
			}
		});

html側で「終了」が「開始」より前で指定できないようバリデーションがかかります。

### views.py
– 1.「開始」「終了」の入力があった場合、2.「開始」のみ入力があった場合、3.「終了」のみ入力があった場合、4.「開始」「終了」の入力がないPOSTの場合、5.「GET」の場合 でそれぞれレコードを取得します。
– ForeginKeyのクエリを検索する場合は、${model}__${column}で検索する。ここでは、顧客の会社名一部一致の検索のため、client__name__containsとしている。
– 検索内容を検索結果ページに表示させる

def estimate(request, num=1):
	if(request.method=='POST' and request.POST['datepicker_s'] and request.POST['datepicker_e']):
		data = Estimates.objects.filter(estimate_date__range=(request.POST['datepicker_s'], request.POST['datepicker_e']), client__name__contains=request.POST['client_name'], title__contains=request.POST['title']).order_by('-id')
		query = "「" + request.POST['datepicker_s'] + "〜" + request.POST['datepicker_e'] + "」"
		query += "「" + request.POST['client_name'] + "」" if request.POST['client_name'] else ""
		query += "「" + request.POST['title'] + "」" if request.POST['title'] else ""
		query += "の検索結果"
	elif(request.method=='POST' and request.POST['datepicker_s']):
		data = Estimates.objects.filter(estimate_date__gte=request.POST['datepicker_s'], client__name__contains=request.POST['client_name'], title__contains=request.POST['title']).order_by('-id')
		query = "「" + request.POST['datepicker_s'] + "〜」"
		query += "「" + request.POST['client_name'] + "」" if request.POST['client_name'] else ""
		query += "「" + request.POST['title'] + "」" if request.POST['title'] else ""
		query += "の検索結果"
	elif(request.method=='POST' and request.POST['datepicker_e']):
		data = Estimates.objects.filter(estimate_date__lte=request.POST['datepicker_e'], client__name__contains=request.POST['client_name'], title__contains=request.POST['title']).order_by('-id')	
		query = "「〜" + request.POST['datepicker_e'] + "」"
		query += "「" + request.POST['client_name'] + "」" if request.POST['client_name'] else ""
		query += "「" + request.POST['title'] + "」" if request.POST['title'] else ""
		query += "の検索結果"
	elif(request.method=='POST'):
		data = Estimates.objects.filter(client__name__contains=request.POST['client_name'], title__contains=request.POST['title']).order_by('-id')
		query += "「" + request.POST['client_name'] + "」" if request.POST['client_name'] else ""
		query += "「" + request.POST['title'] + "」" if request.POST['title'] else ""
	else:
		data = Estimates.objects.all().order_by('-id')
		query = ""
	page = Paginator(data, 3)
	count = data.count()
	total = data.aggregate(Sum('total'))
	params = {
		'data' : page.get_page(num),
		'count' : count,
		'total' : total,
		'query' : query,
	}
	return render(request, 'sales/estimate.html', params)

これで1ページ目は上手くいってるんだけど、2ページ目はpostではなくgetになってしまうから、上手くいかんな。どうしたらいいんだろうか。

[Django3.0] 1対多(hasMany)のモデルを作成

顧客が多数の見積を取る事を考え、sales_clientsテーブルから1対多(hasMany)の関係にあるテーブルを作成したい。

見積登録画面

見積画面を元にテーブルのデータ型を作成していきます。
mysqlのdateはDateField、integerはIntegerFieldにします。
clientはhasManyのFoerignKeyとなるものです。

データ型が一通り出来たら、ER図を修正します。

さて、いよいよデータ型を元にmodels.pyを作っていきます。
リレーションは、models.ForeignKey(${modelName})で書きます。
顧客レコードが削除されたら、顧客レコードに紐づいた見積も一緒に削除されると困るので、on_delete=models.PROTECTと設定してあげます。

models.py

class Estimates(models.Model):
	client = models.ForeignKey(Clients, on_delete=models.PROTECT)
	estimate_date = models.DateField(auto_now=True)
	position = models.CharField(max_length=50, null=True, blank=True)
	name = models.CharField(max_length=255, null=True, blank=True)
	title = models.CharField(max_length=255)
	classification1 = models.CharField(max_length=255, null=True, blank=True)
	// classification2~classification10は省略
	type1 = models.CharField(max_length=255, null=True, blank=True)
	// type2〜type10は省略
	name1 = models.CharField(max_length=255, null=True, blank=True)
	// name2〜name10は省略
	size1 = models.CharField(max_length=255, null=True, blank=True)
	// size2〜size10は省略
	unit1 = models.IntegerField(null=True, blank=True)
	// unit2〜unit10は省略
	price1 = models.IntegerField(null=True, blank=True)
	// price2〜price10は省略
	total = models.IntegerField(null=True, blank=True)
	remark = models.TextField(max_length=300, null=True, blank=True)
	created_at = models.DateTimeField(auto_now_add=True)
	updated_at = models.DateTimeField(auto_now=True)

	def __str__(self):
		return self.title

### migration
$ python manage.py makemigrations sales
-> 0004_auto_20200913_1714.pyが作成されたので中身を見てみます。fieldsの末尾にmodels.ForeignKeyが作られている事がわかります。

fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('estimate_date', models.DateField(auto_now=True)),
                ('position', models.CharField(blank=True, max_length=50, null=True)),
                // 省略
                ('client', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='sales.Clients')),
            ],

$ python manage.py migrate

mysql> show tables;
mysql> describe sales_estimates;
+——————+————–+——+—–+———+—————-+
| Field | Type | Null | Key | Default | Extra |
+——————+————–+——+—–+———+—————-+
| id | int(11) | NO | PRI | NULL | auto_increment |
// 省略
| client_id | int(11) | NO | MUL | NULL | |
+——————+————–+——+—–+———+—————-+
70 rows in set (0.00 sec)

ぎゃああああああああああああああああああああああああああああああ
client_idが出来てるううううううううううううううううううう

[Django3.0]remodalからの削除処理

顧客一覧ページから、対象の削除ボタンを押下するとremodalで確認ボタンが表示され、OKを押すとレコードが削除されるようにする。

### mysql
mysql> select * from sales_clients;
-> 2つレコードが入っています。

### view
– remodalをformにして、client_idをinput hiddenで削除完了ページにpostします。

remodal

{% block script %}
	<div class="remodal" data-remodal-id="modal">
		<form method="post" action="/client/delete" id="form_id">
			{% csrf_token %}
			<button data-remodal-action="close" class="remodal-close"></button>
				<input type="hidden" id="client_id" name="client_id">
			    <h1>得意先削除</h1>
			    <p>
			    <span id="company_name"></span>を削除して宜しいでしょうか?
			    </p>
			    <br>
			<button data-remodal-action="cancel" class="remodal-cancel">Cancel</button>
			<button data-remodal-action="confirm" class="remodal-confirm">OK</button>
		</form>
	</div>
	<script src="{% static 'sales/js/remodal.min.js' %}"></script>
	<script>
		var remodal = $('[data-remodal-id=modal]').remodal();

		$('.del').on('click', function(){
			var id = $(this).attr("id");
			var name = $(this).attr("value");
			document.getElementById("company_name").innerHTML = name;
			document.getElementById("client_id").setAttribute("value", id);
		})

		$(document).on('confirmation', remodal, function(){
			$('#form_id').submit();
		});
	</script>
{% endblock %}

### views.py
views.pyでは、*.objects.getで対象のレコードを取得して削除します。

/sales/views.py

def client_delete(request):
	if(request.method == 'POST'):
		client_id = request.POST['client_id']
		client = Clients.objects.get(id=client_id)
		client.delete()
		return render(request, 'sales/client_delete.html')
	return render(request, 'sales/client_delete.html')

### 削除実行
mysql> select * from sales_clients;
+—-+——————————————–+——————————–+——–+————+—————–+————–+————————-+———-+————+——————————-+————–+————–+————–+—————–+——–+—————————-+—————————-+
| id | name | name_kana | office | department | position | charge | charge_mail | zipcode | prefecture | address | tel | fax | name_top | position_top | remark | created_at | updated_at |
+—-+——————————————–+——————————–+——–+————+—————–+————–+————————-+———-+————+——————————-+————–+————–+————–+—————–+——–+—————————-+—————————-+
| 1 | ジャパンソフトウェア株式会社 | ジャパンソフトウェア | 本社 | 営業部 | 代表取締役 | 佐藤太郎 | staro@japansoftware.com | 100-0002 | 東京都 | 千代田区皇居外苑1-2-3 | 03-1234-5678 | 03-1234-5679 | 山本五郎 | 代表取締役 | | 2020-08-30 02:09:35.555187 | 2020-08-30 02:09:35.555259 |
+—-+——————————————–+——————————–+——–+————+—————–+————–+————————-+———-+————+——————————-+————–+————–+————–+—————–+——–+—————————-+—————————-+
1 row in set (0.00 sec)

deleteはviews.pyで*.delete()で削除できる。
DjangoのCRUDは一通りマスターしました。
ところでDjangoは論理削除の機能はあるんでしょうか? is_activeのカラムを作って、削除時にupdateするのかな。

[Django3.0]DBのリストをviewに表示

sales_clientsテーブルのレコードを得意先一覧ページで表示させたい。
レコード全てを取得する際には、views.pyで${modelName}.objects.all()として取得する。

mysql> select * from sales_clients;
+—-+——————————————–+———————————–+——–+————+—————–+————–+————————–+———-+————+———————————————————————–+————–+————–+————–+—————–+——–+—————————-+—————————-+
| id | name | name_kana | office | department | position | charge | charge_mail | zipcode | prefecture | address | tel | fax | name_top | position_top | remark | created_at | updated_at |
+—-+——————————————–+———————————–+——–+————+—————–+————–+————————–+———-+————+———————————————————————–+————–+————–+————–+—————–+——–+—————————-+—————————-+
| 1 | ジャパンソフトウェア株式会社 | ジャパンソフトウェア | 本社 | 営業部 | 代表取締役 | 佐藤太郎 | staro@japansoftware.com | 100-0002 | 東京都 | 千代田区皇居外苑1-2-3 | 03-1234-5678 | 03-1234-5679 | 山本五郎 | 代表取締役 | | 2020-08-30 02:09:35.555187 | 2020-08-30 02:09:35.555259 |
| 16 | 六本木ソフトウェア株式会社 | ロッポンギソフトウェア | 本社 | 営業部 | 課長 | 田中太郎 | ttanaka@roppongisoft.com | 106-6240 | 東京都 | 港区六本木住友不動産六本木グランドタワー40階 | 03-1234-5678 | 03-1234-5679 | 山田一郎 | 代表取締役 | | 2020-09-05 03:18:49.981333 | 2020-09-05 03:18:49.981377 |
+—-+——————————————–+———————————–+——–+————+—————–+————–+————————–+———-+————+———————————————————————–+————–+————–+————–+—————–+——–+—————————-+—————————-+
2 rows in set (0.00 sec)

sales/views.py

def client(request):
	data = Clients.objects.all()
	params = {
		'data' : data
	}
	return render(request, 'sales/client.html', params)

/templates/sales/client.html

<table class="table table-striped">
					<thead >
						<tr>
							<th scope="col" class="font-weight-normal">ID</th>
							<th scope="col" class="font-weight-normal">会社名</th>
							<th scope="col" class="font-weight-normal">住所</th>
							<th scope="col" class="font-weight-normal">見積</th>
							<th scope="col" class="font-weight-normal">受注</th>
							<th scope="col" class="font-weight-normal">アクション</th>
						</tr>
					</thead>
					<tbody>
						{% for item in data %}
						<tr>
							<td>{{item.id}}</td>
							<td class="text-nowrap">{{item.name}}</td>
							<td class="text-nowrap">〒{{item.zipcode}} {{item.prefecture}}{{item.address|truncatechars:20}}</td>
							<td>4</td>
							<td>6</td>
							<td class="text-nowrap"><button class="btn btn-light">詳細</button> <button class="btn btn-light">編集</button> <button class="btn btn-light" onclick="location.href='#modal'">削除</button></td>
						</tr>
						{% endfor %}
					</tbody>	
				</table>

住所の文字数を制限するため、item.address|truncatechars:20とすると、20文字以上は自動的に三点リーダで表示されます。

続いて、詳細、編集、削除ボタンのリンクを作成していきます。

[Django3.0] ModelFormによるデータ更新の書き方2

views.pyでは、*.objects.get(id=*)としてレコードを取り出し、save()で更新する。

/sales/views.py

def master_complete(request):
	data = Master.objects.get(id=1)
	if(request.method == 'POST'):
		master = MasterForm(request.POST, instance=data)
		master.save()
	return render(request, 'sales/master_complete.html')

mysql側でデータが更新されている事を確認します。

mysql> select * from sales_master;
+—-+————————————–+——–+———-+————+—————————-+————–+————–+——————–+————–+—————–+—————————-+—————————-+
| id | name | office | zipcode | prefecture | address | tel | fax | mail | name_top | position_top | created_at | updated_at |
+—-+————————————–+——–+———-+————+—————————-+————–+————–+——————–+————–+—————–+—————————-+—————————-+
| 1 | 東京テクノロジー株式会社 | 本社 | 100-6321 | 東京都 | 千代田区丸の内2-4-2 | 03-1234-5678 | 03-1234-5679 | info@tokyotech.com | 山田太郎 | 代表取締役 | 2020-08-22 12:30:30.000000 | 2020-08-27 11:50:16.915337 |
+—-+————————————–+——–+———-+————+—————————-+————–+————–+——————–+————–+—————–+—————————-+—————————-+
1 row in set (0.00 sec)

get, create, updateはマスターしました。
次はバリデーションでしょうか。

[Django3.0] ModelFormによるupdateの書き方

sales_masterテーブルのid=1のレコードをformに表示させたい
forms.pyでModelFormを使用する
view側ではdjango-widdget-tweaksを引き続き使用

mysql> select * from sales_master;
+—-+————————————–+——–+———-+————+—————————-+————–+————–+——————–+————–+—————–+—————————-+—————————-+
| id | name | office | zipcode | prefecture | address | tel | fax | mail | name_top | position_top | created_at | updated_at |
+—-+————————————–+——–+———-+————+—————————-+————–+————–+——————–+————–+—————–+—————————-+—————————-+
| 1 | 東京テクノロジー株式会社 | 本社 | 100-6321 | 東京都 | 千代田区丸の内2-4-1 | 03-1234-5678 | 03-1234-5679 | info@tokyotech.com | 山田太郎 | 代表取締役 | 2020-08-22 12:30:30.000000 | 2020-08-22 12:30:30.000000 |
+—-+————————————–+——–+———-+————+—————————-+————–+————–+——————–+————–+—————–+—————————-+—————————-+
1 row in set (0.00 sec)

/sales/forms.py

from django import forms
from.models import Master

class MasterForm(forms.ModelForm):
	class Meta:
		model = Master
		fields = ['name', 'office', 'zipcode', 'prefecture', 'address', 'tel', 'fax', 'mail', 'name_top', 'position_top']

/sales/views.py

def master(request):
	data = Master.objects.get(id=1)
	params = {
		'form': MasterForm(instance=data)
	}
	return render(request, 'sales/master.html', params)

/sales/templates/sales/master.html
-> 変更なし

上手く引っ張ってこれました。

[Django3.0]MySQLへのデータ登録

受け取る側のviews.pyでModesに入れれば良い

/sales/views.py

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

def master_complete(request):
	if(request.method == 'POST'):
		name = request.POST['name']
		office = request.POST['office']
		zipcode = request.POST['zipcode']
		prefecture = request.POST['prefecture']
		address = request.POST['address']
		tel = request.POST['tel']
		fax = request.POST['fax']
		mail = request.POST['mail']
		name_top = request.POST['name_top']
		position_top = request.POST['position_top']
		master = Master(name=name, office=office, zipcode=zipcode, prefecture=prefecture, address=address,
			tel=tel,fax=fax, mail=mail, name_top=name_top, position_top=position_top)
		master.save()
	return render(request, 'sales/master_complete.html')

mysql> select * from sales_master;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect…
Connection id: 44
Current database: hanbai

+—-+————————————–+——–+———-+————+—————————-+————–+————–+——————–+————–+—————–+—————————-+—————————-+
| id | name | office | zipcode | prefecture | address | tel | fax | mail | name_top | position_top | created_at | updated_at |
+—-+————————————–+——–+———-+————+—————————-+————–+————–+——————–+————–+—————–+—————————-+—————————-+
| 1 | 東京テクノロジー株式会社 | 本社 | 100-6321 | 東京都 | 千代田区丸の内2-4-1 | 03-1234-5678 | 03-1234-5679 | info@tokyotech.com | 山田太郎 | 代表取締役 | 2020-08-22 12:30:30.000000 | 2020-08-22 12:30:30.000000 |
| 2 | テスト | 本社 | 100-0001 | 東京都 | 千代田区千代田1-1-1 | 03-1234-5678 | 03-1234-5679 | test@gmail.com | 山田太郎 | | 2020-08-26 22:03:28.299894 | 2020-08-26 22:03:28.299937 |
+—-+————————————–+——–+———-+————+—————————-+————–+————–+——————–+————–+—————–+—————————-+—————————-+
2 rows in set (0.00 sec)