引用自:https://blog.csdn.net/weixin_42950386/article/details/83143293css
定义模型类
模型类被定义在"应用/models.py"文件中,此例中为"booktest/models.py"文件。
模型类必须继承自Model类,位于包django.db.models中。
提示:对于重要数据使用逻辑删除。html
示例演示
接下来首先以"图书-英雄"管理为例进行演示。
注意:这里咱们用的版本是django==1.8.2版本。
了解和2.1版本的区别,请百度查询,这里再也不啰嗦。python
1.下载pymysql
pip install pymysql
设置test2/__init__.py文件mysql
1 import pymysql 2 pymysql.install_as_MySQLdb()
配置数据库在settings.py中:ajax
DATABASES = { 'default': { # 'ENGINE': 'django.db.backends.sqlite3', 'ENGINE': 'django.db.backends.mysql', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 'NAME': 'test2', 'USER': 'root', 'PASSWORD': 'mysql', 'PORT': 3306, 'HOST': 'localhost', } }
2.打开booktest/models.py文件,定义模型类以下
1 from django.db import models 2 # from datetime import date 3 # Create your models here. 4 5 class BookInfo(models.Model): 6 """图书模型类""" 7 # 书名 8 btitle = models.CharField(max_length=40) 9 # 出版日期 10 bpub_date = models.DateField(default='1970-01-01') 11 # 阅读量 12 bread = models.IntegerField(default=0) 13 # 点赞量 14 bgood = models.IntegerField(default=0) 15 # 删除 16 is_del = models.BooleanField(default=False) 17 18 class HeroInfo(models.Model): 19 """英雄模型类""" 20 # 英雄名称 21 hname = models.CharField(max_length=20) 22 # 性别 23 hgender = models.BooleanField(default=False) # False为男 24 # 年龄 25 hage = models.IntegerField(default=18) 26 # 功夫 27 hcomment = models.CharField(max_length=128) 28 # 关联 29 hbook = models.ForeignKey("BookInfo") 30 # 删除 31 isDelete = models.BooleanField(default=False)
3.迁移
生成迁移文件。正则表达式
建立数据库sql
python manage.py makemigrations数据库
报错django
解决方案:ubuntu
看一下settings.py文件 apps中有没有添加 booktest
而后执行以下命令。
python manage.py makemigrations
python manage.py migrate
迁移
打开数据库的命令行,查看当前全部表以下图:
迁移
表bookinfo结构如:
默认值并不在数据库层面生效,而是在django建立对象时生效。
图书表结构
表booktest_heroinfo结构以下:
Django框架会根据关系属性生成一个关系字段,并建立外键约束。
英雄表结构
测试数据
在数据库命令行中,复制以下语句执行,向booktest_bookinfo表中插入测试数据:
insert into booktest_bookinfo(btitle,bpub_date,bread,bcomment,isDelete) values ('射雕英雄传','1980-5-1',12,34,0), ('天龙八部','1986-7-24',36,40,0), ('笑傲江湖','1995-12-24',20,80,0), ('雪山飞狐','1987-11-11',58,24,0);
再复制以下语句执行,向booktest_heroinfo表中插入测试数据:
insert into booktest_heroinfo(hname,hgender,hbook_id,hcomment,isDelete) values ('郭靖',1,1,'降龙十八掌',0), ('黄蓉',0,1,'打狗棍法',0), ('黄药师',1,1,'弹指神通',0), ('欧阳锋',1,1,'蛤蟆功',0), ('梅超风',0,1,'九阴白骨爪',0), ('乔峰',1,2,'降龙十八掌',0), ('段誉',1,2,'六脉神剑',0), ('虚竹',1,2,'天山六阳掌',0), ('王语嫣',0,2,'神仙姐姐',0), ('令狐冲',1,3,'独孤九剑',0), ('任盈盈',0,3,'弹琴',0), ('岳不群',1,3,'华山剑法',0), ('东方不败',0,3,'葵花宝典',0), ('胡斐',1,4,'胡家刀法',0), ('苗若兰',0,4,'黄衣',0), ('程灵素',0,4,'医术',0), ('袁紫衣',0,4,'六合拳',0);
4,后台管理
打开test1/settings.py文件,找到语言编码、时区的设置项,将内容改成以下
LANGUAGE_CODE = 'zh-hans' #使用中国语言 TIME_ZONE = 'Asia/Shanghai' #使用中国上海时间
admin.py文件中:
1 from django.contrib import admin 2 from booktest.models import * 3 # Register your models here. 4 5 # 关联对象 6 # 1.以块的形式嵌入 7 # 建立StackedInline类 8 class BookStackedInline(admin.StackedInline): 9 # 写多类的名字 10 model = HeroInfo 11 # 额外设置编辑子对象 默认为3个 12 extra = 2 # 额外编辑两个对象 13 14 # 2.以表格的形式嵌入 15 class BookTabularInline(admin.TabularInline): 16 # 写多类的名字 17 model = HeroInfo 18 # 额外设置编辑子对象 默认为3个 19 extra = 2 # 额外编辑两个对象 20 21 22 class BookInfoAdmin(admin.ModelAdmin): 23 # 每页显示多少条数据 24 list_per_page = 10 25 # 顶部显示的属性,设置为True在顶部显示,设置为False不在顶部显示,默认为True 26 actions_on_top = True 27 # 底部显示的属性,设置为True在底部显示,设置为False不在底部显示,默认为False 28 actions_on_bottom = True 29 # 自定义显示字段 30 # list_display = [模型字段1,模型字段2....] 模型字段能够是BookInfo里面设置的属性名 也能够是方法名 31 list_display = ['id', 'btitle', 'bpub_date', 'title'] 32 # 方法列排序 在models.py文件 33 # 右侧栏过滤器 34 list_filter=['btitle'] # 以btitle 过滤 35 # 搜索框 36 search_fields = ['btitle'] # 以btitle字段搜索 37 # 关联BookStackedInline类 块类 38 # inlines = [BookStackedInline] 39 # 关联BookTabularInline类 40 inlines = [BookTabularInline] 41 42 class HeroInfoAdmin(admin.ModelAdmin): 43 list_display = ['id', 'hname', 'hcomment'] 44 45 46 class AreaInfoAdmin(admin.ModelAdmin): 47 list_display = ['id', 'atitle', 'parent'] 48 # 编辑页 49 # 添加/修改页面字段顺序 50 # fields = ['aParent', 'atitle'] 51 # 分组显示 fieldsets=() 后面跟元祖 52 # 与fields=[] 不能同时使用 53 fieldsets = ( 54 ('基本', {'fields':['aParent']}), 55 ('高级', {'fields':['atitle']}) 56 ) 57 58 59 60 # 注册 61 admin.site.register(BookInfo, BookInfoAdmin) 62 admin.site.register(HeroInfo, HeroInfoAdmin) 63 admin.site.register(AreaInfo, AreaInfoAdmin)
models.py文件中各类方法
1 from django.db import models 2 from datetime import date 3 # Create your models here. 4 # 创建一个Manager类 5 class InfoManager(models.Manager): 6 """管理器类""" 7 # 改变查询的结果 8 def all(self): 9 # 1.调用父类结果 10 result = super().all() 11 # 改变结果 12 return result.filter(isDelete=False) 13 14 def create_book(self, btitle, bpub_date): 15 # 获取模型所在的模型类 16 model_class = self.model 17 # 建立对象 18 book = model_class() 19 book.btitle = btitle 20 book.bpub_date = bpub_date 21 book.save() 22 return book 23 24 25 class BookInfo(models.Model): 26 """图书模型类""" 27 # 书名 28 # btitle = models.CharField(max_length=20,verbose_name='书名') # verbose_name= 给列标题更名 29 btitle = models.CharField('书名',max_length=20) # 也能够第一个参数放中文标题 不用加verbose_name= 30 # 出版时间 31 bpub_date = models.DateField() 32 # 阅读量 33 bread = models.IntegerField(default=0) 34 # 评论数 35 bcomment = models.IntegerField(default=0) 36 # 是否删除 37 isDelete = models.BooleanField(default=False) 38 # 创建manager对象 39 objects = InfoManager() 40 41 # 将方法作列 42 def title(self): 43 return self.btitle 44 # 方法列排序 45 title.admin_order_field='btitle' 46 # 方法列标题更名 47 title.short_description = '书名(方法列)' 48 49 50 class HeroInfo(models.Model): 51 """英雄模型类""" 52 # 名字 53 hname = models.CharField(max_length=20) 54 # 性别 55 hgender = models.BooleanField(default=False) 56 # 功夫 57 hcomment = models.CharField(max_length=128) 58 # 书名 59 hbook = models.ForeignKey('BookInfo') 60 # 是否删除 61 isDelete = models.BooleanField(default=False) 62 63 64 class AreaInfo(models.Model): 65 """地区模型类""" 66 # 地区名 67 atitle = models.CharField(max_length=20) 68 # 关系属性 表明当前地区父类地区 69 aParent = models.ForeignKey('self', null=True, blank=True) 70 71 def __str__(self): 72 return self.atitle 73 74 # 封装方法 访问关联对象成员 75 def parent(self): 76 if self.aParent is None: 77 return '' 78 else: 79 return self.aParent.atitle 80 81 parent.short_description = '父级区域名称'
重写模板
1)在templates/目录下建立admin目录,结构以下图:
2)打开当前虚拟环境中Django的目录,再向下找到admin的模板,目录以下:
/home/python/.virtualenvs/py_django/lib/python3.5/site-packages/django/contrib/admin/templates/admin
编辑base_site.html文件:
{% extends "admin/base.html" %} {% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %} {% block branding %} <h1 id="site-name"><a href="{% url 'admin:index' %}">{{ site_header|default:_('Django administration') }}</a></h1> <hr> <h1>自定义的管理页模板</h1> <hr> {% endblock %} {% block nav-global %}{% endblock %}
建立管理员
终端中命令以下:
python manage.py createsuperuser
根据提示输入管理员、邮箱、密码
启动服务器
python manage.py runserver
打开浏览器,在地址栏中输入以下地址后回车
http://127.0.0.1:8000/admin/
输入创建的管理员和密码登陆
4.定义视图
打开booktest/views.py文件,定义视图代码以下:
1 from django.shortcuts import render, redirect # redircet重定向 2 from booktest.models import * 3 from datetime import date 4 from django.http import HttpRequest, HttpResponse 5 # Create your views here. 6 def index(request): 7 8 # 查看全部书 9 list = BookInfo.objects.all() 10 return render(request, 'booktest/index.html', {'list': list}) 11 12 def create(request): 13 14 b = BookInfo() 15 b.btitle = '流星蝴蝶剑' 16 b.bpub_date = date(1989,2,1) 17 b.save() 18 return redirect(index) # 跳转回首页 19 20 def delete(request, bid): 21 22 b = BookInfo.objects.get(id=bid) 23 b.delete() 24 return redirect(index) 25 26 def books(request, bid): 27 b = BookInfo.objects.get(id=bid) 28 list = b.heroinfo_set.all() 29 30 return render(request, 'booktest/detail.html', {'list':list,'book':b})
5.配置url
打开test2/urls.py文件,配置url以下:
1 from django.conf.urls import include, url 2 from django.contrib import admin 3 4 urlpatterns = [ 5 url(r'^admin/', include(admin.site.urls)), 6 # 引入booktest的url配置 7 url(r'^', include('booktest.urls')), # booktest.urls要加引号,否则找不到文件 ? 8 ]
在booktest应用下建立urls.py文件,代码以下:
1 from django.conf.urls import include, url 2 from django.contrib import admin 3 from booktest import views 4 5 urlpatterns = [ 6 url(r'^index$', views.index), 7 url(r'^create$', views.create), 8 # 传值用() 扩起来 如:(\d+) 9 url(r'^delete/(\d+)$', views.delete), 10 url(r'^books/(\d+)$', views.books), 11 ]
6.建立模板
打开test2/settings.py文件,配置模板查找目录TEMPLATES的DIRS。
‘DIRS’: [os.path.join(BASE_DIR,‘templates’)],
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR,'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
模板目录
建立templates/booktest/index.html文件。
模板文件
渲染模板index.html:
<a href="/create">新增</a> <ul> {% for book in list %} <li><a href="/books/{{ book.id }}">{{ book.btitle }}</a> --- <a href="/delete/{{ book.id }}">删除</a></li> {% endfor %} </ul>
7.运行 运行服务器。
python manage.py runserver (主机名 端口号) 括号里能够省去
在浏览器中查看。
首页
操做效果以下图。
运行
在mysql命令行中查看数据表变化以下图:
数据变化
静态文件配置
在settings.py文件中定义静态文件存放的物理目录
STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ]
在项目根目录下建立static目录,再建立img、css、js目录
ajax登陆提示403
这是csrf机制致使的 打开settings.py
MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', # 把这行注释了就能够了 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', )
模板继承
继承格式:{% extends 父模板文件路径%}
例:
{% extends 'layout/header.html' %} {% block 块名 %} {{ block.super}} #获取父模板中块的默认内容 重写的内容 {% endblock 块名%}
html转义
要关闭模板上下文字符串的转义: 能够使用 {{ 模板变量|safe}} 也能够使用: {% autoescape off %} 模板语言代码 {% endautoescape %} 模板硬编码中的字符串默认不会通过转义,若是须要转义,那须要手动进行转义
验证码
1)安装包
pip install Pillow==3.4.1
2)在booktest/views.py文件中,建立视图verify_code
1 from PIL import Image, ImageDraw, ImageFont 2 from django.utils.six import BytesIO 3 ... 4 def verify_code(request): 5 #引入随机函数模块 6 import random 7 #定义变量,用于画面的背景色、宽、高 8 bgcolor = (random.randrange(20, 100), random.randrange( 9 20, 100), 255) 10 width = 100 11 height = 25 12 #建立画面对象 13 im = Image.new('RGB', (width, height), bgcolor) 14 #建立画笔对象 15 draw = ImageDraw.Draw(im) 16 #调用画笔的point()函数绘制噪点 17 for i in range(0, 100): 18 xy = (random.randrange(0, width), random.randrange(0, height)) 19 fill = (random.randrange(0, 255), 255, random.randrange(0, 255)) 20 draw.point(xy, fill=fill) 21 #定义验证码的备选值 22 str1 = 'ABCD123EFGHIJK456LMNOPQRS789TUVWXYZ0' 23 #随机选取4个值做为验证码 24 rand_str = '' 25 for i in range(0, 4): 26 rand_str += str1[random.randrange(0, len(str1))] 27 #构造字体对象,ubuntu的字体路径为“/usr/share/fonts/truetype/freefont” 28 font = ImageFont.truetype('FreeMono.ttf', 23) 29 #构造字体颜色 30 fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255)) 31 #绘制4个字 32 draw.text((5, 2), rand_str[0], font=font, fill=fontcolor) 33 draw.text((25, 2), rand_str[1], font=font, fill=fontcolor) 34 draw.text((50, 2), rand_str[2], font=font, fill=fontcolor) 35 draw.text((75, 2), rand_str[3], font=font, fill=fontcolor) 36 #释放画笔 37 del draw 38 #存入session,用于作进一步验证 39 request.session['verifycode'] = rand_str 40 #内存文件操做 41 buf = BytesIO() 42 #将图片保存在内存中,文件类型为png 43 im.save(buf, 'png') 44 #将内存中的图片数据返回给客户端,MIME类型为图片png 45 return HttpResponse(buf.getvalue(), 'image/png')
3)打开booktest/urls.py文件,配置url
url(r'^verify_code/$', views.verify_code),
调用验证码
1)在booktest/views.py文件中,建立视图verify_show。
def verify_show(request): return render(request,'booktest/verify_show.html')
2)打开booktest/urls.py文件,配置url。
url(r'^verify_show/$', views.verify_show),
3)在templates/booktest/目录下建立verify_show.html。
<html> <head> <title>验证码</title> </head> <body> <form method="post" action="/verify_yz/"> {%csrf_token%} <input type="text" name="yzm"> <img id="yzm" src="/verify_code/"/> <span id="change">看不清,换一个</span> <br> <input type="submit" value="提交"> </form> </body> </html>
验证
1)在booktest/views.py文件中,建立视图verify_yz。
1 def verify_yz(request): 2 yzm=request.POST.get('yzm') 3 verifycode=request.session['verifycode'] 4 response=HttpResponse('no') 5 if yzm==verifycode: 6 response=HttpResponse('ok') 7 return response
2)打开booktest/urls.py文件,配置url。
url(r'^verify_yz/$', views.verify_yz),
反向解析
当某一个url配置的地址发生变化时,页面上使用反向解析生成地址的位置不须要发生变化。
根据url 正则表达式的配置动态的生成url。
在项目urls中包含具体应用的urls文件时指定namespace;
在应用的urls中配置是指定name;
在模板文件中使用时,格式以下:
{% url 'namespace名字:name' %} 例如{% url 'booktest:fan2'%}
带位置参数:
{% url 'namespace名字:name' 参数 %} 例如{% url 'booktest:fan2' 1%}
带关键字参数:
{% url 'namespace名字:name' 关键字参数 %} 例如{% url 'booktest:fan2' id=1 %}
在重定向的时候使用反向解析:
from django.core.urlresolvers import reverse
无参数:
reverse('namespace名字:name名字')
若是有位置参数
reverse('namespace名字:name名字', args = 位置参数元组)
若是有关键字参数
reverse('namespace名字:name名字', kwargs=字典)
中间件
1) 新建middleware.py文件。
2) 定义中间件类。
在类中定义中间件预留函数。
__init__:服务器响应第一个请求的时候调用。
process_request:是在产生request对象,进行url匹配以前调用。
process_view:是url匹配以后,调用视图函数以前。
process_response:视图函数调用以后,内容返回给浏览器以前。
process_exception:视图函数出现异常,会调用这个函数。
若是注册的多个中间件类中包含process_exception函数的时候,调用的顺序跟注册的顺序是相反的。
3) 注册中间件类。
图片上传