入门
小Demo设计介绍
- 本示例完成“图书-英雄”信息的维护,需要存储两种数据:图书、英雄
- 图书表结构设计:
- 表名:BookInfo
- 图书名称:btitle
- 图书发布时间:bpub_date
- 英雄表结构设计:
- 表名:HeroInfo
- 英雄姓名:hname
- 英雄性别:hgender
- 英雄简介:hcontent
- 所属图书:hbook
- 图书-英雄的关系为一对多
创建应用
在项目目录下(有manage.py文件的目录)命令行中执行(booktest为应用名):
python manage.py startapp booktest
创建成功后目录为
运行应用命令(ip可以不写,端口号可以不指定 默认8000 )
python manage.py runserver ip:port
设计模型类
from django.db import models
class BookInfo(models.Model):
bittle = models.CharField(max_length=20)
bpub_date = models.DateTimeField()
def __str__(self):
#return self.bittle.encode('utf-8')# python2写法 在3中会报TypeError: __str__returned non-string (type bytes)
错误
return self.bittle # python3写法
class HeroInfo(models.Model):
hname = models.CharField(max_length=10)
hgender = models.BooleanField()
hcontent = models.CharField(max_length=1000)
hbook = models.ForeignKey(BookInfo,on_delete=models.CASCADE)#指定外键 级联删除,也就是当删除主表的数据时候从表中的数据也随着一起删除
def __str__(self):
return self.hname
生成数据表 :
激活模型:在settings.py 的INSTALLED_APPS 最后添加项目的名字
生成迁移文件:根据模型类生成sql语句
执行 python manage.py makemigrations
执行迁移:执行sql语句生成数据表
python manage.py migrate
测试数据操作:
进入python shell :
python manage.py shell
管理操作
- 创建一个管理员用户
python manage.py createsuperuser,按提示输入用户名、邮箱、密码
在前台地址后面加/admin就是管理界面 例:http://127.0.0.1:8000/admin
管理界面本地化:
编辑settings.py文件,可以设置编码、时区
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
向admin注册booktest的模型
打开admin.py,注册模型
from django.contrib import admin from .models import * admin.site.register(BookInfo)
自定义管理页面
修改admin.py
通过定义ModelAdmin的子类,来定义模型在Admin界面的显示方式
关联对象
修改admin.py
视图
①.修改views.py设计界面 例:
from django.shortcuts import render from django.http import * def index(request): return HttpResponse('hello world')
②.urls.py 在urlpatterns添加路径与界面 例:
from django.contrib import admin from django.urls import path from booktest import views urlpatterns = [ path('admin/', admin.site.urls), path('',views.index) ]
(django2.X将url改为path
path转化器
文档原文是Path converters,暂且翻译为转化器。
Django默认支持以下5个转化器:
- str,匹配除了路径分隔符(
/
)之外的非空字符串,这是默认的形式 - int,匹配正整数,包含0。
- slug,匹配字母、数字以及横杠、下划线组成的字符串。
- uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
- path,匹配任何非空字符串,包含了路径分隔符
- 使用尖括号(
<>
)从url中捕获值。
例:path('<int:id>',views.show)
也可以使用正则表达式 将path改为re_path (需要引入re_path)
例:re_path(r'^(d+)$',views.show)
)
访问http://localhost:8000/
模板
创建模板的目录
页面设计
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>hello world</h1> </body> </html>
在视图views.py中引入模板
from django.shortcuts import render from django.http import * from django.template import RequestContext,loader def index(request): temp = loader.get_template('booktest/index.html') return HttpResponse(temp.render())#temp.render() 渲染 加载页面内容
可以用render函数代替
from django.shortcuts import render from django.http import * def index(request): return render(request,'booktest/index.html')#书写简单 用此方法更多
效果
获取传递数据
利用视图views.py中render的第三个参数传递数据
from django.shortcuts import render from django.http import * from .models import * def index(request): bookList = BookInfo.objects.all()#传递对象 context={'title':'hello','list':bookList} return render(request,'booktest/index.html',context)#context传递参数
页面接收
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--<h1>hello world</h1>--> <h1>{{ title }}</h1><!--参数获取--> {% for book in list %} {#在{% %}里写python代码#} <li>{{ book.bittle}}</li> {% endfor %} </body> </html>
页面效果
在提交ajax请求是报Forbidden (CSRF token missing or incorrect.错误
需要添加js(可以直接添加,也可以写成js文件引入)
$(function () { $.ajaxSetup({ headers: { "X-CSRFToken": getCookie("csrftoken") } }); }); <!--getCookie函数:--> function getCookie(name) { var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)"); if(arr=document.cookie.match(reg)) return unescape(arr[2]); else return null; }
===================================================================================================================================
模块
关联mysql
安装包 pip install mysql-python
pip install mysqlclient
创建数据库
在settings.py的DATABASES配置数据库设置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'test2',#数据库名 'USER': 'root',#mysql账号 'PASSWORD': '5418854188',#mysql密码 'HOST': 'localhost',#数据库服务器ip 'PORT': '3306',#mysql 端口 } }
之后正常开发(详情参考上面) 创建应用 python manage.py startapp booktest
settings.py INSTALLED_APPS添加应用
定义模型
定义属性
迁移(生成迁移文件:python manage.py makemigrations,执行迁移:python manage.py migrate)
#default,blank是python层面的对象,不影响数据库表结构,不需要重新迁移
===========================================================================================================================
存储session
- 使用存储会话的方式,可以使用settings.py的SESSION_ENGINE项指定
- 基于数据库的会话:这是django默认的会话存储方式,需要添加django.contrib.sessions到的INSTALLED_APPS设置中,运行manage.py migrate在数据库中安装会话表
使用Redis缓存session
- 会话还支持文件、纯cookie、Memcached、Redis等方式存储,下面演示使用redis存储
- 安装包
pip install django-redis-sessions
- 修改settings中的配置,增加如下项
SESSION_ENGINE = 'redis_sessions.session'
SESSION_REDIS_HOST = 'localhost'
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 0
SESSION_REDIS_PASSWORD = ''
SESSION_REDIS_PREFIX = 'session'
- 管理redis的命令
启动:sudo redis-server /etc/redis/redis.conf
停止:sudo redis-server stop
重启:sudo redis-server restart
redis-cli:使用客户端连接服务器
keys *:查看所有的键
get name:获取指定键的值
del name:删除指定名称的键
===============================================================================================================================================================================
管理静态文件
- 项目中的CSS、图片、js都是静态文件
1.在settings 文件中定义静态内容(STATIC_URL :逻辑路径(虚拟路径) 可以没有真实文件夹,但模板中路径会先匹配此路径,然后在通过下面的配置(物理路径)找文件)
STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ]
2.在项目根目录下创建static目录,再创建当前应用名称的目录
例: mysite/static/myapp/
3.在模板中可以使用硬编码
例:
/static/my_app/myexample.jpg
在模板中可以使用static编码
4.也可以
例:
{ % load static from staticfiles %} {#在模板中引入模块#} <img src="{ % static "my_app/myexample.jpg" %}" alt="My image"/>
==============================================================================================================================
中间件
===================================================================================================================================
上传文件
- 当Django在处理文件上传的时候,文件数据被保存在request.FILES
- FILES中的每个键为<input type="file" name="" />中的name
- 注意:FILES只有在请求的方法为POST 且提交的<form>带有enctype="multipart/form-data" 的情况下才会包含数据。否则,FILES 将为一个空的类似于字典的对象
- 使用模型处理上传文件:将属性定义成models.ImageField类型
pic=models.ImageField(upload_to='cars/')
- 注意:如果属性类型为ImageField需要安装包Pilow
- 图片存储路径
- 在项目static目录下创建media文件夹
- 图片上传后,会被保存到“/static/media/cars/图片文件”
- 打开settings.py文件,增加media_root项
MEDIA_ROOT=os.path.join(BASE_DIR,"static/media")
- 使用django后台管理,遇到ImageField类型的属性会出现一个file框,完成文件上传
- 手动上传的模板代码
<!DOCTYPE html> <html> <head> <title>文件上传</title> </head> <body> <form method="post" action="/upload/" enctype="multipart/form-data"> {% csrf_token %} <input type="text" name="title"><br> <input type="file" name="pic"/><br> <input type="submit" value="上传"> </form> </body> </html>
- 添加视图路径
path('upload/',views.upload)
- 手动上传的视图代码
from django.conf import settings import os def upload(request): if request.method == "POST": f1 = request.FILES['pic'] #fname = '%scars\%s' % (settings.MEDIA_ROOT, f1.name) fname = os.path.join(settings.MEDIA_ROOT, f1.name) with open(fname, 'wb') as pic:#以二进制读写文件 for c in f1.chunks(): pic.write(c) return HttpResponse("ok") else: return HttpResponse("error")
==========================================================================================================================================================================
分页
- Django提供了一些类实现管理数据分页,这些类位于django/core/paginator.py中
Paginator对象
- Paginator(列表,int):返回分页对象,参数为列表数据,每面数据的条数
属性
- count:对象总数
- num_pages:页面总数
- page_range:页码列表,从1开始,例如[1, 2, 3, 4]
方法
- page(num):下标以1开始,如果提供的页码不存在,抛出InvalidPage异常
异常exception
- InvalidPage:当向page()传入一个无效的页码时抛出
- PageNotAnInteger:当向page()传入一个不是整数的值时抛出
- EmptyPage:当向page()提供一个有效值,但是那个页面上没有任何对象时抛出
Page对象
创建对象
- Paginator对象的page()方法返回Page对象,不需要手动构造
属性
- object_list:当前页上所有对象的列表
- number:当前页的序号,从1开始
- paginator:当前page对象相关的Paginator对象
方法
- has_next():如果有下一页返回True
- has_previous():如果有上一页返回True
- has_other_pages():如果有上一页或下一页返回True
- next_page_number():返回下一页的页码,如果下一页不存在,抛出InvalidPage异常
- previous_page_number():返回上一页的页码,如果上一页不存在,抛出InvalidPage异常
- len():返回当前页面对象的个数
- 迭代页面对象:访问当前页面中的每个对象
例:
1.创建视图pagTest
from django.core.paginator import Paginator def pagTest(request,pIndex='1'): list1 = HeroInfo.objects.all() p = Paginator(list1, 10) pIndex = int(pIndex) list2 = p.page(pIndex) plist = p.page_range return render(request, 'booktest/pagTest.html', {'list': list2, 'plist': plist, 'pIndex': pIndex})
2.配置url
path('page/<str:pIndex>/',views.pagTest)
3.定义模板pagTest.html
<!DOCTYPE html> <html> <head> <title></title> </head> <body> <ul> {%for area in list%} <li>{{area.id}}--{{area.hname}}</li> {%endfor%} </ul> {%for pindex in plist%} {%if pIndex == pindex%} {{pindex}} {%else%} <a href="/page/{{pindex}}/">{{pindex}}</a> {%endif%} {%endfor%} </body> </html>
=====================================================================================================
富文本编辑器
- 安装django-tinymce pip install django-tinymce
- 在settings的
INSTALLED_APPS添加应用'
tinymce'
在settings.py中添加编辑配置项
TINYMCE_DEFAULT_CONFIG = { 'theme': 'advanced', 'width': 600, 'height': 400, }
配置url
path('tinymce/',include('tinymce.urls')),
在admin中使用需要在模型类中进行配置 例:
from django.db import models from tinymce.models import HTMLField class HeroInfo(models.Model): ... hcontent = HTMLField()
自定义使用
def editor(request): return render(request, 'other/editor.html')
path('editor/',views.editor),
<!DOCTYPE html> <html> <head> <title></title> <script type="text/javascript" src='/static/tiny_mce/tiny_mce.js'></script> <script type="text/javascript"> tinyMCE.init({ 'mode':'textareas', 'theme':'advanced', 'width':400, 'height':100 }); </script> </head> <body> <form method="post" action="/content/"> <input type="text" name="hname"> <br> <textarea name='hcontent'>哈哈,这是啥呀</textarea> <br> <input type="submit" value="提交"> </form> </body> </html>