# 一 、xadmin安装,注意xadmin不支持python3
#1、pip install xadmin
#2、在setting中将xadmin、与其依赖crispy_forms的注册到app中(这里要注意,下载xadmin时候会默认将crispy-forms一起下载,但是在注册app时候,要用下划线,而不是分隔符)
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'xadmin',
'crispy_forms',
]
#3、修改django项目中urls.py中
from django.conf.urls import url,include
import xadmin
from users.views import ActiveUserView
urlpatterns = [
url(r'^admin/', xadmin.site.urls,name='admin'),
url(r'^captcha/', include('captcha.urls'),name ='captcha' ),
url(r'^active/(?P<active_code>.*)/$', ActiveUserView.as_view(),), # (?P)固定写法,P代表Parameter,active_code:参数字段,".*",代表后面所有字符都赋值给active_code
]
#4、直接访问后台127.0.0.1/admin 就可以了
#5、使用xadmin替换pip安装的xadmin,去github上下载最新的xadmin,然后解压出来,拷贝里面的xadmin文件夹到项目下
#6、在项目/下创建一个文件夹extra_apps专门用来存放以后项目用到的第三方包,将xadmin拖放进去
#7、mark一下extra_apps,让pycharm把此目录当成搜索目录,在setings.py中添加sys.path.insert(1,os.path.join(BASE_DIR,'extra_apps')),告诉python把此目录当成搜索目录
#8、pip uninstall xadmin 卸载之前通过pip安装的xadmin,直接访问127.0.0.1/admin ,此时运行的就是github上下载下来的源码的xadmin
#二、项目中使用xadmin
#1、在app下新建adminx.py
#2、注册自己的model类到xadmin
import xadmin
from .models import EmailVerifyRecord
class EmailVerifyRecordAdmin(object): #定义admin
list_display = ['code', 'email', 'send_type', 'send_time'] # 后台显示哪些列
search_fields = ['code', 'email', 'send_type'] # 搜索,搜索中不能添加时间比较麻烦,放在过滤里面
list_filter = ['code', 'email', 'send_type', 'send_time'] # 过滤
xadmin.site.register(EmailVerifyRecord,EmailVerifyRecordAdmin) #将EmailVerifyRecord的model注册到EmailVerifyRecordAdmin,
#这时候重启服务,访问后台就会出现此模块
#3、注册主题,随意找一个adminx写入
from xadmin import views
class BaseSetting(object):
enable_themes = True #主题
use_bootswatch = True
xadmin.site.register(views.BaseAdminView,BaseSetting)
#4、修改左上角系统标题、与下方footer名称,菜单折叠,随意找一个adminx写入
from xadmin import views
class GlobalSetting(object):
site_title = '在线学习管理系统' #左上角系统标题
site_footer = '在线学习网站' #下方footer名称
menu_style = 'accordion' #菜单折叠
xadmin.site.register(views.CommAdminView,GlobalSetting)
#5、修改菜单名字为中文,拿user模块来举例
#5.1 在user模块下的apps.py中,UsersConfig中添加属性:
verbose_name = u'用户操作'
#5.2 然后,在user模块下的__init__.py中写入
default_app_config = 'users.apps.UsersConfig'
#6、xadmin常用操作
class BannerAdmin(object):
...
model_icon = 'fa fa-group' #具体去百度找 font awesome,只需要替换group
ordering = ['-click_num'] # 显示排序
readonly_fields = ['click_num', 'fav_nums'] # 后台不可编辑
exclude = ['add_time'] # 详情不显示add_time 此字段与readonly_fields互斥
relfield_style = 'fk-ajax' # 下拉筛选改为搜索
#保证项目使用最新版本的font awesome解压找到font、css,找到项目下\xadmin\static\xadmin\vendor\font-awesome,替换css与css就是最新版本的
#7、一般外键关联数据在xadmin只能通过在列表选择对应外键数据跳转再去编辑,但是想在详情编辑中,可以直接编辑(只能一层嵌套):
class LessonInline(object):
model = Lesson
extra = 0
class CourseAdmin(object):
list_display = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_num','add_time']
search_fields = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_num']
list_filter = ['name','desc','detail','degree','learn_times','students','fav_nums','image','click_num','add_time']
model_icon = 'fa fa-book' #图标
ordering = ['-click_num'] #显示排序
readonly_fields = ['click_num','fav_nums']#后台不可编辑
exclude= ['add_time'] #详情不显示add_time 此字段与readonly_fields互斥
relfield_style='fk-ajax' #下拉筛选改为搜索
inlines = [LessonInline]
#8、一张表在后台注册成两个管理器,以课程为例,课程一张表,后台分为轮播课程、非轮播课程
#models代码如下:
class Course(models.Model):
name = models.CharField(verbose_name=u'课程名',max_length=50)
is_banner = models.BooleanField(verbose_name=u'是否轮播',default=False) #是否为轮播课程
add_time = models.DateTimeField(verbose_name=u'添加时间',default=datetime.now)
class Meta:
verbose_name = u'课程'
verbose_name_plural = verbose_name
def __unicode__(self):
return self.name
class BannerCourse(Course):
'''banner课程'''
class Meta:
verbose_name = u'轮播课程'
verbose_name_plural = verbose_name
proxy = True #不会生成表
#adminx代码如下:
class CourseAdmin(object):
list_display = ['name','is_banner','add_time']
search_fields = ['name','is_banner']
list_filter = ['name','is_banner', 'add_time']
def queryset(self):
qs = super(CourseAdmin, self).queryset()
qs = qs.filter(is_banner=False)
return qs
class BannerCourseAdmin(object):
list_display = ['name', 'is_banner', 'add_time']
search_fields = ['name', 'is_banner']
list_filter = ['name', 'is_banner', 'add_time']
def queryset(self):
qs = super(BannerCourseAdmin, self).queryset()
qs = qs.filter(is_banner=True)
return qs
xadmin.site.register(BannerCourse, BannerCourseAdmin)
xadmin.site.register(Course, CourseAdmin)
#9、将model中的方法获取的值,在后台列表字段显示
#model中代码如下:
class Course(models.Model):
name = models.CharField(verbose_name=u'课程名',max_length=50)
class Meta:
verbose_name = u'课程'
verbose_name_plural = verbose_name
def get_zj_nums(self):
'''获取该课程章节'''
return self.lesson_set.all().count()
get_zj_nums.short_description = u'章节数' #指定后台显示列表字段名
def __unicode__(self):
return self.name
#admix中代码如下:
class CourseAdmin(object):
list_display = ['name','get_zj_nums']
search_fields = ['name']
list_filter = ['name']
#10 在model中定义方法,返回html,在后台以html代码形式显示:
#model中代码:
class Course(models.Model):
name = models.CharField(verbose_name=u'课程名',max_length=50)
class Meta:
verbose_name = u'课程'
verbose_name_plural = verbose_name
def go_to(self):
from django.utils.safestring import mark_safe
return '<a href="http://www.baidu.com">百度</a>' #如果不使用mark_safe,在后台显示的就是一段文本了
go_to.short_description = u'跳转' # 指定后台显示列表字段名
def __unicode__(self):
return self.name
# admix中代码如下:
class CourseAdmin(object):
list_display = ['name', 'go_to']
search_fields = ['name']
list_filter = ['name']
#11、xadmin插件开发,集成百度uditor编辑器,
#11.1 github上搜素django ueditor,找到zhangfisher/DjangoUeditor,下载并解压,
#11.2 切换命令行到解压后的目录执行python setup.py install(如果是虚拟环境开发,进入虚拟环境在进入对应目录)
#11.3 将 DjangoUeditor 放入到settings.py中的INSTALLED_APPS
#11.4 配置urls.py如下:
urlpatterns = [
...
url(r'^ueditor/', include('DjangoUeditor.urls')),
]
#11.5 比如给课程加富文本编辑器,去Course的model中引入代码:
from DjangoUeditor.models import UEditorField
detail = UEditorField(u'课程详情', width=600, height=300, imagePath="course/ueditor/", filePath="course/ueditor/", upload_settings={"imageMaxSize": 1204000},default='')
#imagePath:图片上传路径,跟平时写的model中的路径是一样的
#filePath:富文本中文件的路径,跟平时写的model中的路径是一样的
#11.6 给xadmin写插件集成ueditor,在xadmin/plugin下新建ueditor.py(名字随意.py),代码如下:
import xadmin
from xadmin.views import BaseAdminPlugin,CreateAdminView,UpdateAdminView
from DjangoUeditor.models import UEditorField
from DjangoUeditor.widgets import UEditorWidget
from django.conf import settings
class XadminUEditorWidget(UEditorWidget):
def __init__(self,**kwargs):
self.ueditor_options = kwargs
self.Media.js = None
super(XadminUEditorWidget,self).__init__(kwargs)
class UeditorPlugin(BaseAdminPlugin):
def get_field_style(self,attrs,db_field,style,**kwargs):
if style == 'ueditor': #这个字段与adminx中的style_fields = {'detail':'ueditor'} 字段对应
if isinstance(db_field,UEditorField):
widget = db_field.formfield().widget
param = {}
param.update(widget.ueditor_settings)
param.update(widget.attrs)
return {'widget':XadminUEditorWidget(**param)}
return attrs
def block_extrahead(self,context,nodes):
js = '<script type="text/javascript" src="%s"></script>' % (settings.STATIC_URL + "ueditor/ueditor.config.js")
js += '<script type="text/javascript" src="%s"></script>' % (settings.STATIC_URL + "ueditor/ueditor.all.min.js")
nodes.append(js)
xadmin.site.register_plugin(UeditorPlugin,UpdateAdminView)
xadmin.site.register_plugin(UeditorPlugin,CreateAdminView)
#11.7 在课程的adminx中CourseAdmin加入代码如下:
class CourseAdmin(object):
....
style_fields = {'detail':'ueditor'}
#11.8 如果上传图片csrf_token出错,那就把github上下载下来的源码解压出的文件夹DjangoUeditor复制,替换掉开发环境下的site-packages/DjangoUeditor
#因为通过python setup.py install安装的有问题,我下载的是这样,还有一个是他的路由用的是旧版的,如果是新版的django,url改了不再是(),而是[],
#这样就需要修改DjangoUeditor/urls.py:
#源码:
# urlpatterns = patterns('',
# url(r'^controller/$',get_ueditor_controller)
# )
#修改后:
urlpatterns = [
url(r'^controller/$', get_ueditor_controller)
]
#11.9 前端展示,全是转义后的html,关闭django模板转义:
{% autoescape off%}
{{ course.detail }}
{% endautoescape %}
#12 excel的插件使用:待研究
#三、使用static文件夹,放入css、js、图片等静态资源
#1、在根目录创建static文件夹
#2、在static下创建css、js、img、images等
#3、在settings中添加静态资源文件夹路径支持,内容如下:
STATIC_URL = '/static/'
STATICFILES_DIRS=(
os.path.join(BASE_DIR,'static'),#【注】:这里一定注意,后面那个"," ,元组只有一项必须要加
)
#四、处理直接访问静态html文件
#1、在urls中引入
from django.views.generic import TemplateView
#2、在urlpatterns中添加路由支持
url('^$', TemplateView.as_view(template_name='index.html'),name='index') #template_name只需要写名字就可以了
url('^login/$', TemplateView.as_view(template_name='login.html'),name='login') #template_name只需要写名字就可以了
#这样django会直接访问静态页面,不走views中django代码
#五、用户登陆
#1 、指定字段登陆
from django.shortcuts import render
from django.contrib.auth import authenticate,login
#自定义包
def user_login(request):
if request.method == 'POST':
user_name = request.POST.get('username')
pass_word = request.POST.get('password')
user = authenticate(username = user_name,password = pass_word)
if user is not None:
login(request,user)
return render(request,'index.html')
else:
return render(request)
return render(request,'login.html',{})
#2、username、或者email等任何一个字段作为账号登陆
#首先在user_login所在的views.py中定义class
from django.contrib.auth.backends import ModelBackend
from .models import UserProfile
#自定义登陆验证
class CustomBackend(ModelBackend):
def authenticate(self, username=None, password=None, **kwargs):
try:
user = UserProfile.objects.get(username = username)
if user.check_password(password): #将外界传进来的password加密后验证
return user
else:
return None
except Exception as e:
return None
#然后要在settings.py中添加
AUTHENTICATION_BACKENDS = ('users.views.CustomBackend',) #默认验证authenticate使用的是ModelBackend,这样通过重写后,就执行我们自己方法了,","不要忘记
#django查询数据库过滤时候使用“或”
user = UserProfile.objects.get(Q(username=account) | Q(mobile=account)) #查询username或者mobile为username的用户
#页面上判断登陆成功:
request.user.is_authenticated
#六、基于类完成views的书写
#1、修改views.py
from django.shortcuts import render
from django.contrib.auth import authenticate,login
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from django.views.generic.base import View
#自定义包
from .models import UserProfile
class LoginView(View):
def get(self,request):#对应get方法,如果想接受PUT、HEADER、DELETE等可以查看View中声明的
return render(request,'login.html',{})
def post(self,request):#对应post方法,如果想接受PUT、HEADER、DELETE等可以查看View中声明的
user_name = request.POST.get('username')
pass_word = request.POST.get('password')
user = authenticate(username=user_name, password=pass_word)
if user is not None:
login(request, user)
return render(request, 'index.html')
else:
return render(request, 'login.html', {'err_msg': '用户名或密码错误'})
#2、修改urls.py中的urlpatterns
url(r'^login/$',LoginView.as_view(),name='login'),
#七、使用form
#1、在app下创建forms.py,写入下面内容创建form
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(required=True,min_length=5,max_length=20)
password = forms.CharField(required=True,min_length=5,max_length=20)
#2、views中
#django内部包
from django.shortcuts import render
from django.contrib.auth import authenticate,login
from django.contrib.auth.backends import ModelBackend
from django.db.models import Q
from django.views.generic.base import View
#自定义包
from .models import UserProfile
from .forms import LoginForm
#自定义登陆验证
class CustomBackend(ModelBackend):
def authenticate(self, username=None, password=None, **kwargs):
try:
user = UserProfile.objects.get(Q(username = username) | Q(mobile=username))
if user.check_password(password): #将外界传进来的password加密后验证
return user
else:
return None
except Exception as e:
return None
class LoginView(View):
def get(self,request):#对应get方法
return render(request,'login.html',{})
def post(self,request):#对应post方法
login_form = LoginForm(request.POST)
if login_form.is_valid():
user_name = request.POST.get('username')
pass_word = request.POST.get('password')
user = authenticate(username=user_name, password=pass_word)
if user is not None:
login(request, user)
return render(request, 'index.html')
else:
return render(request, 'login.html', {'err_msg': '用户名或密码错误'})
else:
print(login_form.errors)
return render(request,'login.html',{'login_form':login_form})
#template中
#在class中添加出错样式
{% if login_form.errors.username %}errorput{% endif %}
#显示错误信息
{ % for key, error in login_form.errors.items %}
{{error}}
{ % endfor %}
{{err_msg}}
#八、url路径使用与静态文件static使用
#1、url
<a style="color:white" class="fr registerbtn" href="{% url 'register' 11 22 %}">注册</a> #11 22为参数
#2、静态资源路径:使用这种方式静态资源不在依赖settings.py中STATIC_URL = '/static/',而是依赖STATICFILES_DIRS
#,在根目录创建static,settings.py中添加
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
#在templates中的html中写入:
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'css/reset.css' %}">
<script src="{% static 'js/jquery.min.js'%}" type="text/javascript"></script>
#3、模板继承
#父级模板 base.html
{% block title %}我是父模板title{% endblock %}
#子模板
{% extends 'base.html' %}
{% block title %}我是子模板title{% endblock %}
#4、引入子模版
{% include 'page.html' %}
#5、模板规则
{{ request.user.mobile|default_if_none:'' }} #如果字段为none让其显示字符串
<li class="{% if forloop.counter|divisibleby:5 %}five{% endif %}"></li> #forloop.counter能被5整除,第5个
<div class="module1_{{ forloop.counter|add:2 }} box"></div> #forloop.counter + 2
#九、django验证码,github搜素 "django captcha",找到“mbi/django-simple-captcha”,点进去查看说明
#1、pip install django-simple-captcha==0.4.6 ,这里我用的0.4.6
#2、将captcha 加入settings.py下的install_app中
#3、 在urls.py中加入,url(r'^captcha/', include('captcha.urls')),
#4、运行makemigrations、migrate,创建验证码需要的表
#5、在forms.py中对应的业务的form类中添加注册码,比如注册需要使用验证码,那我就在注册的form中填写内容如下:
from django import forms
from captcha.fields import CaptchaField
class RegisterForm(forms.Form):
email = forms.CharField(required=True,min_length=6,max_length=20)
password = forms.CharField(required=True, min_length=6, max_length=20)
captcha = CaptchaField()
#6、在views中实例化RegisterForm传入模板html中
from .forms import RegisterForm
class RegisterView(View):
def get(self,request):
register_form = RegisterForm()
return render(request,'register.html',{'register_form':register_form})
#7、在模板html中只需要引用就可以了
{{ register_form.captcha }}
#8、后台验证
register_form = RegisterForm()
register_form.is_validate()
#9、如果验证码不正确,在form.errors中会返回,但是是英文的,自定义验证码错误信息为中文
#在form中将captcha改为如下:
captcha = CaptchaField(error_messages={'invalid':u'验证码错误'})
#十、django中给密码加密
from django.contrib.auth.hashers import make_password
make_password(password)
#十一、django发送邮件
from django.core.mail import send_mail
#在settings.py添加发送者邮箱相关信息如下:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' #email后端
EMAIL_USE_TLS = False #是否使用TLS安全传输协议
EMAIL_USE_SSL = True #是否使用SSL加密,qq企业邮箱要求使用
EMAIL_HOST = 'smtp.exmail.qq.com' #发送邮件的邮箱 的 SMTP服务器,这里用了qq企业邮箱
EMAIL_PORT = 465 #发件箱的SMTP服务器端口
EMAIL_HOST_USER = 'service@eagldasdade.com' #发送邮件的邮箱地址
EMAIL_HOST_PASSWORD = 'asdasdadasd' #发送邮件的邮箱密码
EMAIL_FROM = 'service@eagldasdade.com' #要与EMAIL_HOST_USER保持一致
#在view中
from jiudaoyou.settings import EMAIL_FROM
def send_register_email(email):
email_title = '注册激活链接'
email_body = '请点击下面的链接激活您的账号:http://127.0.0.1:8000/active/{0}'.format('1234')
send_arr = [email] #必须是个list,可以发送多个
send_status = send_mail(email_title,email_body,EMAIL_FROM,send_arr)
if send_status:
pass
#十二、扩展django系统自带的user表
#1、在model中创建UserProfile,集成AbstractUser
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserProfile(AbstractUser): #扩充系统的表user,继承了AbstractUser,会把之前系统的user表中字段都继承下来并将新添加字段添加进去 ,去setting中设置AUTH_USER_MODEL = "users.UserProfile"
nick_name = models.CharField(verbose_name=u"昵称",max_length=50,default="")
birday = models.DateField(verbose_name=u"生日",null=True,blank=True)
gender = models.CharField(verbose_name=u"性别",max_length=10,choices=(('male',u'男'),('female',u'女')),default='male')
address = models.CharField(verbose_name=u"昵称",max_length=100,default=u'')
mobile = models.CharField(verbose_name=u"手机",max_length=11,null=True,blank=True)
image = models.ImageField(verbose_name=u"头像",upload_to='media/images/photo/%Y/%m',default='media/images/photo/default.png',max_length=256)
class Meta:
verbose_name = u'用户'
verbose_name_plural = verbose_name
def __unicode__(self):
return self.username #之前表有username,
#2、在settings.py中设置代码如下
AUTH_USER_MODEL = "users.UserProfile" #注意这里没有model,app.类名,这样也默认将user注册在后台admin,不需要单独写注册
#十三、在页面上显示数据库的相对路径图片
#1、配置settings.py代码如下:
MEDIA_URL = '/media/'#页面访问路径,在页面显示时候,拼在图片字段前面的路径
MEDIA_ROOT = os.path.join(BASE_DIR,'media') #上传文件的路径,页面显示用不到,这里提一下,上传时候拼在model字段图片前面的路径
#2、在settings.py的 TEMPLATES下的OPTIONS中添加media上下文:
'django.core.context_processors.media',
#3、页面上
<img src = "{ MEDIA_URL }}{{ course_org.image }}"/> #MEDIA_URL是配置,如果不配置第2步,MEDIA_URL是取不到值得
#4、配置显示路由,在urls.py的urlpatterns中:
from django.views.static import serve
from jiudaoyou.settings import MEDIA_ROOT
urlpatterns=[
url(r'^media/(?P<path>.*)$',serve,{'document_root':MEDIA_ROOT})
]
#十四、django分页库,github搜索pure pagination,找到“jamespacileo/django-pure-pagination”
#1、pip install django-pure-pagination
#2、将pure_pagination注册到settings.py的INSTALLED_APPS 中:
INSTALLED_APPS = (
...
'pure_pagination',
)
#3、views.py中
all_orgs = CourseOrg.objects.all()
page = request.GET.get('page', 1)
p = Paginator(all_orgs, 5, request=request)
orgs = p.page(page)
return render(request,'org-list.html',{
...
'all_orgs':orgs,
})
#4、template的html上
{% for course_org in all_orgs.object_list %}
#内容
{ % endfor %}
{{ all_orgs.render }} #默认页码
#自定义页码
{% load i18n %}
<ul class ="pagelist" >
# 有上一页显示上一页
{% if all_orgs.has_previous %}
<li class ="long" > < a href="?{{ all_orgs.previous_page_number.querystring }}" > 上一页 </a> </li>
{% endif %}
{% for page in all_orgs.pages %}
{% if page %}
{% ifequal page all_orgs.number %}
# 当前页#
<li class ="active" > <a href="?{{ page.querystring }}" > {{page}} </a> </li>
{% else %}
# 非当前页
<li > <a href = "?{{ page.querystring }}" class ="page" > {{page}} </a> </li>
{% endifequal %}
{% else %}
# 没有页码不显示
<li class ="none" > <a href="" >...</a> </li>
{% endif %}
{% endfor %}
{% if all_orgs.has_next %}
# 有下一页显示下一页
<li class ="long" > <a href="?{{ all_orgs.next_page_number.querystring }}" > 下一页 </a> </li>
{% endif %}
</ul>
#十五、ModelForm :将model字段映射到form中,不需要在写一次model中的字段,save之后直接保存到数据库
#1、form中
from django import forms
from operation.models import UserAsk
class UserAskForm(forms.ModelForm):
#这里也可以像forms.Form中一样新增字段
class Meta:
model = UserAsk # 使用哪个model中的字段
fields = ['name', 'mobile', 'course_name'] # 使用model下某些字段验证
#对每一个字段进行重写验证,必须以clean开头,如下:
def clean_mobile(self):
mobile = self.cleaned_data['mobile'] #获取用户post后,传进入form的mobile
if len(mobile) == 11:
return mobile
else:
raise forms.ValidationError(u'手机号不合法',code='mobile_invalid') #必须抛出这个异常,才能捕获
def clean_name(self):
name = self.cleaned_data['name'] #获取用户post后,传进入form的name
print(name)
print(len(name))
if len(name) > 2:
return name
else:
raise forms.ValidationError(u'姓名非法',code='name_invalid') #必须抛出这个异常,才能捕获
def clean_course_name(self):
course_name = self.cleaned_data['course_name'] #获取用户post后,传进入form的course_name
print(course_name)
if len(course_name) >2:
return course_name
else:
raise forms.ValidationError(u'课程名不合法',code='course_name_invalid') #必须抛出这个异常,才能捕获
#2、views中
from django.views.generic import View
from django.shortcuts import render
from django.http import JsonResponse
#自定义内部包
from .forms import UserAskForm
class AddUserAskView(View):
def post(self,request):
userask_form = UserAskForm(request.POST)#如果不指定instance会新增,指定instance会修改:userask_form.save(commit=True,instance=request.user)
if userask_form.is_valid():
userask_form.save(commit=True)
#异步ajax返回json
return JsonResponse({'status':'success'})
else:
# 异步ajax返回json
return JsonResponse({'status':'fail','msg':userask_form.errors})
#十六、url命名空间
#1、全局urls.py中
urlpatterns = [
....
url(r'^org/', include('organization.urls',namespace='org')),
]
#2、每个应用下的urls.py中
urlpatterns = [
#list
url(r'list/$',OrgView.as_view(),name='org_list'),
]
#3、模板页面上
<a href="{% url 'org:org_list' %}"></a>
#十七、模板页面获取当前课程(course)的章节数量(lesson),由于lesson是存在course这个外键的,所以,在course中可以利用ar的set方向查,Course的model中定义如下:
class Course(models.Model):
course_org = models.ForeignKey(CourseOrg,verbose_name=u'课程机构',null=True,blank=True)
name = models.CharField(verbose_name=u'课程名',max_length=50)
desc = models.CharField(verbose_name=u'课程描述', max_length=300)
detail = models.TextField(verbose_name=u'课程详情')
degree = models.CharField(verbose_name=u'课程等级', choices=(('cj','初级'),('zj','中级'),('cg','高级')),max_length=2)
learn_times = models.IntegerField(verbose_name=u'学习时长(分钟数)',default=0)
students = models.IntegerField(verbose_name=u'学习人数', default=0)
fav_nums = models.IntegerField(verbose_name=u'收藏人数', default=0)
image = models.ImageField(verbose_name=u'封面图片', upload_to='course/%Y/%m', default='course/default.png',max_length=256)
click_num = models.IntegerField(verbose_name=u'点击数', default=0)
add_time = models.DateTimeField(verbose_name=u'添加时间',default=datetime.now)
class Meta:
verbose_name = u'课程'
verbose_name_plural = verbose_name
def get_zj_nums(self):
'''获取该课程章节'''
return self.lesson_set.all().count() #课程与章节
def get_learn_users(self):
'''学习该课程的用户'''
return self.usercourse_set.all()[:8] #课程与用户是多对多
def __unicode__(self):
return self.name
#模板html上代码如下:
章节数:{{ course.get_zj_nums }}
用户:{% for user_course in course.get_learn_users%}
用户姓名:{{user_course.user.name}}
{% endfor %}
#choice 如果是选择类型,类似性别字段为sex,不能直接在模板上{{user.sex}},要写法如下:
{{user.get_sex_display}} #此时会显示男、女
#十八、view验证登陆,未登录不让进
#1、创建一个文件mixin_utils.py,内容如下:
#python内部包
#django内部包
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
#自定义内部包
class LoginRequiredMixIn(object):
@method_decorator(login_required(login_url='/login/'))
def dispatch(self, request, *args, **kwargs):
return super(LoginRequiredMixIn, self).dispatch(request, *args, **kwargs)
#2、在view.py中继承即可:
from django.views.generic.base import View
from .models import Course,CourseResource
from operation.models import UserFavorite,CourseComments,UserCourse
class CourseCommentView(LoginRequiredMixIn,View): #这里顺序不能错
'''课程评论信息'''
def get(self, request, course_id):
vw = 'comments'
course = Course.objects.get(id=int(course_id))
all_course_resource = CourseResource.objects.filter(course=course)
all_comments = CourseComments.objects.filter(course_id=int(course_id))
return render(request, 'course-comment.html', {
'course': course,
'all_comments': all_comments,
'all_course_resource': all_course_resource,
'vw': vw
})
#如果不登录访问CourseCommentView,那就会跳转到login
#十九、上传图片
#1、方法一:
# form
from django import forms
from .models import UserProfile
class UploadImageForm(forms.ModelForm):
'''上传头像form'''
class Meta:
model = UserProfile # 使用哪个model中的字段
fields = ['image'] # 使用model下某些字段验证
#views
class UploadImageView(LoginRequiredMixIn,View):
'''用户上传头像'''
def post(self,request):
image_form = UploadImageForm(request.POST,request.FILES)
if image_form.is_valid():
request.user.image = image_form.cleaned_data['image']
request.user.save()
return render(request, 'usercenter-info.html', {
})
return render(request,'usercenter-info.html',{
})
#2、方法二,利用ModelForm直接报错# :
# form
from django import forms
from .models import UserProfile
class UploadImageForm(forms.ModelForm):
'''上传头像form'''
class Meta:
model = UserProfile # 使用哪个model中的字段
fields = ['image'] # 使用model下某些字段验证
#views中
class UploadImageView(LoginRequiredMixIn,View):
'''用户上传头像'''
def post(self,request):
image_form = UploadImageForm(request.POST,request.FILES,instance=request.user) #如果不指定,instance会新增,指定instance会修改
if image_form.is_valid():
image_form.save(commit=True)
return render(request, 'usercenter-info.html', {
})
return render(request,'usercenter-info.html',{
})
#二十、获取新插入数据的id
d = Data()
d.save()
#id :d.id
#二十一、后台重定向
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
return HttpResponseRedirect(reverse('users:user_index')) #reverse中的写法跟前台模板url后写法相同 {% url 'users:user_index' %}
#二十二、配置404、500页面
#404配置
#1、全局url配置参数,handler404,代码如下:
urlpatterns = [
......
]
#全家404页面配置
handler404 = 'users.views.page_not_found' #变量名必须是这个
handler500 = 'users.views.page_error' #变量名必须是这个
#2、在users下的views.py中添加方法如下:
#全局404错误页
def page_not_found(request):
from django.shortcuts import render_to_response
response = render_to_response('404.html',{}) #当然404页面要存在
response.status_code = 404
return response
#全局500错误页
def page_error(request):
from django.shortcuts import render_to_response
response = render_to_response('500.html',{})
response.status_code = 500
return response
#3、开启settings.py中的DEFUG为False、配置ALLOWED_HOSTS:
DEBUG = False
ALLOWED_HOSTS = ['*'] #*代表所有
#4、此时图片、css等是找不到的,因为DEBUG为False的时候,settings.py中的STATIC_URL、STATICFILES_DIRS不在生效,线上都是通过服务器(apache、nginx等)代理的,
#当DEBUG为False时候,django认为是生产环境,就自动使者两个变量失效,这时候自己配置就好了:
#settings.py中添加代码如下:
STATIC_ROOT = os.path.join(BASE_DIR,'static') #配置生产环境下静态资源路径
#urls.py中的urlpatterns中添加代码如下:
urlpatterns = [
...
url(r'^static/(?P<path>.*)$',serve,{'document_root':STATIC_ROOT})
]
django学习2
原创
©著作权归作者所有:来自51CTO博客作者wx637630f8ac60c的原创作品,请联系作者获取转载授权,否则将追究法律责任
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
django 学习笔记2
创建项目BookManager: django-ad
django 数据库 字段 -
django学习之路(2)-django的功能模块
的形式出现的,它是MVC中的C,实现了M和T的交互。
django 学习 表单 中间件 -
Django ~ 2
一 模版 一模版的组成 HTML代码+逻辑控制代码 二 逻辑控制代码的组成 1 变量(
模版 django html -
Django学习记录2-settings.py文件
Django学习记录2-settings.py文件
Django #学习记录 django 数据库 mysql