LoginSignup
0
0

More than 5 years have passed since last update.

django#007_MessagesとTemplateグループ化

Posted at

前回まで

前回はUser Objectについて話しましたので、今回はメッセージの表示とか、あとtemplatesの中にあるHTMLページをまとめる方法を書きたいと思います。Registerシステムがあれば、Login成功とか、Login失敗するときは色んな表示メッセージがくるじゃないですか?

流れ

  • view.pyでLoginの動作などをしたのあとのメッセージ追加
  • templates の中でメッセージ追加
  • templatesのHTMLをグループ化する  

view.pyでLoginの動作などをしたのあとのメッセージ追加

まず messages frameworkを見てきましょう。
WebをみるときたまにPOP-UPをみたことがありますか?一回だけでClickすればなくなる。それはこのmessages frameworkの役目ですね。中にはレベルに分けておいて(info,warning,errorなど)
メッセージのレベルは以下のようになります:

DEBUG:いわゆる開発中のとき使われてるのMessageですね。
INFO:Userにお知らせする。
SUCCESS:Userがやってたアクション成功した(Loginしましたとか)
WARNING:エラーにはならなく実行しましたが、まぁ、英語通り、警告って感じですね。
ERROR:アクション実行できませんでした。なにかエラーが起こってる。
image.png
以下の例は、
User登録成功:info,success
User 登録失敗:error
User Login in成功:info

あと前回説明抜けところがありますね。

Form.is_valid()

これを使うことによってFormのデータが有効かどうかをCheckしてくれますね~もし無効なデータがあるならFalseに戻し、OKなデータならTrueが戻してくれます。

Form.cleaned_data

DjangoのForm  FrameworkはデータがOKかどうかを判断するだけではなく、データ自体も“綺麗”にしてくれます、データを一致のFormatに変更しれくれます。例えば、DateFieldをPythonのdatetime.date Objectに変更し、“'1994-07-15'”がもらってでもちゃんとPythonのObjectに変更しれくれます。多分言葉だけ説明してもちょっとわかりつらいから、Shellから説明します。

python manage.py shell

djangoからforms をImportし、新しいforms を1個作ります。
fieldsは文字200までのsubjとメールアドレスですね。

In [6]: from django import forms                                                
In [7]: class form1(forms.Form): 
   ...:     subj=forms.CharField(max_length=100) 
   ...:     email=forms.EmailField() 

データ新しく作ります。そして新しいform1 “f”が作りました。

In [8]: data1={'subj':'test1', 
   ...:        'email':'abc@example.com'}  
In [9]: f=form1(data1) 

ではまず先のis_valid()を試してみよう。
うんうん、OKですね。無効な入力が入ってません。

In [13]: f.is_valid()                                                           
Out[13]: True

次はclean()を使ってみます。
うん…あまり変わらないですね。

In [14]: f.clean()                                                              
Out[14]: {'subj': 'test1', 'email': 'abc@example.com'}

じゃ今度はもう一つのform “form2”を作ってみますね。
文字200まで、メールアドレス、更に時間の入力も入ってます。

In [27]: class form2(forms.Form): 
    ...:     subj=forms.CharField(max_length=100) 
    ...:     email=forms.EmailField() 
    ...:     date=forms.DateField() 

ではでは、また新しいデータを作り、f2が定義されました。

In [28]: data2={'subj':'subj2', 
    ...:        'email':'example@example.com', 
    ...:        'date':'1998-02-11' 
    ...:      }  

In [29]: f2=form2(data2)

まずデータが有効かどうかをCheckします。

In [30]: f2.is_valid()                                                          
Out[30]: True

clean()かけるまえのデータは、辞書ですね。

In [42]: f2.data                                                                
Out[42]: {'subj': 'subj2', 'email': 'example@example.com', 'date': '1998-02-11'}

次はclean()をかけてみます。
出力の変化見えましたか?dateの項目がdatetime.dateになりました!

In [31]: f2.clean()                                                             
Out[31]: 
{'subj': 'subj2',
 'email': 'example@example.com',
 'date': datetime.date(1998, 2, 11)}
In [33]: f2.cleaned_data.get('date')                                            
Out[33]: datetime.date(1998, 2, 11)

念のため、Typeを確認しよう。OKですね!

In [43]: d=f2.cleaned_data.get('date')                                          
In [44]: d                                                                      
Out[44]: datetime.date(1998, 2, 11)
In [45]: type(d)                                                                
Out[45]: datetime.date

最後はメールアドレスのところに変なもの入れてみよう。

In [36]: data3={'subj':'subj2',  
    ...:     ...:        'email':'examplexample.com',  
    ...:     ...:        'date':'1998-02-11' 
    ...:     ...:      }  

is_valid() はちゃんとFalse返してくれたね~

In [37]: f3=form2(data3)   
In [38]: f3.is_valid()                                                          
Out[38]: False

話が長くなりましたが、コードは以下になります:


from django.shortcuts import render,redirect
from django.http import HttpResponse
from .models import mydb
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login,logout,authenticate
from django.contrib import messages

def homepage(request):
    return render(
        request=request
        ,template_name="helloworld/home.html"
        ,context={"mydb":mydb.objects.all}
        )

def register(request):

    if request.method == "POST":
        form=UserCreationForm(request.POST)
        if form.is_valid():
            user=form.save()
            username=form.cleaned_data.get('username') #
            messages.success(request,'Your account is Created,{}.'.format(username))#
            login(request,user)
            messages.info(request,'Logged In,{}.'.format(username))#
            return redirect("helloworld:homepage")
        else:
            for msg in form.error_messages:
                print(form.error_messages[msg])
                messages.error(request,'some error,{}.',format(form.error_messages[msg]))#



    form =UserCreationForm

    return render(
        request=request
        ,template_name="helloworld/register.html"
        ,context={"form":form}

        )

templates の中でメッセージ追加

次はheader.htmlの中にmessageを入れます。
POP UP Messageの出し方はFrameworkによって違いますので、ここはw3.cssの参考例になります。views.pyからmessage をもらって、このmessageの属性によって出てくるのメッセージがわかります。

<head>
    {% load static %}
    <link rel='stylesheet' href="{% static "helloworld/w3c.css"%}">
</head>

<body>

    <div class="w3-bar w3-border w3-light-grey">
        <a href="/" class="w3-bar-item w3-button w3-mobile">Home</a>
        <a href="/register" class="w3-bar-item w3-button w3-mobile">Register</a>
        <a href="/login" class="w3-bar-item w3-button w3-mobile">login</a>
    </div>

          {% if messages %}
        {% for message in messages %}
            {% if message.tags == 'success'%}
                <div class="w3-panel w3-green">

                    <h3>success</h3>
                    <p>{{message}}</p>
                          <span onclick="this.parentElement.style.display='none'"
                    class="w3-button w3-display-topright"
                    >&times;</span>
                </div>
            {% elif message.tags == 'info'%}
                <div class="w3-panel w3-blue">

                    <h3>Info</h3>
                    <p>{{message}}}</p>
                          <span onclick="this.parentElement.style.display='none'"
                    class="w3-button w3-display-topright"
                    >&times;</span>
                </div>
            {% elif message.tags == 'warning'%}
                <div class="w3-panel w3-red">

                    <h3>Warning</h3>
                    <p>{{message}}</p>
                          <span onclick="this.parentElement.style.display='none'"
                    class="w3-button w3-display-topright"
                    >&times;</span>
                </div>
            {% elif message.tags == 'error'%}
                <div class="w3-panel w3-yellow">

                    <h3>Error</h3>
                    <p>{{message}}</p>
                          <span onclick="this.parentElement.style.display='none'"
                    class="w3-button w3-display-topright"
                    >&times;</span>
                </div>
            {% endif %}
        {% endfor %}
    {% endif %}

  {% block content%}}
  {% endblock%}

</body>

Userを登録成功したら、SuccessとInfoのメッセージがちゃんと出ましたね!
image.png
もしなにかの入力間違いだったら…
image.png

templatesのHTMLをグループ化する

こっちらは先までのheader.htmlですが、めっちゃ長いと思いませんか?
ここで”include”というものを紹介します。
ここからみると、Navバーがあって、Messageのエリアもあっての感じですね。
image.png
じゃこんな風に分けたらどうです?Layoutも綺麗になりますね。
image.png

nav.htmlを開いて、header.htmlの中にあるNavの部分をここで貼り付けます。

  <nav>
    <div class="w3-bar w3-border w3-light-grey">
        <a href="/" class="w3-bar-item w3-button w3-mobile">Home</a>
        <a href="/register" class="w3-bar-item w3-button w3-mobile">Register</a>
        <a href="/login" class="w3-bar-item w3-button w3-mobile">login</a>
    </div>
  </nav>

message.htmlを開いて、先POPUPの部分だけここに貼り付けます。

  {% if messages %}
        {% for message in messages %}
            {% if message.tags == 'success'%}
                <div class="w3-panel w3-green">

                    <h3>success</h3>
                    <p>{{message}}</p>
                          <span onclick="this.parentElement.style.display='none'"
                    class="w3-button w3-display-topright"
                    >&times;</span>
                </div>
            {% elif message.tags == 'info'%}
                <div class="w3-panel w3-blue">

                    <h3>Info</h3>
                    <p>{{message}}}</p>
                          <span onclick="this.parentElement.style.display='none'"
                    class="w3-button w3-display-topright"
                    >&times;</span>
                </div>
            {% elif message.tags == 'warning'%}
                <div class="w3-panel w3-red">

                    <h3>Warning</h3>
                    <p>{{message}}</p>
                          <span onclick="this.parentElement.style.display='none'"
                    class="w3-button w3-display-topright"
                    >&times;</span>
                </div>
            {% elif message.tags == 'error'%}
                <div class="w3-panel w3-yellow">

                    <h3>Error</h3>
                    <p>{{message}}</p>
                          <span onclick="this.parentElement.style.display='none'"
                    class="w3-button w3-display-topright"
                    >&times;</span>
                </div>
            {% endif %}
        {% endfor %}
    {% endif %}

最後に、header.htmlは先作ったのものを“include”すれば、完成です。

<head>
    {% load static %}
    <link rel='stylesheet' href="{% static "helloworld/w3c.css"%}">
</head>

  {% include "helloworld/includes/nav.html" %}
  {% include "helloworld/includes/message.html" %}

  {% block content%}}
  {% endblock%}

</body>

以上、お疲れ様です!

0
0
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
0
0