【Dajngo(日報アプリ開発)】モデルフィールドのデフォルト値を関数で設定する [default=function]

Django

(最終更新月:2021年10月)

前回の記事では、SlugFieldを追加し、「pk」ではなく「slug」で特定のページへアクセスする方法について解説しました

当記事では、

  • スラッグフィールドのデフォルト値を関数で設定する方法

について解説していきます

関連書籍

デフォルト値の設定

ランダムな文字列がデフォルト値となるよう設定していきます

まずはランダムな文字列を作り出す関数を別ファイルで定義していきます

ランダムな値を返す関数

utilsフォルダに新たなファイル「random_string.py」を作成し、必要な関数をこちらに定義していきます

utils > random_string.py

import random,string

def random_string_generator(size=20, chars=string.ascii_lowercase + string.digits):
    return ''.join(random.choice(chars) for _ in range(size))

こちらのrandom_string_generatorを使った関数にて、SlugFieldにデフォルト値を割り当てます

自動生成したスラッグをデフォルト値に設定

nippo > models.py

from utils.random_string import random_string_generator
#...他のインポートは割愛します

def slug_maker():
    repeat = True
    while repeat:
        new_slug = random_string_generator()
        counter = NippoModel.objects.filter(slug=new_slug).count()
        if counter == 0:
            repeat = False
    return new_slug

#<<モデルマネジャー、クエリセットは割愛>>

class NippoModel(models.Model):
    #...,
    slug = models.SlugField(max_length=20, unique=True, default=slug_maker)
    #....,

ファイル内で、スラッグ生成のための独立した関数「slug_maker」を定義します

slug_makerでは使用済みの値を返さぬようにチェックするコードを加えています

SlugField内の「blank=True, null=True」を改め、

default=関数名

とし、デフォルト値を設定します

また、「unique=True」とすることで、同じ値が存在しないようにバリデーションをかけています

マイグレーションを経て、エラーが出なければデフォルト値の設定は完了です

テストの実行で確認しよう!

スラッグに変更を加えたことで、既存の関数で訂正すべき箇所もありますが、↓の通り、きちんとスラッグが保存されているかをテストする関数を追加しましょう

def test_slug_saved(self):
    nippo_obj = NippoModel.objects.first()
    self.assertTrue(nippo_obj.slug)

訂正する箇所もあり、test.py全体はこんな感じになりました

from django.test import TestCase
from django.urls import reverse
from nippo.models import NippoModel

from django.contrib.auth import get_user_model
from allauth.account.models import EmailAddress

User = get_user_model()

class NippoTestCase(TestCase):
    def __init__(self, *args, **kwargs):
        self.email = "test@itc.tokyo"
        self.password = "somepassword"
        self.title = "testTitle1"
        self.content = "testContent1"
        self.slug = "some-slug-for-test"
        super().__init__(*args, **kwargs)

    #初期設定
    def setUp(self, *args, **kwargs):
        user_obj = User(email=self.email)
        user_obj.set_password(self.password)
        user_obj.save()
        email_obj = EmailAddress(user=user_obj, email=self.email, verified=True)
        email_obj.save()
        #public = False ( Default )
        nippo_obj = NippoModel(user=user_obj, title=self.title, content=self.content)
        nippo_obj.save()
    

    #日報の作成
    def test_saved_single_object(self):
        qs_counter = NippoModel.objects.count()
        self.assertEqual(qs_counter, 1)

    def test_user_saved(self):
        counter = User.objects.count()
        self.assertEqual(counter, 1)
        email_counter = EmailAddress.objects.count()
        self.assertEqual(email_counter, 1)
    
    def test_email_verified(self):
        email_obj = EmailAddress.objects.first()
        self.assertEqual(True, email_obj.verified)

    def test_login(self):
        data = {"email": self.email, "password": self.password}
        response = self.client.post("/accounts/login/", data)
        self.assertEqual(response.status_code, 200)

    def test_signup(self):
        new_data = {"email": "test2@itc.tokyo", "password1": "somepassword2", "password2": "somepassword2"}
        redirect_to = reverse("account_email_verification_sent")
        response = self.client.post("/accounts/signup/", new_data)
        #Email Confirmationへredirectされているか?
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response.url, redirect_to)
        #ユーザーが作られているか?
        self.assertEqual(User.objects.count(), 2)

    #DetailView Not Queryのときに404を返すか?
    def test_response_404(self):
        detail_url = reverse('nippo-detail', kwargs={"slug": "none-of-the-word"})
        detail_response = self.client.get(detail_url)
        self.assertEqual(detail_response.status_code, 404)

#Anonymousユーザーはアクセスできない
    def test_access_to_createview(self):
        url = reverse("nippo-create")
        redirect_to = reverse("account_login")
        response = self.client.get(url)
        self.assertRedirects(response, f"{redirect_to}?next=/create/")

#ログインユーザーが日報を作成する
    def test_create_on_createView(self):
        user_obj = User.objects.first()
        url = reverse('nippo-create')
        create_data = {"user": user_obj, "title": "title_from_test", "content": "content_from_test", "slug":"some-random-slug"}
        self.client.login(email=self.email, password=self.password)
        response = self.client.post(url, create_data)
        redirect_to = reverse("nippo-list")
        qs_counter2 = NippoModel.objects.count()
        self.assertRedirects(response, redirect_to)
        self.assertEqual(qs_counter2, 2)

    def test_update_with_another_user(self):
        another_user = User(email="test2@itc.tokyo")
        another_user.set_password("somepassword2")
        another_user.save()
        self.client.login(email=another_user.email, password=another_user.password)
        redirect_to = reverse("account_login")
        nippo_obj = NippoModel.objects.first()
        url = reverse('nippo-update', kwargs={"slug": nippo_obj.slug})
        response = self.client.get(url)
        self.assertRedirects(response, f"{redirect_to}?next=/update/{nippo_obj.slug}/")

    def test_update_with_own_user(self):
        self.client.login(email=self.email, password=self.password)
        nippo_obj = NippoModel.objects.first()
        url = reverse('nippo-update', kwargs={"slug": nippo_obj.slug})
        response = self.client.get(url)
        self.assertEqual(response.status_code, 200)

    def test_delete_with_another_user(self):
        another_user = User(email="test2@itc.tokyo")
        another_user.set_password("somepassword2")
        another_user.save()
        self.client.login(email=another_user.email, password=another_user.password)
        redirect_to = reverse("account_login")
        nippo_obj = NippoModel.objects.first()
        url = reverse('nippo-delete', kwargs={"slug": nippo_obj.slug})
        response = self.client.post(url, {})
        self.assertRedirects(response, f"{redirect_to}?next=/delete/{nippo_obj.slug}/")

    def test_delete_with_own_user(self):
        redirect_to = reverse("nippo-list")
        self.client.login(email=self.email, password=self.password)
        nippo_obj = NippoModel.objects.first()
        url = reverse('nippo-delete', kwargs={"slug": nippo_obj.slug})
        response = self.client.post(url, {})
        self.assertRedirects(response, redirect_to)

    def test_listview_with_anonymous(self):
        url = reverse("nippo-list")
        response = self.client.get(url)
        object_list = response.context_data["object_list"]
        self.assertEqual(len(object_list), 0)

    def test_listview_with_own_user(self):
        url = reverse("nippo-list")
        self.client.login(email=self.email, password=self.password)
        response = self.client.get(url)
        object_list = response.context_data["object_list"]
        self.assertEqual(len(object_list), 1)

#日報を作成する
    def make_nippo(self, user, public):
        nippo_obj = NippoModel(user=user, public=public)
        nippo_obj.title = f"title {nippo_obj.pk}"
        nippo_obj.content = f"content {nippo_obj.pk}"
        nippo_obj.save()
        return nippo_obj

#サーチフォームテスト
    def test_search_queryset(self):
        user_obj = User.objects.get(email=self.email)
        test_user = User(email="test2@itc.tokyo")
        test_user.set_password("somepassword2")
        test_user.save()
        obj1 = self.make_nippo(user=user_obj, public=True)
        obj2 = self.make_nippo(user=user_obj, public=False)
        obj3 = self.make_nippo(user=test_user, public=True)
        obj4 = self.make_nippo(user=test_user, public=False)
        counter = NippoModel.objects.count()
        self.assertEqual(counter, 5)
        self.client.login(email=self.email, password=self.password)
        response = self.client.get(reverse("nippo-list"))
        self.assertEqual(len(response.context_data["object_list"]), 4)
        url = reverse("nippo-list") + "?search=1"
        response = self.client.get(url)
        self.assertEqual(len(response.context_data["object_list"]), 1)
        url = reverse("nippo-list") + "?search=content"
        response = self.client.get(url)
        self.assertEqual(len(response.context_data["object_list"]), 4)

#SlugFieldについて
    def test_slug_saved(self):
        nippo_obj = NippoModel.objects.first()
        self.assertTrue(nippo_obj.slug)

まとめ

前回のSlugFieldを作成・設定から続き、デフォルト値を関数で設定する方法について解説しました

関数では、

  • returnで設定したい値を返すこと
  • default=関数名と「 () 」は除いて記述すること

を覚えて置きましょう

次回は、作成日を記録する為の「DateField」、日付をカレンダー入力する「datepicker」について解説していきます

当記事では、日報アプリ開発シリーズの続編として、コードの詳細などに関しての説明は省いております

「詳しく知りたい!」という方は、こちら↓より日報アプリ開発についての記事集をご覧ください

当ブログは、「プログラミング初心者が一からWebアプリを作り、ネットで公開するまで」を解説しているサイトです。

日報アプリを一から開発し、ウェブに公開するまではこちらにまとめています

また、公開したウェブアプリはこちら(https://nippo.itc-app.site)でご覧いただけます(公開後もアップデート中)

 

その他、各分野別に

  1. Pythonについて
  2. HTML・CSSについて
  3. Djangoフレームワークについて
  4. Webサーバーについて
  5. 実際に公開をする方法

を記載したページも用意しています

 

ご自身の目的に合わせて、お好きな箇所からご覧ください

404 NOT FOUND | ITCブログ
今の自分にチャレンジする
タイトルとURLをコピーしました