Django之博客系统:用户注册和Profile
前面章节介绍了用户的登录,退出。这一章将介绍用户的注册。首先需要创建一个表单来让用户填写用户名,密码等信息。创建UserRegistrationFrom表单。并指定model为User类
from django.contrib.auth.models import User
class UserRegistrationForm(forms.ModelForm):
password=forms.CharField(label=u"密码")
password2=forms.CharField(label=u"重复输入密码")
class Meta:
model=User
fields=('username','first_name','email')
def clean_password2(self):
cd=self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError(u'密码不匹配')
return cd['password2']
在这里定义了clean_password2用于校验两次输入的密码是否不相同,如果不同则抛出异常。这个函数在调用user_form.is_valid()的时候将会被触发调用
接下来在views.py中添加处理函数:
def register(request):
if request.method == "POST":
user_form=UserRegistrationForm(request.POST)
if user_form.is_valid():
new_user=user_form.save(commit=False)
new_user.set_password(user_form.cleaned_data['password']) #使用set_password方法将用户的密码进行加密后再进行保存操作
new_user.save()
return render(request,'blog/register_done.html',{'new_user':new_user})
else:
user_form=UserRegistrationForm()
return render(request,'blog/register.html',{'user_form':user_form})
当用户注册成功,返回register_done页面,初始访问的时候返回register页面
在blog应用中的url中添加路由配置:
url(r'^register/$',views.register,name='register'),
在templates/blog下新添加register.html和register_done.html
register.html代码如下
{% extends "blog/base.html" %}
{% block title %}创建新用户{% endblock %}
{% block content %}
<h1>创建新用户</h1>
<p>请填写如下表单:</p>
<form action="." method="post">
{{ user_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Create my account"></p>
</form>
{% endblock %}
register_done.html代码如下:
{% extends "blog/base.html" %}
{% block title %}欢迎{% endblock %}
{% block content %}
<h1>欢迎 {{ new_user.first_name }}!</h1>
<p>已经成功创建用户 <a href="{% url "login" %}">请登录</a>.</p>
{% endblock %}
在url中输入http://127.0.0.1:8000/account/register/进入注册界面
注册完成后提示注册成功,并附上了登录的链接
扩展用户模型:
到目前为止,我们所有的用户都是通过User类内置的元素来编辑的。但是User模型只有固定的一些字段。如果我们想扩展User的字段就需要创建一个profile模型来包含我们想增加的字段。并且和django中的User做一对一的关联
首先在models.py中添加如下代码:user一对一关联用户和profile。另外还定义了date_of_birth和photo字段,如果想要上传图片需要安装Pillow来管理图片。
class Profile(models.Model):
user=models.OneToOneField(settings.AUTH_USER_MODEL)
#通过OneToOneField将profile和User类关联起来
date_of_birth=models.DateTimeField(blank=True,null=True)
photo=models.ImageField(upload_to='users/%/Y/%/m/%/d',blank=True)
def __str__(self):
return 'Profile for user{}'.format(self.user.username)
class Profile_admin(admin.ModelAdmin):
list_display = ['user','date_of_birth','photo']
在setting.py中添加图片的存放路径:这里设置存放在/media路径。MEDIA_URL 是管理用户上传的多媒体文件的主URL,MEDIA_ROOT是这些文件在本地保存的路径
MEDIA_URL='/media/'
MEDIA_ROOT=os.path.join(BASE_DIR,'media/')
在主urls.py中添加如下代码:
from django.conf import settings
from django.conf.urls.static import static
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
下面开始进行数据库迁移:
zhf@zhf-maple:~/py_prj/mysite$ python manage.py makemigrations
Migrations for 'blog':
blog/migrations/0005_profile.py
- Create model Profile
zhf@zhf-maple:~/py_prj/mysite$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, blog, contenttypes, sessions, taggit
Running migrations:
Applying blog.0005_profile... OK
在admin.py中进行注册:
admin.site.register(Profile,Profile_admin)
如果我们需要用户在线编辑他们的profile,需要定义模型,在forms.py中添加如下代码:
class UserEditForm(forms.ModelForm):
class Meta:
model=User
fields=("first_name","last_name","email")
class ProfileEditForm(forms.ModelForm):
class Meta:
model=Profile
fields=('date_of_birth','photo')
这两个表单(forms)的功能:
- UserEditForm:允许用户编辑它们的first name,last name, e-mail 这些储存在User模型(model)中的内置字段。
- ProfileEditForm:允许用户编辑我们存储在定制的Profile模型(model)中的额外数据。用户可以编辑他们的生日数据以及为他们的profile上传一张照片。
在views,py的register函数中的new_user.save()后添加
profile=Profile.objects.create(user=new_user)。这给每个用户添加了一个profile对象。注意,在这段代码添加前的用户是没有这个profile对象的,只有这个profile对象添加之后的用户才有这个对象。
下面添加edit函数来编辑profile
@login_required(login_url='/account/login')
def edit(request):
if request.method == 'POST':
user_form=UserEditForm(instance=request.user,data=request.POST)
profile_form=ProfileEditForm(instance=request.user.profile,data=request.POST,files=request.FILES)
if user_form.is_valid() and profile_form.is_valid():
user_form.save()
profile_form.save()
else:
user_form=UserEditForm(instance=request.user)
profile_form=ProfileEditForm(instance=request.user.profile)
return render(request,'blog/edit.html',{'user_form':user_form,'profile_form':profile_form})
我们使用login_required装饰器decorator是因为用户编辑他们的profile必须是认证通过的状态。在这个例子中,我们使用两个模型(model)表单(forms):UserEditForm用来存储数据到内置的User模型(model)中,ProfileEditForm用来存储额外的profile数据。为了验证提交的数据,通过is_valid()方法是否都返回True我们来检查每个表单(forms)。在这个例子中,我们保存两个表单(form)来更新数据库中对应的对象。
最后在blog应用中的urls.py中添加路由:
url(r'^edit/$', views.edit, name='edit'),
登录帐号后输入http://127.0.0.1:8000/account/edit/进入编辑
进入admin界面也可以看到添加的profile对象