LoginSignup
1
2

More than 5 years have passed since last update.

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

Posted at

はじめに

やったことをまとめると以下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でハンドリングする方がいいと思います ※役に立つかもしれないので、残しままにします

おわりに

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

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

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2