class CustomUser(User):
age = models.PositiveIntegerField(blank=True)
job = models.CharField(max_length=300, blank=True)
location = models.CharField(max_length=300, blank=True)
class Meta(User.Meta):
db_table = 'customuser'
如上,CustomUser表示自定义用户,在基础字段上增加了age, job, location三个字段。如果执行python manage.py syncdb,数据库会自动建好一下6个用户直接相关的表:
CREATE TABLE auth_info
(
user_ptr_id integer NOT NULL,
age integer,
job character varying,
location character varying,
CONSTRAINT auth_info_pkey PRIMARY KEY (user_ptr_id),
CONSTRAINT auth_info_user_ptr_id_fkey FOREIGN KEY (user_ptr_id)
REFERENCES auth_user (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION DEFERRABLE INITIALLY DEFERRED,
CONSTRAINT auth_info_age_check CHECK (age >= 0)
)
WITH (
OIDS=FALSE
);
ALTER TABLE auth_info
OWNER TO postgres;
字段
user_ptr_id挺关键的,别忘了。
class UserCreateForm(UserCreationForm):
'''
创建新用户
'''
email = forms.EmailField() #邮箱
job = forms.CharField(max_length=300, required=False) #职业
age = forms.IntegerField(required=False) #年龄
location = forms.CharField(max_length=300, required=False) #工作地点
class Meta:
model = User
fields = (
"username", "email", "password1", "password2",
"job", "age", "location"
)
# 判断年龄是否为负数
def clean_age(self):
age = self.cleaned_data['age']
if age < 1:
raise forms.ValidationError("年龄不能小于1岁")
return age
# 判断该email是否已被注册
def clean_email(self):
email = self.cleaned_data["email"]
try:
User._default_manager.get(email=email)
except User.DoesNotExist:
return email
raise forms.ValidationError(
"the email already exists.Plase change one or login",
code='duplicate_email',
)
def save(self, commit=True):
user = super(UserCreateForm, self).save(commit=False)
user.job = self.cleaned_data["job"]
user.age = self.cleaned_data["age"]
user.email = self.cleaned_data["email"]
user.location = self.cleaned_data["location"]
if commit:
user.save()
return user
不一一解释了,代码自身应该能将自身解释的很清楚了,需要注意的是,如果某个字段是非必须的,需注明:
required=False,默认的都是必须的。
上面省略了,用户名,邮箱唯一性、有效性检查的代码,这部分可自行添加。为防止页面在提交后跳转,我们使用了异步提交(ajaxSubmit, 来自jquery.form.js)
def sign_up(request):
'''
注册
'''
if request.method == "POST":
form = UserCreateForm(request.POST)
if form.is_valid():
usr = form.save()
else:
raise HttpInternalError()
上面的
def sign_in(request):
'''
登录
'''
params = utils.get_params(request)
redirect_to = utils.get_dict_value(params, 'next', '')
if request.method == "POST":
form = AuthenticationForm(request, data=request.POST)
if form.is_valid():
login(request, form.get_user())
rememberme = utils.get_dict_value(params, "remember-me")
if rememberme == "on":
request.session.set_expiry(7*24*3600)
else:
request.session.set_expiry(0)
return utils.dumps_json({"next":redirect_to,"username": utils.get_param(params, "username")})
raise HttpInternalError()
这里需要说明一下用户登录有效期的问题,默认有效期是
2周,但如果在代码里将session的过期设为了浏览器关闭即过期,那么以后用户再登录如果不进行如何设置的话,默认的就是浏览器关闭即过期了,所以这里当用户选择了“自动登录”,还需要显式的设置一次过期时间。
class UserProfileForm(UserChangeForm):
'''
个人信息修改
'''
class Meta:
model = User
fields = ('username','email','password','age', 'job', 'location')
password = ReadOnlyPasswordHashField()
def __init__(self, *args, **kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
def clean_password(self):
return self.initial["password"]
def update(request):
'''
修改个人信息
'''
if request.method == 'POST':
form = UserProfileForm(request.POST, instance=request.user.customuser)
if form.is_valid():
form.save()
if 'username' in request.REQUEST:
usr = CustomUser.objects.get(username = request.POST['username'])
return str(usr)
elif 'email' in request.REQUEST:
usr = CustomUser.objects.get(email = request.POST['email'])
return str(usr)
raise HttpInternalError()
class CaptchaForm(forms.Form):
email = forms.EmailField()
captcha = CaptchaField()
注册码模块:
urlpatterns += patterns('',
url(r'^captcha/', include('captcha.urls')),
)
EMAIL_HOST = 'smtp.issas.ac.cn' #SMTP地址
EMAIL_PORT = 25 #SMTP端口
EMAIL_HOST_USER = '[email protected]' #邮箱地址
EMAIL_HOST_PASSWORD = '******' #邮箱密码
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
def reset_password_dialog(request):
'''
重置密码对话框
'''
form = CaptchaForm()
return render_to_response("accounts/inc/password_reset_dialog.html", locals(),
context_instance=RequestContext(request))
accounts/inc/password_reset_dialog.html
如你所见,上述html代码中没有提交代码,这个对话框是ajax方式请求,提交代码在其母页面中。
后端代码:
urlpatterns += patterns('django.contrib.auth.views',
url(r'^password/reset/(?P[0-9A-Za-z]+)-(?P.+)/$',
'password_reset_confirm', {"template_name":"accounts/inc/password_reset_confirm.html"}, name="password_reset_confirm"),
url(r'^password/done/$', 'password_reset_complete', {"template_name":"accounts/inc/password_reset_complete.html"}, name="password_reset_complete")
)
views.py
def reset_password(request):
'''
重置用户密码
'''
if request.method == 'POST':
form_sn = CaptchaForm(request.POST)
if form_sn.is_valid():
human = True
else:
return "sn_error" #验证码错误
form_email = PasswordResetForm(request.POST)
email_template_name = "accounts/inc/password_reset_email.html"
if form_email.is_valid():
opts = {
'use_https': request.is_secure(),
'token_generator': default_token_generator,
'from_email': settings.DEFAULT_FROM_EMAIL,
'email_template_name': email_template_name,
'request': request,
}
#form.save(**opts)
from MapCloud.common.ThreadPool import async_execute
async_execute(form_email.save, kwds=opts)
return render_to_response("accounts/inc/password_reset_done.html", locals(),
context_instance=RequestContext(request))
raise HttpInternalError()
这部分代码是参考着django.contrib.auth.forms.PasswordResetForm来写的,是有点麻烦,主要是其中的模板参数不清楚,下面一一解释一下(强烈建议看看django/contrib/admin/templates/registration中的默认模板):
密码已重置,您现在可以返回首页重新登录!
密码重置
{% if validlink %}
{% else %}
密码重置失败,可能这个链接已经被使用过了,您可以重新申请密码重置
{% endif %}
我们向您的邮箱里发送了密码重置链接,请按链接中的指示重置密码。
如果没收到相关邮件,请确认您在上一步所填写的邮箱是否时您注册时使用的邮箱。
谢谢!
{% autoescape off %}
您收到此封邮件是因为您请求重置 {{ site_name }} 上的帐号密码.
请点击下面的链接并设置一个新的密码:
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
{% endblock %}
另:您的用户名为:{{ user.get_username }}
谢谢您对我们的支持!
{% endautoescape %}
OK,这样这部分基本上就可以使用了。