読者です 読者をやめる 読者になる 読者になる

Djangoroidの奮闘記

python,django,angularJS1~三十路過ぎたプログラマーの奮闘記

django備忘録2 Model Form など

Model Form

  • forms.py を作成する
from django import forms #formsをimport
from .models import SignUp #modelsから、classをimport

class SignUpForm(forms.ModelForm): #forms.ModelForm で、modelformを継承したformclassが作成可能
  class Meta:
  model = SignUp
  fields = ['email']

*ちなみに、admin.pyにも設定可能。

admin.py

class SignUpAdmin(admin.ModelAdmin):
  list_display = ["__str__", "timestamp", "updated"]
  form = SignUpForm

で、admin formにもimport可能 ※これは、formの動作を確認する時に有効!

Form Validation

  • clean_emailメソッドと、 form.cleaned_data を利用して、validationを行う

forms.py

class SignUpForm(forms.ModelForm):
  class Meta:
  model = SignUp
  fields = ['full_name','email']

  def clean_email(self):
  print (self.cleaned_data) #cleaned_data
  return "abc@ddd.com"# これは、abc@ddd.com をemailの箇所に入力するということになる。

は、保存の時に, clean_email の関数が実行される、いつか何でかわからん。 →これは、view.py→template/formタグ→action''の場合は、自分に送信→views.pyにもう一度戻ってくる?

  • さらにちょっと色々項目を増やせる。 forms.py
class SignUpForm(forms.ModelForm):
  class Meta:
  model = SignUp
  fields = ['full_name','email']

  #clean_emailメソッドで、formに入力されたemailのvalidationをする。
  def clean_email(self):
  email = self.cleaned_data.get('email')
  email_base, provider = email.split("@")
  domain, extension = provider.split('.')
  if not domain == 'USC':
      raise forms.ValidationError("USC emailを入力してください。")
  if not extension == "edu":
      raise forms.ValidationError("有効なメールアドレスを入力してください!")
  return email

  def clean_full_name(self):
  full_name = self.cleaned_data.get('full_name')
  if not "sky" in full_name:
      raise forms.ValidationError("skyが含まれていません。")
  return full_name

最終的にこういう感じで、validationが可能。 def clean_フィールド名(self): ってのが、validationの時の関数みたい

View & Template Context

  • views にcontextを設定 →templates に渡す

views.py

def home(request):
  title = "My Title %s" %(request.user)
  context = {
  "template_title":title,
  }
  return render(request, "home.html",context)

home.html
<h1>{{ template_title }}</h1>

とかそんな感じ!

  • さらに一歩進んで、、、簡単なユーザー認証で、表示するページを変える 必要なのは、is_authenticated()

例えば、こんな風に、表示を変えられる

from django.shortcuts import render

# Create your views here.
def home(request):
  title = "ようこそ!ユーザー登録をお願いします!"
  if request.user.is_authenticated():
  title = "My Title %s" %(request.user)
  context = {
  "template_title":title,
  }
  return render(request, "home.html",context)

・view templates の関係のちょっとしたtips contextに設定しなくても、user, request.userは、templateに反映可能。 それが可能なのは、settings.py に入っている、TEMPLATESの、 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', あたりらしい

{{ user }} {{ request.user }}

で、反映されるのを確認。

  • Form in View views.pyの中に、forms.py のformを入れる→contextで、templatesに反映

views.py

form = SignUpForm()
context = {
    "form":form
}
って感じで、contextに渡す。
homes.html
<form method='' action=''>
{{ form }}

<input type='submit' value='Sign Up'/>

</form>

って感じで、form タグの中に、設定する。

  • 登録などのform のmethodは、基本的にPOSTを使う。 検索の時とかは、GET

  • ただ、methodが、POSTの場合は、{% csrf_token %} が必要。

<form method='POST' action=''>{% csrf_token %}
{{ form }}

こんな感じで、1行いれるだけ!

  • views.pyで、

views.py

  if request.method == "POST":
  print (request.POST)

と入れると、request.POSTの内容が表示される。 つまり、フォームの流れとしては、、、

urls.py → views.py(form)→templates(home.html)で、home.htmlのフォームに入力→action="" の先に送付。つまり、home.htmlの元のデータ(views.py(form.py))に行く!views.pyは、request.POSTを持った、formsを、forms.save()で、modelsに保存するという感じの流れなのか?

  • だから、

views.py

form = SignUpForm(request.POST or None)

をセットして、POSTの内容を渡す

  • save() メソッドはオプション commit キーワード引数を持っています。こ の引数には True または False を指定します。 save() を commit=False で呼び出すと、データベースに保存する前のモデルオブジェクト を返します。
  if form.is_valid():
      instance = form.save(commit=False)
  if instance.full_name == None:
      instance.full_name = "Justin"
  instance.save()
  print (instance.email)
  print (instance.timestamp)

この例だと、instance = form.save(commit=False) 未保存の状態 instance.save()で保存というstepを踏むということ。

  • POSTした後は、再度viewに戻ってきて、処理を行うため、送信後のtemplatesに渡すcontextも微妙に変えて渡すことができる。

例えば、以下のとおりです! context で、新しい変数をtemplatesに渡してる viewは、modelよりも小さくが基本みたいだから、modelにこの辺は組み込んだ方がいいのかもしれん。

views.py

from django.shortcuts import render

from .forms import SignUpForm
# Create your views here.
def home(request):
  title = "ようこそ!ユーザー登録をお願いします!"
  if request.user.is_authenticated():
  title = "My Title %s" %(request.user)
  form = SignUpForm(request.POST or None)
  context = {
  "title":title,
  "form":form,
  }

  if form.is_valid():
  # form.save()
  #print (request.POST['email']) --"これはやっちゃダメ。POST全部が上書きされてしまう。"
  instance = form.save(commit=False)

  full_name = form.cleaned_data.get("full_name")
  if not full_name:
      full_name = "New Full Name"
      instance.full_name = full_name
      # instance = form.save(commit=False)
      # if not instance.full_name:
      # instance.full_name = "Justin"
  instance.save()
  context = {
  "title": "Thank you",
  }

  return render(request, "home.html",context)