小梅の日記帳

覚書き、メモ、等々残していくつもりです。

異なるボタンによるPOSTのテストについて

tutorial/urls.py

"""tutorial URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include

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

tutorial_app/url.py

from tutorial_app.views import SampleFormView, SampleTemplateView
from django.urls import path

urlpatterns = [
  #ここで、class_Viewを用いるときには、as_viewという表現を用いる。
  path('template_index', SampleTemplateView.as_view()),
  path('sample_template', SampleFormView.as_view()),
]

models.py

from django.db import models

class Product(models.Model):
    code = models.CharField('商品番号', max_length=30, unique=True)
    name = models.CharField('商品名', max_length=100)

    def __str__(self):
      return "{0}{1}".format(self.code, self.name)

forms.py

from django import forms
from django.core import validators
from . import models

class ProductForm(forms.Form):
  name = forms.ModelChoiceField(
      models.Product.objects,
      label='商品',
      to_field_name='code'
  )

  product = forms.CharField(
      required=False,
      validators=[validators.MaxLengthValidator(10)])

  # clean_product関数
  def clean_product(self):
    product = self.cleaned_data['product']
    if len(product) > 5:
      raise forms.ValidationError("productのエラー")
    return product

  # clean関数
  def clean(self):
    clean_data = super().clean()
    return clean_data

views.py

from django.views.generic import FormView, TemplateView
from tutorial_app.forms import ProductForm
from tutorial_app.models import Product


class SampleFormView(FormView):
  form_class = ProductForm
  template_name = "tutorial_app/sample.html"
  success_url = "sample_template"

  def form_valid(self, form):
    print(form)
    return super().form_valid(form)

  def post(self, request, *args, **kwargs):
    if request.POST.get('action')=='送信1':
      print('送信1')
    if request.POST.get('action')=='送信2':
      print('送信2')

    return super().post(request, *args, **kwargs)

class SampleTemplateView(TemplateView):
  template_name = "index.html"

sample.html

<html>
<body>
<form action="" method="post">
  {% csrf_token %}
  {% if form.errors %}
    {% for errors in form.errors.values %}
      {% for error in errors %}
        {{ error }}<br>
      {% endfor %}
    {% endfor %}
  {% endif %}

  {% for field in form %}
    <div>
      {{ field.label_tag }}
    </div>

    <div>
      {{ field }}
    </div>
  {% endfor %}
  <button type="submit" name="action" value="送信1">送信1</button>
  <button type="submit" name="action" value="送信2">送信2</button>
</form>
</body>
</html>

このようなテストが書ける。

from django.test import TestCase
from django.test.client import Client

class SubmitTests(TestCase):
    def test_submit(self):
        c = Client(enforce_csrf_checks=False)
        response1 = c.post('/tutorial/sample_template', {'name': '1', 'product': '車', 'action': '送信2'})
        response2 = c.post('/tutorial/sample_template', {'name': '2', 'product': '馬', 'action': '送信1'})
        self.assertEqual(response1.status_code, 200)

ここで、Clientメソッドは、Client()でもデフォルトでscrfがオフになっているのでcsrfについては設定する必要はない。 異なるボタンに反応させるには、dic型でボタンの名前と値を指定すれば良いとわかった。

djangoproject.jp