Django
Python3

Djangoでシーケンス使ってみた


はじめに

やったことをまとめると以下3つ



  • 1日で出来る!DjangoでCRUDを作るの続き(ソースはここのページのものが基準になってます)

  • シーケンスをちゃんと使うようにした


    • 連番の取得を、登録されている最大値+1からの脱却




  • FormModelを少し使えるようにした



    • views.pytemplatesの連携をTodoを利用していたが、TodoFormを使うように修正




シーケンスを使ってみた

Djangoで提供してくれているようなのでそちらを使ってみた

[vagrant@localhost mysite]$ sudo pip3 install django-sequences

Collecting django-sequences
Downloading https://files.pythonhosted.org/packages/7a/2d/0c21146f8283ee56b3d920859e55be2550b2c8fb9fb8b6aa9ac2930690ea/django_sequences-2.2-py2.py3-none-any.whl
Installing collected packages: django-sequences
Successfully installed django-sequences-2.2
[vagrant@localhost mysite]$ python3 manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sequences, sessions, todos
Running migrations:
Applying sequences.0001_initial... OK
[vagrant@localhost mysite]$ python3 manage.py shell
Python 3.7.0 (default, Jul 26 2018, 15:06:09)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from sequences import get_next_value
>>> get_next_value('todo_seq')
1
>>> get_next_value('todo_seq')
2
>>> get_next_value('todo_seq_next')
1
>>> get_next_value('todo_seq')
3

これでよしなにsequenceで発番ができたので、シーケンスを使うようにする


todos/views.py

def add(request):

t1 = Todo()
t1 = get_next_value('todo_seq')
t = TodoForm(request.POST, instance=t1)
t.save()
return HttpResponseRedirect(reverse('index'))

ついでに、save()のたびに日付は自動更新されるようにする


todos/models.py

update_date = models.DateTimeField('date published', auto_now=True)




  • auto_now=Trueをつけるだけ



    • auto_now_add=Trueなら登録時のみ日付が自動でささる



      • insert_dateupdate_dateで分けているなら使うべき





※ソースは一部抜粋


FormModelを(ちょっと)使ってみた

基本的にTodoFormを使って連携するように修正 ※ただし、todo_idだけは別途連携してる・・・

ついでに、add:登録update:更新を共通化する。


todos/views.py

from django.http import HttpResponse, HttpResponseRedirect

from django.urls import reverse
from django.shortcuts import render
from todos.models import Todo, TodoForm

def index(request):
todo_list = Todo.objects.all()
context = {'todo_list': todo_list}
return render(request, 'todos/index.html', context)

def new(request):
context = {'form': TodoForm(), 'todo_id': ""}
return render(request, 'todos/new.html', context)

def add(request):
todo = Todo()
todo.todo_id = request.POST['todo_id']
todo_form = TodoForm(request.POST, instance=todo)

if todo_form.is_valid():
todo_form.save()
return HttpResponseRedirect(reverse('index'))
else:
return render(request, 'todos/new.html', {'form': todo_form, 'todo_id': todo_id})

def detail(request, todo_id):
todo = Todo.objects.get(todo_id=todo_id)
context = {'form': TodoForm(instance=todo), 'todo_id': todo_id}
return render(request, 'todos/new.html', context)

def delete(request, todo_id):
t = Todo.objects.get(todo_id=todo_id)
t.delete()
return HttpResponseRedirect(reverse('index'))



  • パラメータcontextform: TodoForm()になるように修正



    • todo_idは別で連携する




  • todo_form.is_validで登録可能かチェックを追加


    • ダメなら入力画面へ戻す



登録、更新をまとめたのでurl.pyからupdateを削除する


todos/urls.py

urlpatterns = [

path('', views.index, name='index'),
path('new/', views.new, name='new'),
path('add/', views.add, name='add'),
path('<int:todo_id>/', views.detail, name='detail'),
path('delete/<int:todo_id>/', views.delete, name='delete'),
]

もちろんtemplateも修正する


todos/templates/todos/new.html

<html>

<head></head>
<body>
<form action="/todos/add/" method="post">
{% csrf_token %}
{% for field in form.visible_fields %}
{{ field.label }}: <input type="text" name="{{ field.name }}" value="{{ field.value }}"/>
{{ field.errors }}
<br>
{% endfor %}
<input type="hidden" name="todo_id" value="{{ todo_id }}"/>
<input type="submit" value="登録"/>
</form>
</body>
</html>



  • form.visible_fieldshidden以外のfieldのことをさす(今回はhiddenないけど)



    • hiddenは、form.hidden_fieldsを利用する


    • {{ form }}でinputタグを書かずにformを作ってくれる


    • form.as_tableならテーブルで、form.as_ulならリスト形式、form.as_pなら箇条書きで出力


      • 個人的(最終的)には、cssとかも当てたいのでhtmlタグは自分で書きたいと思う





おまけ

シーケンス取得をModel側で実施してみた

save()を継承して、todo_idのチェックを行い、空だったらシーケンスから採番する


todos/models.py

from django import forms

from django.db import models
from django.forms import ModelForm
from sequences import get_next_value

class Todo(models.Model):
todo_id = models.CharField(primary_key=True, max_length=5, default="")
title = models.CharField(max_length=50, default="")
main_text = models.CharField(max_length=300, default="")
update_date = models.DateTimeField('date published', auto_now=True)

def save(self, *args, **kwargs):
if self.todo_id == "":
self.todo_id = get_next_value('todo_seq')
super().save(*args, **kwargs)

class TodoForm(ModelForm):
class Meta:
model = Todo
fields = ['todo_id', 'title', 'main_text', 'update_date']
exclude = ['todo_id', 'update_date']




  • Todosave()を実装



    • todo_id == ""ならシーケンスから採番する
      ※やってみたけど微妙だな。って思いました。views.pyでハンドリングする方がいいと思います
      ※役に立つかもしれないので、残しままにします




おわりに

まだまだ勉強中

「自分のこうしたい!」が全く反映できずにモヤモヤ中

でも、やりたいことは別なので次に進もうと思います。