Django 2.0 项目实战 (2): 查看与编辑用户个人资料,扩展Django自带后台User Admin

在我们上一篇文章中我们扩展了Django自带的User模型并实现了用户的登录与注册。在本文里,我们将会开发两个功能页面,一个允许用户登录后查看自己的个人信息,一个允许用户编辑个人资料,并在编辑成功后返回个人信息页。同时我们还将会Django的自带的UserAdmin后台进行扩展,实现对用户扩展信息的直接管理和编辑。本文代码用Django 2.0 + Python 3.X编写。


第一步 重温models.py和urls.py


模型Models设计是Django Web开发的第一步,更多信息见Django 2.0 Web开发核心技术之Models设计

# users/models.py

from django.db import models
from django.contrib.auth.models import User
# Create your models here.


class UserProfile(models.Model):

   user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')

   org = models.CharField(
       'Organization', max_length=128, blank=True)

   telephone = models.CharField(
       'Telephone', max_length=50, blank=True)

   mod_date = models.DateTimeField('Last modified', auto_now=True)

   class Meta:
       verbose_name = 'User Profile'

   
def __str__(self):
       return "{}".format(self.user.__str__())


# users/urls.py

from django.urls import re_path
from . import views

app_name = 'users'
urlpatterns = [
   re_path(r'^register/$', views.register, name='register'),
   
re_path(r'^login/$', views.login, name='login'),
   
re_path(r'^user/(?P<pk>\d+)/profile/$', views.profile, name='profile'),
   
re_path(r'^user/(?P<pk>\d+)/profile/update/$', views.profile_update, name='profile_update'),
   
re_path(r'^user/(?P<pk>\d+)/pwdchange/$', views.pwd_change, name='pwd_change'),
   
re_path(r'^logout/$', views.logout, name='logout'),


第二步 编写视图views.py


from django.shortcuts import render, get_object_or_404
from django.contrib.auth.models import User
from .models import UserProfile
from django.contrib import auth
from .forms import RegistrationForm, LoginForm, ProfileForm, PwdChangeForm
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.contrib.auth.decorators import login_required

def profile(request, pk):
   user = get_object_or_404(User, pk=pk)
   return render(request, 'users/profile.html', {'user': user})


def profile_update(request, pk):
   user = get_object_or_404(User, pk=pk)
   user_profile = get_object_or_404(UserProfile, user=user)

   if request.method == "POST":
       form = ProfileForm(request.POST)

       if form.is_valid():
           user.first_name = form.cleaned_data['first_name']
           user.last_name = form.cleaned_data['last_name']
           user.save()

           user_profile.org = form.cleaned_data['org']
           user_profile.telephone = form.cleaned_data['telephone']
           user_profile.save()

           return HttpResponseRedirect(reverse('users:profile', args=[user.id]))
   else:
       default_data = {'first_name': user.first_name, 'last_name': user.last_name,
                       
'org': user_profile.org, 'telephone': user_profile.telephone, }
       form = ProfileForm(default_data)

   return render(request, 'users/profile_update.html', {'form': form, 'user': user})


views.profile非常好理解。我们重点看下views.profile_update函数是怎么工作的:


  • 我们先从url获取user的主键pk(id), 利用get_object_or_404方法获取需要修改个人资料的用户对象user,然后再利用user获取一一对应的user_profile对象。

  • 当用户通过POST方法提交个人资料修改表单,我们先验证表单ProfileForm的数据是否有效。如果有效,我们将更新过的first_namelast_name数据存入user,再将更新过的telephoneorg数据存入user_profile。更新成功返回个人信息页。

  • 如果用户没有提交表单或不是通过POST方法提交表单,我们先获取现有数据生成default_data,利用ProfileForm显示


ProfileForm实际上是非常简单的,包含了我们允许用户修改的字段。在这个案例里,我们没允许用户修改用户名和电子邮件,所以没有加进去。

# users/forms.py
from django import forms

class ProfileForm(forms.Form):

   first_name = forms.CharField(label='First Name', max_length=50, required=False)
   last_name = forms.CharField(label='Last Name', max_length=50, required=False)
   org = forms.CharField(label='Organization', max_length=50, required=False)
   telephone = forms.CharField(label='Telephone', max_length=50, required=False)


第三步 编写template


#users/templates/users/profile.html

{% block content %}
<h2>Account Info</h2>
<ul>
   <li>
Username: {{ user.username }} </li>
   <li>
Email: {{ user.email }} </li>
</ul>
<h2>
My Profile</h2>

<ul>
   <li>
First Name: {{ user.first_name }} </li>
   <li>
Last Name: {{ user.last_name }} </li>
   <li>
Organization: {{ user.profile.org }} </li>
   <li>
Telephone: {{ user.profile.telephone }} </li>
</ul>

{% if user.is_authenticated %}
<a href="{% url 'users:profile_update' user.id %}">Edit</a>
| <a href="{% url 'users:pwd_change' user.id %}">Change Password </a>
| <a href="{% url 'users:logout' %}">Logout</a>
{% endif %}

{% endblock %}


#users/templates/users/profile_update.html


{% block content %}
<h2>Account Info</h2>
<ul>
   <li>
Username: {{ user.username }} </li>
   <li>
Email: {{ user.email }} </li>

</ul>
<h2>
Update My Profile</h2>

<div
class="form-wrapper">
  <form
method="post" action="" enctype="multipart/form-data">
     
{% csrf_token %}
     {% for field in form %}
          <div class="fieldWrapper">
       
{{ field.errors }}
       {{ field.label_tag }} {{ field }}
       {% if field.help_text %}
            <p class="help">{{ field.help_text|safe }}</p>
       
{% endif %}
          </div>
       
{% endfor %}
     <div class="button-wrapper submit">
        <input
type="submit" value="Update" />
     </div>
  </form>
</div>

<a
href="{% url 'users:logout' %}">Logout</a> |
     <a href="{% url 'users:pwd_change' user.id %}">Password change</a>

{% endblock %}


第四步 查看实战效果


下图个人资料页,并包含修改资料,改变密码和退出的链接。

下图是修改个人资料页面:

我们有没有说过,用户只有再登录后才能查看自己个人信息和编辑个人信息?要实现这个功能,我们只需在views.py相应函数前加@login_required这个装饰器,如下所示。我们会再后面专门讲解Django的装饰器。@login_required的作用是检查用户是否已登录,并在用户登录后转到用户试图请求的页面。

from django.contrib.auth.decorators import login_required


@login_required
def profile(request, pk):
   user = get_object_or_404(User, pk=pk)
   return render(request, 'users/profile.html', {'user': user})


@login_required
def profile_update(request, pk):
    .......


第五步 扩展Django自带的User Admin


Django自带的User Admin只能编辑管理基础字段如用户名和电子邮件。我们现在希望能扩展User Admin,在编辑User的同时编辑我们User Profile里的额外字段(如电话)。去实现这个功能,我们只需要按如下代码修改users/admin.py

from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from .models import UserProfile

admin.site.unregister(User)


class UserProfileInline(admin.StackedInline):
   model = UserProfile


class UserProfileAdmin(UserAdmin):
   inlines = [UserProfileInline, ]


admin.site.register(User, UserProfileAdmin)

下图是实际效果。UserAdmin后多了一栏User Profiles


本文介绍了如何利用Django 2.0展示用户资料和编辑个人资料,并扩展了Django自带的User Admin。在下文中我们将介绍密码重置和退出。欢迎关注我的微信号【Python与Django大咖之路】获取最新动态。

猜你喜欢

转载自blog.csdn.net/weixin_42134789/article/details/80250556
今日推荐