🔖 Day11 - UserChangeForm

2018 - 06 - 26
🔖 Day11 - UserChangeForm
除了password reset, password change, 當然還有修改用戶的資料。 Django更改用戶資料跟用戶註冊的原理差不多,都是使用內建的Form: django.contrib.auth.forms.UserChangeForm 但內建的UserChangeForm其實是給superuser例如admin用的,所以表單內容會比較多 - 如上圖。 為了讓用戶自行更改資料,我們可以新增一個subclass - UserAccount
1. [Set url] 先到urls.py新增urlspattern:
from <app> import views as myviews

urlspattern=[
    ...
    ...
    path('myaccount/', myviews.myaccount, name='myaccount'),
]


2. [Create view function] 新建一個views function - myaccount
from .forms import UserAccount

def myaccount(request):
    if request.method == "POST":
        form = UserAccount(request.POST, instance=request.user)
        if form.is_valid():
            form.save()
            return appindex(request)
        else:
            error = 'There is something wrong about your information.'
            form = UserAccount(instance=request.user)
            return render(request, 'registration/myaccount.html', {'form':form, 'error':error})
    else:
        form = UserAccount(instance=request.user)
        return render(request, 'registration/myaccount.html', {'form':form})

留意這裡我們除了request.POST,還加了instance=request.user 因為這一次我們希望把用戶既有的資料,預先填寫在form裡面,所以我們要強調instance。
3. [Create new form] 然後到<app>.forms開設一個class - UserAccount為UserChangeForm的subclass:
from django.contrib.auth.forms import UserChangeForm
from django.contrib.auth.models import User

class UserAccount(UserChangeForm):
    username = forms.CharField(required=True, disabled=True)
    email = forms.EmailField(required=False, help_text='You may update your email address here')
    first_name = forms.CharField(required=False, help_text='You may edit your nickname here for display', label='Nickname')
    password = forms.CharField(
        required=False, 
        help_text="You may change your password <a href='registration/password_change'>here</a>"
    )

    class Meta:
        model = User
        fields = ('username', 'first_name', 'email', 'password',)

這裡我們利用subclass UserAccount overrides UserChangeForm原本的表單。 先是把我們希望有的fields都加上自行寫help_text,required都改為False,因為我們不一定需要用戶更改了甚麼; 再把first_name的label改為Nickname, 還有把username的field argument加上disabled=True,防止用戶自行修改, 最重要就是在Meta說明哪些fields需要被顯示出來。
4. [Create template] 最後建立一張template - registration/myaccount.html
{% extends 'base.html' %}
{% block content %}

<form method="POST">
    {% csrf_token %}
    {% for field in form %}
        <label for='{{ field.name }}'>{{ field.label_tag }}</label>: 
        {% if field.name != "password" %}
            {{ field }}
        {% endif %}
        {% if field.help_text %}
            {{ field.help_text | safe }}
        {% endif %}
    {% endfor %}
    <input type='submit' value='Submit'>
</form>

{% endblock %}

留意上面,form的內容加上了一行condition。 當for loop遇到password field時,我們故意把它不顯示出來。 因為Django 的password並不是普通地儲存在database,而是用hasher等加密了。 如果不遮罩,password field的內容會顯示出貌似:pbkdf2_xxxxxxxxxxxxxxxxxxxxxxx 而且即使用戶在這頁面改密碼自行更改,Django也不會接納。 所以乾脆把password field隱藏,然後在help text加上password_change的連結。 因為helptext是一串plain text,要把step 3的連結有效顯示,該用戶點擊,就要在help_text加上safe的filter tag。 這樣就可以變成:

Comments

There is no comment yet

New Comment

Please Login to comment