安装mysql驱动
pip install mysql-python
模型分层
opreation是下面几个模型的操作层
将多个app放入一个路径
- 新建apps文件夹,将各app拉入,注意不要勾选下面两项
- 由于路径问题,operation会进行报错,如下图:
- 右键apps设置为资源路径,取消IDE报错。
- 在setting里面设置取消命令行运行报错
#将apps引入到资源路径中
sys.path.insert(0,os.path.join(BASE_DIR,'apps'))
django 后台汉化&时区调整
LANGUAGE_CODE = 'zh-hans'#后台汉化
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False#设置为False即采用本地时间非国际时间
错误解决1
- 提示setting neither ….
通过转到venv / bin / activate并添加行来自动执行该过程: set DJANGO_SETTINGS_MODULE=mysite.settings到代码的底部。
错误解决2
Exception Value:
(1452, 'Cannot add or update a child row: a foreign key constraint fails (`mooconline`.`django_admin_log`, CONSTRAINT `django_admin_log_user_id_52fdd58701c5f563_fk_auth_user_id` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`))')
修改,增加
'default': {
...
'OPTIONS': {
"init_command": "SET foreign_key_checks = 0;",
},
},
- 有时候错误莫名其妙,多谷歌,多试试,最好弄明白原理,但也不必浪费太多时间,还没到那阶段。
xadmin 后台
- 安装
#先进入虚拟后台
(py2.7djangoj1.9) bogon:moocOnline eric$ pip install xadmin
- 在settings中注册xadmin和crispy-forms依赖包
'xadmin',
'crispy_forms',#注意换成下滑线
- 变更后台管理路径
import xadmin
urlpatterns = [
url(r'^xadmin/', include(xadmin.site.urls)),
]
- 注释掉admin.py 中的admin后台管理
- 同步xadmin的表
python manage.py makemigrations
python manage.py migrate
- 注册model
在model下创建adminx.py文件,用来注册model
通过源码安装
- 上github下载源码,解压将xadmin文件夹放到项目中存放第三方源码的路径extra_apps下,并将extra_apps包mark成资源包。
- 在settings里面设置
sys.path.insert(0, os.path.join(BASE_DIR, 'extra_apps'))
错误解决3
AppRegistryNotReady: Models aren't loaded yet
将manage.py 改成下面,再以具体是缺什么模块装什么模块。
import django
import os
import sys
from django.core.wsgi import get_wsgi_application
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "moocOnline.settings")
django.setup()
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
application = get_wsgi_application()
错误解决4
(1146, "Table 'mooconline.xadmin_log' doesn't exist")
- 这是因为使用源码安装xadmin后新的包有自己表需要创建,所以在同步一次数据库即可。
格式化输出
'{0}---{1}'.format(self.code,self.email)
定制显示列
- 在管理器中设置
class EmailVerifyRecordAdmin(object):#注意这个继承
list_display = ['code','email','send_type','send_time']
增加搜索功能
class EmailVerifyRecordAdmin(object):#注意这个继承
list_display = ['code','email','send_type','send_time']
search_fields = ['code','email','send_type']
增加过滤功能
list_filterv= ['code','email','send_type','send_time']
错误解决5
- 上传图片报错
is located outside of the base path component
- 路径前多了个斜杠
upload_to='image/%Y/%m'
关于路径前的斜杠
(无)表示当前目录
(/)表示该目录为根目录的一个子目录
(./)表示此文件当前所在环境
(../)表示此文件所在环境的上一层环境
xadmin主题
class BaseSetting(object):
enable_themes = True# 开启主题
use_bootswatch = True
class GlobalSettings(object):
site_title = '智创无限管理后台'
site_footer = '智创无限有限责任公司'
menu_style = 'accordion'#菜单折叠
- 在apps.py中修改app的中文名
在app里添加apps.py
#coding:utf8
__author__ = 'eric'
__date__ = '2017/8/23 21:27'
from django.apps import AppConfig
class OperationConfig(AppConfig):
name = 'courses'
verbose_name = '课程'
在app的init.py里面增加下面代码
default_app_config = 'courses.apps.OperationConfig'
使用template来配置路径
from django.views.generic import TemplateView
urlpatterns = [
url(r'^$',TemplateView.as_view(template_name='index.html'),name='index'),
]
静态文件及模板路径
- 模板路径配置,settings中
TEMPLATES = [
{
...
'DIRS': [os.path.join(BASE_DIR,'templates')],
...
]
- 静态文件路径配置
STATIC_URL = '/static/'
STATICFILES_DIRS =(os.path.join(BASE_DIR, 'static'),)
注意要将静态文件中的相对路径改成static路径
403访问禁止
Django 为了防止csrf攻击,要求form表单提交要有token 验证,所以要在form后面加如下代码
{% csrf_token %}
</form>
解决邮箱验证
- 因为Django自带验证是基于用户名称的没有通过邮箱验证功能,所以我们需要重写auth验证类来达到邮箱验证功能
class CustomBackend(ModelBackend):
def authenticate(self, username=None, password=None, **kwargs):
try:
#并级查询
user = UserProfile.objects.get(Q(username=username)|Q(email=username))
if user.check_password(password): # 检查密码函数
return user
except Exception as e:
return None
需要在setting中注册重写的类
#在这里注册重写的类
AUTHENTICATION_BACKENDS =(
'users.views.CustomBackend',
)
基于类的登录判断优化
- 之前是在views.py中创建登录验证函数,如下:
def userlogin(request):
if request.method == 'POST':
user_name = request.POST.get('username', '')
pass_word = request.POST.get('password', '')
# 通过authemticate方法验证用户提交的数据是否正确
user = authenticate(username=user_name, password=pass_word)
if user is not None:
login(request, user)
return render(request, 'index.html',locals())
else:
return render(request, 'login.html', {'msg':'用户名或密码错误'})
elif request.method == 'GET':
return render(request, 'login.html', {})
- 比较麻烦,现进行基于类的继承方式来进行优化如下:
from django.views.generic.base import View
class LoginView(View):
def get(self,request):
return render(request, 'login.html', {})
def post(self,request):
user_name = request.POST.get('username', '')
pass_word = request.POST.get('password', '')
# 通过authemticate方法验证用户提交的数据是否正确
user = authenticate(username=user_name, password=pass_word)
if user is not None:
login(request, user)
return render(request, 'index.html', locals())
else:
return render(request, 'login.html', {'msg': '用户名或密码错误'})
在urls.py中调用如下:
url(r'^login/$',LoginView.as_view(),name='login'),
用django的form验证登录
- 有时候提交的数据需要进行简单的验证,django 的form提供了该功能
创建forms.py文件
# coding:utf8
from django import forms
class LoginForm(forms.Form):
# 这里面的字段必须和前端form表单里面的字段一致,否则起不到验证效果
username = forms.CharField(required=True)#必填
password = forms.CharField(min_length=3)#最小长度为3
在views.py进行应用
#基于类的书写
from django.views.generic.base import View
class LoginView(View):
def get(self,request):
return render(request, 'login.html', {})
def post(self,request):
# 实例化一个form验证
loginform = LoginForm(request.POST) # 这里需要一个字典参数,request.POST刚好返回一个字典
if loginform.is_valid(): # 判断是否合法
user_name = request.POST.get('username', '')
pass_word = request.POST.get('password', '')
# 通过authemticate方法验证用户提交的数据是否正确
user = authenticate(username=user_name, password=pass_word)
if user is not None:
login(request, user)
return render(request, 'index.html', locals())
else:
return render(request, 'login.html', {'msg': '用户名或密码错误!'})
else:
return render(request, 'login.html', {'loginform': loginform }) # 如果输入格式不对,返回提示信息。
login.html
<form action="/login/" method="post" autocomplete="off">
<input type='hidden' name='csrfmiddlewaretoken' value='mymQDzHWl2REXIfPMg2mJaLqDfaS1sD5'/>
<!--- 如果出现usermane的错误的提示-->
<div class="form-group marb20 {% if loginform.errors.username %} errorput {% endif %}">
<label>用 户 名</label>
<input name="username" id="account_l" type="text" placeholder="手机号/邮箱"/>
</div>
{% if loginform.errors.username %}
<div class="error btns login-form-tips" id="jsLoginTips">{{ loginform.errors.username }}</div>
{% endif %}
<div class="form-group marb8 {% if loginform.errors.password %} errorput {% endif %}">
<label>密 码</label>
<input name="password" id="password_l" type="password" placeholder="请输入您的密码"/>
</div>
{% if loginform.errors.password %}
<div class="error btns login-form-tips" id="jsLoginTips">{{ loginform.errors.password}}</div>
{% endif %}
<div class="error btns login-form-tips" id="jsLoginTips">{{ msg }}</div>
<div class="auto-box marb38">
<a class="fr" href="forgetpwd.html">忘记密码?</a>
</div>
<input class="btn btn-green" id="jsLoginBtn" type="submit" value="立即登录 > "/>
<input type='hidden' name='csrfmiddlewaretoken' value='5I2SlleZJOMUX9QbwYLUIAOshdrdpRcy'/>
{% csrf_token %}
</form>
-前端判断用户状态
{% if request.user.is_authenticated %}
session
#settings中
'django.contrib.sessions',#该应用自动处理request请求与post,处理sessionID以及post的时候自动发送sessionID
HTML 中的路径问题
- 普通路径表示
路径参考
/static/css # 从顶层目录开始
./ #从本层目录开始
../ #从上层目录开始
- 使用django 的相对路径标签
优点是当静态文件目录放生变动时不用进入前端代码修改
<html>
{% load staticfiles %}#在html中首先加载静态文件标签,前后要有一个空格
<head>
# 表示后面的路径在setting 中设置静态文件的目录下
src="{% static 'images/dig_close.png' %} "# 相对路径前面不加/
#后面修改静态文件的目录名称时候只修修改settings.py中的设置,如下:
STATIC_URL = '/static/'
STATICFILES_DIRS =(os.path.join(BASE_DIR, 'static'),)
# 表示从url中获取相对路径
href="{% url 'register' %}"
django 验证库
pip install django-simple-captcha==0.4.6
# 在forms.py中创建类
from captcha.fields import CaptchaField
class RegisterForm(forms.Form):
email = forms.EmailField(required=True)
password = forms.CharField(min_length=3) # 最小长度为3
captcha = CaptchaField()
# 配置路径
url(r'^captcha/', include('captcha.urls')),
# 在处理函数中实例化类
class RegisterView(View):
def post(self, request):
register_form = RegisterForm(request.POST)
if register_form.is_valid():#如果验证通过
#保存用户及密码
#获取邮箱账号,以及将密码加密
user_name = request.POST.get('email', '')
pass_word = request.POST.get('password', '')
user_profile = UserProfile()
user_profile.email = user_name
user_profile.username = user_name
user_profile.password = make_password(pass_word)# 对密码进行加密保存,因为django 只存密文
user_profile.save()
else:
return render(request,'register.html',{'register':register_form})
return render(request, 'register.html')
def get(self, request):
register_form = RegisterForm()
return render(request, 'register.html', {'register_form': register_form})
#修改HTML
<label>验 证 码</label>
{{register_form.captcha }}
- 上面jinja里面实际生成了相应的HTML代码,查看页面源代码如下:
- 简要总结:
- forms.py里面的处理类字段必须和HTML里面的一直,否则验证不会通过
- 出问题多debug仔细看提示
匹配网址参数
- 路由设置
url(r'^active/(?P<active_code>.*)/$', ActiveUserView.as_view(), name='user_active'),
#对应的get函数
class ActiveUserView(View):
def get(self,request,active_code):#注意这里的active_code要和路由里面的一致
前端相应代码
# 错误红框提示
<div class="form-group marb20 {% if loginform.errors.username %} errorput {% endif %}">
#每个from表单都会要求防止csrf
{% csrf_token %}
</form>
配置media文件路径
- 在根目录下创建名为media的文件夹
- settings.py 设置
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
- 引入处理库
TEMPLATES = [
{
...
'OPTIONS': {
'context_processors': [
...
'django.core.context_processors.media',
],
...
]
- 设置路由
url(r'^media/(?P<path>.*)$', serve, {"document_root":MEDIA_ROOT}),
- 在HTML中使用
pure-pagination分页库使用
<div class="pageturn">
<ul>
{% if courses.has_previous %}
<li class="long"><a href="?{{ courses.previous_page_number.querystring }}">上一页</a></li>
{% endif %}
{% for page in courses.pages %}
{% if page %}
{% ifequal page courses.number %}
<li class="active"><a class="page">{{ page }}</a></li>
{% else %}
<li><a href="?{{ page.querystring }}" class="page">{{ page }}</a></li>
{% endifequal %}
{% endif %}
{% endfor %}
{% if courses.has_next %}
<li class="long"><a href="?{{ courses.next_page_number.querystring }}">下一页</a></li>
{% endif %}
</ul>
</div>
- views.py
#coding:utf8
from pure_pagination import Paginator, PageNotAnInteger
class CoursesView(View):
def get(self,request):
#获取当前页数,如果为分页则设置页数
all_courses = Course.objects.all()
try:
page = request.GET.get('page', 1)
except PageNotAnInteger:
page = 1
p = Paginator(all_courses, 6, request=request)
courses = p.page(page)
course_count = all_courses.count()
return render(request,'course-list.html',locals())
# 注意数据迭代也要改一下
{% for course in courses.object_list %}
django temple 过滤器
- 更多请谷歌,这里记录用到的
int|stringformat:"i" #将int类型的数据转换成字符型
django 排序
hot_orgs = CourseOrg.objects.all().order_by("-click_nums")[:5]
数据库同步错误
- 出现解决办法
python manage migrate --fake
- 防患于未然
course_org = models.ForeignKey(CourseOrg,verbose_name=u'课程所属机构',null=True,blank=True)#这样做是保证没该字段之前添加的数据允许为空,或者增加default=''属性。
Django ModelForm
- 相比之前的ModelForm更为简单并自带save
#之前form
class ModifyForm(forms.Form):
password1 = forms.CharField(min_length=3) # 最小长度为3
password2 = forms.CharField(min_length=3) # 最小长度为3
#
class ModifyPwdView(View):#由于上面的路径设置必须要
def post(self,request):
modify_form = ModifyForm(request.POST)
if modify_form.is_valid():
if request.POST.get('password1','') != request.POST.get('password2',''):
return render(request,'password_reset.html',{'msg':'两次输入密码不一致'})
email = request.POST.get('email','')
users = UserProfile.objects.filter(email=email)
for user in users:
user.password= make_password(request.POST.get('password1',''))
user.save()
return render(request,'index.html')
else:
return render(request, 'login.html')
#
继承forms.Form后还要对字段进行验证,在View里面还要save,但继承forms.ModelForm就简单多了,如下:
from operation.models import UserAsk
class UserAskForm(forms.ModelForm):
class Meta:
model = UserAsk # 指定forms对应的model
fields=['name','mobile','course_name'] #指定form要验证的字段
#
class AddUserAskView(View):
def post(self,request):
userask_form = UserAskForm(request.POST)
if userask_form.is_valid():
user_ask = userask_form.save(commit=True)#这样就保存到了数据库,和之前比不用先实例化在保存。
pass
- django ModelForm 还可以进行自定义的格式筛选
class UserAskForm(forms.ModelForm):
class Meta:
model = UserAsk # 指定forms对应的model
fields=['name','mobile','course_name'] #指定form要验证的字段
#验证手机号码有效性,下面函数定义为固定格式
def clean_mobile(self):
moblie = self.cleaned_data['mobile']#获取填入的moblie
#创建正则表达
REGEX_MOBILE = "^1[358]\d{9}|^147\d{8}$|^176\d{8}$"
p = re.compile(REGEX_MOBILE)
if p.match(moblie):#如果匹配成功
return moblie
else:
#下面的错误返回格式也是固定的
raise forms.ValidationError(u"手机号码非法",code='mobile_invalid')
django ajax
- ajax流程以收藏为例
点击页面收藏按钮-->ajax通过class或id绑定监听-->ajax从当前路径下调用函数-->后台函数处理并返回json-->ajax依据json做出相应显示
----------
#通过id监听
按键标签
<div class="btns">
<div class="btn colectgroupbtn" id="jsLeftBtn">
收藏
</div>
<div class="buy btn"><a style="color: white" href="course-video.html">开始学习</a></div>
</div>
ajax函数
function add_fav(current_elem, fav_id, fav_type){
$.ajax({
cache: false,
type: "POST",
url:"/org/add_fav/",
data:{'fav_id':fav_id, 'fav_type':fav_type},
async: true,
beforeSend:function(xhr, settings){
xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
},
success: function(data) {
if(data.status == 'fail'){
if(data.msg == '用户未登录'){
window.location.href="login.html";
}else{
alert(data.msg)
}
}else if(data.status == 'success'){
current_elem.text(data.msg)
}
},
});
}
ajax监听,此处为通过id监听,通过class监听为$('.jsLeftBtn').on...
$('#jsLeftBtn').on('click', function(){
add_fav($(this), {{ course.id }}, 1);
});
后台处理路径及函数
urlpatterns = [
...
url(r'^add_fav/',AddFavView.as_view(),name='add_fav' ),
]
class AddFavView(View):
"""
用户收藏以及取消收藏
"""
def post(self, request):
fav_id = request.POST.get('fav_id', 0)
fav_type = request.POST.get('fav_type', 0)
user_id = request.user.id
# 首先判断用户是否登录
if not request.user.is_authenticated:
# 如果没有登录则返回没有登录信息
return HttpResponse('{"status":"fail","msg":"用户未登录"}', content_type='application/json')
else:
# 如果用户登录了则判断之前有没有收藏过,如果重复收藏即意味着要取消收藏
from operation.models import UserFavorite
user_fav = UserFavorite.objects.filter(user_id=user_id, fav_id=int(fav_id), fav_type=int(fav_type))
if user_fav: # 如果之前收藏过则取消收藏
user_fav.delete()
# 返回取消收藏相关信息
return HttpResponse('{"status":"fail","msg":"已取消收藏"}', content_type='application/json')
else: # 用户之前为收藏过,则进行收藏
# 创建对象,实例化,保存极为收藏
if int(fav_id) > 0 and int(fav_type) > 0:
userFav = UserFavorite()
userFav.fav_type = fav_type
userFav.fav_id = fav_id
userFav.user_id = user_id
userFav.save()
return HttpResponse('{"status":"success","msg":"收藏成功"}', content_type='application/json')
else:
return HttpResponse('{"status":"fail","msg":"收藏失败"}', content_type='application/json')
html中传递路径参数加空格
<a href="{% url org:org_home org.id %}">
Django 判断用户是否登录
- 全局搜索
edit->find->find in path 快捷键 shift + command + F
{% if request.user.is_authenticated %}#此处的user是浏览器中的匿名对象,用来判断登录状态
错误解决6
使用分页的时候总提示函数参数不对,要求一个整型变量,却给了一个request,仔细对照了之前写的分页,并且查看了函数的源码,发现代码以及逻辑没有问题,弄了半天发现出错的这块源码函数就没有要求request,但之前的要求了request,发现时使用库的时候引用错了,应该使用pure….这个库。
数据类型choices类型的在html中显示的方法
degree = models.CharField(max_length=50,choices=(('cj', u'初级'), ('zj', u'中级'), ('gj', u'高级')))
----------
<span class="fl">难度:<i class="key">{{ course.get_degree_display }}</i></span>
Django QuerySet 外键反取
- 关于Django的外键我有话要说
发现django的外键一般是自己的上级,从来不存下级的外键(这好像有点势力)
但当要取出下级的数据时候就要用反取,具体如下:(取出课程下面的章节)
# models里面设置
并且上级在反调的时候也不用导入下级的包
class CourseOrg(models.Model):
name = models.CharField(max_length=20, verbose_name=u'组织名称')
click_nums = models.IntegerField(default=0, verbose_name=u'点击数量')
fav_nums = models.IntegerField(default=0, verbose_name=u'收藏数量')
image = models.ImageField(upload_to='org/%Y/%m', verbose_name=u'封面图片', max_length=200)
address = models.CharField(max_length=150, verbose_name=u'机构详细地址')
city = models.ForeignKey(CityDict, verbose_name=u'机构所在城市')
desc = models.CharField(max_length=300, verbose_name=u'描述')
add_time = models.DateField(default=datetime.now, verbose_name=u'添加时间')
category = models.CharField(max_length=20, default='pxjg', choices=(('pxjg', '培训机构'), ('gx', '高校'), ('gr', '个人'),),
verbose_name='机构类别')
students = models.IntegerField(default=0, verbose_name='学习人数')
course_nums = models.IntegerField(default=0, verbose_name='课程数量')
class Meta:
verbose_name = u'机构表'
verbose_name_plural = verbose_name
# 返回机构下面所有的课程
def course_org_course_num(self):
return self.course_set.all().count()
#获取机构下面的教师数
def course_org_teacher_num(self):
return self.teacher_set.all().count()
def __unicode__(self):
return self.name
# 在html 中通过机构实例可以调用
{{ course_org.course_org_course_num}}
{{ course_org.course_org_teacher_num}}
重写View验证登录状态
新建一个用于判断登录状态的类,然后让处理类继承
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
class LoginRequestedMixin(object):#mixin一般表示基础的view类
@method_decorator(login_required(login_url='/login/'))
def dispatch(self,request,*args,**kwargs):
return super(LoginRequestedMixin,self).dispatch(request,*args,**kwargs)
# 处理函数继承基础view就会自动验证是否登录,未登录就跳转到指定页面
class CommentView(LoginRequestedMixin,View):
def get(self,request,course_name):
course = Course.objects.get(name=course_name)
return render(request,'course-comment.html',locals())
使用video.js 打造视频播放页面
- 首先下载video.js将相应的文件放到与HTML中路径对应的文件里面
{% block custom_css %}
...
<link rel="stylesheet" type="text/css" href=" {% static 'css/video-js.min.css' %} "/>
<style>
.video-js .vjs-big-play-button{
letf:50%;
right:50%;
}
</style>
{% endblock %}
<script src ="{% static 'js/video.min.js' %}" type ="text/javascript"></script>
{% block custom_js %}
- 播放页面对应设置
# 此处视频是放到七牛云上生成的外链
<div style="width:1200px;height:6750px;margin: auto ">
<video id="example_video_1" class="video-js vjs-default-skin" width="1200" poster="http://video-js.zencoder.com/oceans-clip.png" data-setup="{}" controls preload="none">
<source src="{{ video.link }}" type="video/mp4">
</video>
</div>
<div id="main">
html中的切片
# 切路径后7位判断是否与后面字符串相等
{% request.path|slice:'7' =='/source' %}
顶部搜索框实现
- 包含实现对搜索按键监听的js文件
<script src="/static/js/deco-common.js" type="text/javascript"></script>
----------
//顶部搜索栏搜索方法
function search_click(){
var type = $('#jsSelectOption').attr('data-value'),
keywords = $('#search_keywords').val(),
request_url = '';
if(keywords == ""){
return
}
if(type == "course"){
request_url = "/course/list?keywords="+keywords
}else if(type == "teacher"){
request_url = "/org/teachers/list?keywords="+keywords
}else if(type == "org"){
request_url = "/org/list?keywords="+keywords
}
window.location.href = request_url
}
# 通过id监听
$('#jsSearchBtn').on('click',function(){
search_click()
});
# 然后在对应的处理View里面进行处理
if request.GET.get('keywords'):
keywords = request.GET.get('keywords')
teachers = Teacher.objects.filter(Q(name__icontains=keywords)|Q(work_company__icontains=keywords))
修改密码
- 分析
开始想用继承自forms.FormModel进行验证,结果发现继承自forms.Form的fields里面的参数必须和数据库以及form表单里面的三者一致,出现了一些麻烦,后改为继承forms.Model的表单验证。
class UserAskForm(forms.ModelForm):
class Meta:
model = UserAsk # 指定forms对应的model
fields=['name','mobile','course_name']
#指定form要验证的字段,数据库、此处、form表单三处要一致
#验证手机号码有效性,下面函数定义为固定格式
def clean_mobile(self):
moblie = self.cleaned_data['mobile']#获取填入的moblie
#创建正则表达
REGEX_MOBILE = "^1[358]\d{9}|^147\d{8}$|^176\d{8}$"
p = re.compile(REGEX_MOBILE)
if p.match(moblie):#如果匹配成功
return moblie
else:
#下面的错误返回格式也是固定的
raise forms.ValidationError(u"手机号码非法",code='mobile_invalid')
- 保存密码的时候要使用函数进行加密保存啊,不能直接保存,要不然自己都不知道自己改了个啥,—_—!
from django.contrib.auth.backends import ModelBackend
...
if password1==password2:
user.password = make_password(password1)
- 在js文件中要手动配置路径
HttpResponseRedirect()
- 不仅可以避免硬编码而且可以避免缓存不能用问题
from django.core.urlresolvers import reverse
from django.http import HttpResponse, HttpResponseRedirect
----------
class LogoutView(View):
def get(self, request):
users = UserProfile.objects.filter(username=request.user.username)
for user in users:
logout(request)
return HttpResponseRedirect(reverse('index'))
# reverse是依据给定的视图返回对应路径,避免硬编码。
配置404/500页面
- 在urls.py中配置页面路径
#全局404、500页面配置
handler404 = 'users.views.page_not_found'
handler500 = 'users.views.http_error'
- 设置处理函数
# 404 全局处理函数
from django.shortcuts import render_to_response
def page_not_found(request):
# 创建响应对象
response = render_to_response('404.html',{})
response.status_code=404
return response
# 500 全局处理函数
def http_error(request):
response = render_to_response('500.html',{})
response.status_code=500
return response
- 此时如果不关闭debug模式,仍然访问不到配置好的页面,所以此时要关闭debug模式,但,关闭后回到是Django不会自动的通过之前配置的静态文件路径去找静态文件,这些事情将交给web服务器,所以此处为了体验效果,手动设置静态文件路径
DEBUG = False
# 用*表示匹配所有IP访问
ALLOWED_HOSTS = ['*']
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
STATIC_ROOT = os.path.join(BASE_DIR,'static')
xadmin 配置
- 下载最新的font Awesmoe 解压后替换项目中的对应文件
- 到font Awesmoe网站查取想要图标对应的编码
- 到对应的位置替换
- 顶级目录图标替换
class UserAdmin(object):
change_user_password_template = None
list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
list_filter = ('is_staff', 'is_superuser', 'is_active')
search_fields = ('username', 'first_name', 'last_name', 'email')
ordering = ('username',)
style_fields = {'user_permissions': 'm2m_transfer'}
# model_icon = 'fa fa-user'
model_icon = 'fa fa-user-o'#重点看这块
relfield_style = 'fk-ajax'
- 子目录图标修改
到对应app的adminx.py下面进行替换
- 顶级目录图标替换
- 字段选项设置
- 设置字段默认排列顺序、读写性、显示。
class BannerAdmin(object):
list_display = ['title', 'image', 'url', 'index', 'add_time']
search_fields = ['title', 'image', 'url']
list_filter = ['title', 'image', 'url', 'index', 'add_time']
ordering = ['-add_time'] #按时间倒序排列
readonly_fields= ['title']#只读不能改
exculde=['url']#不显示哪个字段
- 设置字段默认排列顺序、读写性、显示。