-
创建项目
django-admin startproject 项目名
开启测试服务
python manage.py runserver
-
修改基本配置信息
LANGUAGE_CODE = 'zh-Hans' #语言
TIME_ZONE = 'Asia/Shanghai' #时区
ALLOWED_HOSTS = ['*'] #谁可以访问我
USE_TZ = False #不同步内置时区
-
创建子app :用于业务分化
python manage.py startapp name
-
-
admin.py
: django 内置了一个数据库管理工具 -
models.py
: 数据库,模型类 -
views.py
: 存储不同的逻辑代码
-
-
编写视图函数,返回HELLOWORLD app->views->def
from django.http import HttpResponse
注册app:路由映射试图函数
在setting.py
中把子app注册在INSTALLED_APPS
属性中
在urls.py
中注册app中的views.py
路由
from appname import views
path('index/',views.index) #主路由不需要/ 用''即可
-
返回模板页面
-
-
并在
setting.py
中找到TEMPLATES->
'DIRS': [os.path.join(BASE_DIR,'template')],
BASE_DIR
是一个找到当前项目的工作目录,方便迁移返回模板运用
render
from django.shortcuts import render #render 在使用时接受三个参数
return render(请求,'template下路径/html页面')
redirect('路由/') 重定向
create()创建到数据库
models.表名.objects.create(
name = name,
age = age,
)在根项目文件中创建一个名为
static
的文件夹并在
setting.py
页面最后写入
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
)在html中写入
{% load static %}
:告诉django在哪找静态文件夹<img src="{% static 'img/1.png' %}">
-
模板变量加成
-
页面动态渲染
locals()
把当前作用域下的所有变量 变量名做key 变量值做value
-
-
app数据库的使用
-
Django有自带的数据表
-
先将django的自带数据表创建出来 python manage.py migrate 根据数据表差异文件执行真正SQL创建表
-
-
为自己的app创建表
-
python manage.py makemigrations 查找差异 创建迁移文件
只要改变表结构 就需要先查找差异
-
python manage.py migrate 根据迁移文件 生成数据表及字段
-
-
-
admin界面
django所提供用来帮助你管理项目所使用到的数据表的admin.site.register(models.People)要为admin界面创建超级用户: python3 manage.py createsuperuser
def __str__(self): #__unicode__
self.name-
前端数据的接收
-
表单
{% csrf_token %}
防止跨站伪造令牌或者在
settings.py
注销MIDDLEWARE->'django.middleware.csrf.CsrfViewMiddleware',
-
-
第一步,用户GET方法访问 拿到表单
-
-
-
输入表单 POST提交
-
-
当表单为多值情况,get方法只能获取到最后一个数,如果想获取到全部的要用getlist
-
-
路由:
-
perl、正则引擎,使用正则解决一个问题,那么你是在解决两个问题
-
静态路由:
-
path('',views.index)
re_path(r'^$',views.index)
-
-
路由传参:
-
未命名传参:
-
re_path(r'([a-z]{3})/(\d+)/',views.index)
-
-
命名传参:
-
re_path(r'(?P<name>[a-z]{3})/(?P<id_>\d+)/',views.index)
path('<int:id_>/<str:name>/',views.index)
-
-
-
路由分发
-
在子app中创建
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
] -
在主项目
urls.py
中导入include 在urlpatterns中注册子app的urls.py
path('hello_app/',include('hello_app.urls')),
-
-
路由命名
-
可在子app的urls中给路由定义name 也可以在主路由中给导入的路由定义
namespace
-
视图函数使用部分 反向解析:redirect(reverse('index')) -> redirect('/index/')
-
html标签跳转 反向查询 :{% url '子路由名' i %}
-
好处:可以解决路由使用时耦合性太高的问题,当连接映射发生变化,所有使用的地方都得变化,现在给这些连接起一个别名,接下来只要使用别名即可
-
-
应用命名空间:
app_name
使用app_name 指明命名空间,在子app的urls.py文件下配置全局变量
app_name
,这个值是唯一的在这个路由文件中定义其他的映射关系
app_name = 'hello_app' #这个值应该是唯一的
urlpatterns = [
path('', views.index,name = 'index'),
]
自定义过滤器
-
在app目录下创建名为templatetags 的文件夹
-
在这个文件夹下创建
__init__.py
文件,用来标识当前文件夹为一个可导入的包 -
创建一个register变量,这个变量为Library的实例
from django import template
resigter = template.Library() -
定义过滤器函数
def func(var):
return # 返回的内容就是页面展示的东西 -
注册过滤器
-
使用的时候,先将过滤器文件加载
{% load myfilter %}
-
注意:有自定义过滤器的APP,要记得加到settings->INSTALL_APPS中
-
mark_safe:用来标识当前返回数据为安全
from django.utils.safestring import mark_safe
模板继承
-
首先需要在template模板文件夹下创建一个名为
base.html
的文件 只供继承 不会有视图函数返回 -
必须在template 根目录下
-
{% load %} 模板导入标签
-
父页面 {% block name %} {% endblock name %} 通过block标签块挖坑
子模板
{% extends 'base.html' %} #使用的时候,一定是在继承页面的头部首先进行页面继承加载
{% block name %}
{% endblock name %}
模板组件
{% include '组件模板.html' %}
组件页面包含编写常用的页面数据的HTML组件文件,在需要的使用include标签导入即可
Django数据库
-
python manage.py makemigrations
-
生成数据库差异文件
-
-
python manage.py migrate
-
真正执行SQL
-
-
python manage.py createsuperuser
-
admin界面创建超级用户的
-
-
python manage.py runserver
-
127.0.0.1:本地回环路由
-
0.0.0.0:8000
-
LINUX系统下修改admin->Django 超级用户密码
[root@bogon five_hello]# python3 manage.py shell
>>> from django.contrib.auth.models import User
>>> user = User.objects.get(username='root')
>>> user.set_password('a1234567')
>>> user.save()直接登录新密码即可
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 数据库引擎
'NAME': "django_data", # 使用的库名
"USER": "root", # 用户名
"PASSWORD": "woaini21g", # 数据库密码
"HOST": "localhsot", # 数据库主机地址
"PORT": "3306"
}
}表属性
-
字段属性:
verbose_name(字段名称)
对于字段的一个可读性更高的名称如果没有设置该值,django将字段名中的下换线转换成空格,作为当前字段的数据库中名称DateField
年月日,
auto_now
当前数据在修改时,自动更新为当前时区时间DateTimeField
年月日时分秒,
auto_now_add
当数据创建时,自动更新为当前时间,一次创建后不会再改变IntegerField
最大长度2147483647 不能用于存储手机号
Null
如果该值为True,Django将在数据库中将控制存储为NULL字符串字段CharField与TextField要避免使用null,因为空值字符串将存储空字符串(""),而不是null值对于字符串类型的数据字段,大多数情况下,django使用空字符串代表空值blank
如果该值为True,则在验证时该字段值可以为空;null为数据库存储层面可以为空,而blank为表单验证层面可以填写空值choices(设置二元组)
一个二元组的列表或元组;元组中第一个值为真正在数据库中存储的值,第二个值为该选项的描述该值一旦被设定,表单样式会显示选择框,而不是标准的文本框,选择框内的选项为choices中的元组db_column
数据库中用来表示该字段的名称,如果未指定,那么Django将会使用 Field 名作为字段名db_index(加索引)
当该值为True时,为该字段创建索引default
该字段默认值,可以是一个值或是一个回调函数当是一个函数对象时,在创建新对象时,函数editable(不允许被编辑)
如果设置该值为False,那么这个字段将不允许被编辑不会出现在admin后台界面下,以及其他ModelForm表单中,同时也会跳过模型验证primary_key(主键)
设置该值为 True 时,该字段成为模型的主键字段,一个模型类同时只能有一个主键如果一个表中不存在任意一个设置好的主键字段,django会自动设置一个自增的 AutoField 字段来充当主键,该值可以用 pk , id 方式获取。主键的设置还意味着,null=False ,unique=TrueUnique(唯一)
如果该值为True,代表这个数据在当前的表中有唯一值这个字段还会在模型层验证存储的数据是否唯一unique的设置也意味着当前字段具备索引的创建ManyToManyField 、 OneToOneField 与 FileField 字段不可以使用该属性-
模型元选项
class Meta:
#元类 :设置当前类的属性 -> 表的属性
abstract = True
#声明当前的类 是一个抽象基类,可以被其他模型类继承,本身不会创建表
verbose_name = '客户端表' #系统自动后缀加s
verbose_name_plural = '客户端表' #系统后不加sabstract
代表当前模型类为抽象基类,不会创建真正的数据表,只是为了其他模型类继承使用
abstract = Trueapp_label = "appname"
标示当前的模型是哪个app的
db_table
修改数据库的表名
ordering
当前表中的数据存储时的排序规则,这是一个字段名的字符串,可以是一个列表的元祖
每一个字符串前可以使用 " . " 来倒叙排序,使用" ? "随机排序
unique_together
用来设置表中的不重复字段组合
格式为一个元祖,元祖中的每个数据都是一个元祖,用来描述不重复的组合字段
联合约束
ORM操作
-
pytho manage.py shell django 自带了 一个数据库测试的shell工具
-
创建数据
-
>>> p1 = models.Babe.objects.create(name='王五',age=30)
>>> p2 = models.Babe(name='赵六',age=25)
>>> p2.save()
-
-
查询
-
objects.all():获取表中所有数据
-
结果集
-
-
objects.filter()
.first()获取第一个 .last()获取最后一个 [0]索引获取第一个 否则也是结果集
-
支持链式查询:用字段__条件
-
条件:
startswith
以什么开头endswith
以什么结尾gte
大于等于lte
小于等于gt
大于lt
小于 -
equal
:相等的意思in
是否在其中
-
-
objects.exclude() 反义的意思
-
objects.get()
-
多个结果报错:modelapp.models.MultipleObjectsReturned: get() returned more than one Babe -- it returned 2!
-
modelapp.models.DoesNotExist: Babe matching query does not exist.
-
数据表没数据
-
没迁移
-
-
-
官方文档建议少用:
-
objects.order_by() 排序,可以对结果集进行排序
-
objects.count() 将查询结果进行计数,可以对结果集进行计数
-
objects.values() 把结果集改成字典 用于ajax
-
-
改:
-
先要查询到你要改谁
-
接着在内存中 res.filed = other res.save()
-
res.update("修改成什么") 所有符合条件的修改
-
-
删除:
-
res.delete()
-
queryset.delete()
-
多对多 删除关联 不删数据 remove() 关系表建在那个表从哪个表基础上删除
-
多对多 添加add( ) 关系表建在那个表从哪个表基础上添加
-
-
Django惰性查询
表关系
一对一关系:
一对一:一般用于某张表的补充,比如用户基本信息是一张表,但并非每一个用户都需要有登录的权限,不需要记录用户名和密码,此时,合理的做法就是新建一张记录登录信息的表,与用户信息进行一对一的关联,可以方便的从子表查询母表信息或反向查询 更接近于继承(成长)关系 如:人与伟人,老师与教授,男人与父亲,用户与登录时间,文章与评论,班长与班级
teacher = models.OneToOneField(Teacher,primary_key=True,on_delete=models.CASCADE)
,连接表字段 = models.OneToOneField(所连接的表,on_delete=models.CASCADE)primary_key=True 设为主键
多对一关系:
多对一:有很多的应用场景,比如每个员工归属于一个部门,那么就可以让员工表的部门字段与部门表进行一对多关联,可以查询到一个员工归属于哪个部门,也可反向查出某一部门有哪些员工 如:老师与学生,老板与员工,班长与班级同学
teacher = models.ForeignKey(Headmaster,null=True,blank=True,on_delete=models.SET_NULL)
,联系建立在多上,连接表字段 = models.ForeignKey(所连接的表,null=True数据库可以为空,on_delete=models.SET_NULL主表删除时子表不影响)
related_name = '反向查询的别名'
多对多关系:
多对多:如很多公司,一台服务器可能会有多种用途,归属于多个产品线当中,那么服务器与产品线之间就可以做成多对多,多对多在A表添加
ManyToManyField
字段或者从B表添加,效果一致
class RoleAdmin(admin.ModelAdmin):
list_display = ['name','role_count',] #列表里写的models的反向查询别名
admin.site.register(models.Role,RoleAdmin)-
字段关系字段关系是 django 维护表关系的方式;其中主要有一对一,多对一以及多对多, 现在的一对一及多对一关系中需要设置 on_delete 属性用来描述当关联数据被删除时的操作,有如下一些
models.CASCADE
:删除关联数据,与之关联也删除models.PROTECT
:删除关联数据,引发错误ProtectedErrormodels.SET_NULL
:与之关联的值设置为null(前提FK字段需要设置为可空)models.SET_DEFAULT
: 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)models.DO_NOTHING
:删除关联数据,什么也不做 -
SET_NULL与CASCADE的区别:CASCADE是被连接的表内数据删除,那么连接表的数据也会删除, 如:老师与教授,因为老师与教授是一个人,所以老师不在了,教授也就不在了,只能用CASCADE,不能用SET_NULL。 SET_NULL是被连接表内的数据删除后,对连接表没有影响, 如:男人与父亲,这个男人不在了,他的宝宝还在,所以不能用CASCADE,只能用SET_NULL,同时要注意将数据库和表单设置为可以为空, 以上的两种方法的使用都是通过业务逻辑来判断的。
-
查找对象:
all()(all_person = Person.objects.all())
获取一个表中的所有数据,返回 QuerySet 数据对象filter(**kwargs)(res = Person.objects.all().filter(age__lt=1)
返回一个包含数据对象的集合,满足参数中所给的条件exclude(**kwargs)(查找不符合条件的结果)
返回一个包含数据对象的集合,数据为不满足参数中所给的条件get(**kwargs)(获取唯一单条数据,多或者少都会报错,解决办法,try:捕获异常)
get获取数据只会返回一条匹配的结果,获取的数据只能在数据库中有一条order_by(*field)(Person.objects.all().order_by('-age'))
默认情况下,数据表使用模型类中的Meta中指定的ordering选项进行排序现在也可以通过使用order_by函数进行查询结果的排序count()(次数)
返回数据库中对应字段的个数,并且该函数永远不会引发异常values(*fields)(models.Person.objects.all().values())
返回一个查询集结果,但是迭代访问时返回的是字典,而不是数据实例对象 -
链式过滤:
Exact(Person.objects.filter(account__exact='root'))
如果在查询过程中,没有提供查询类型(没有 双下划线 ),那么查询类型就会被默认指定为 exact ,这是一种严格查找的方式,用来在数据库中查找和查询时的关键词参数完全一致的内容Iexact(Person.objects.filter(account__iexact='root'))
忽略大小写的匹配startswith、endswith(Person.objects.filter(passwd__startswith='admin'))
分别匹配开头和结尾,区分大小写istartswith、iendswith(Person.objects.filter(passwd__istartswith='admin'))
分别匹配开头和结尾,忽略大小写Gte(Person.objects.filter(reg_data__gte=datetime.date.today))
大于或等于Lte(Person.objects.filter(reg_data__lte=datetime.date.today))
小于或等于 -
修改:
1,重新赋值2,update
-
删除:
delete
-
反向查询:
一对一不需要加set多对多需要加set
COOKIE
保存在客户端
默认的COOKIE有效期是多久
关闭浏览器,COOKIE即消失
-
设置COOKIE:
-
res = HttpResponse
-
res.set_cookie(key,value,max_age)
-
-
获取COOKIE:
-
request.COOKIES.get(key)
-
-
批量多对多添加
*
解包 代表一个东西 要么是1 要那么是2 不是或,按照人数排序展示
if request.method == 'GET':
bands = models.Band.objects.all() #拿到所有乐队
data_ = {} #创建一个字典
for band in bands: #把所有乐队循环拿出一个乐队数据
count = band.player_set.all().count() #一个乐队的所有音乐家的个数
data_[band] = count #key:乐队的数据 value:这个乐队的音乐家个数
def func(key):
return data_[key]
bands = sorted(data_,key=func)缓存
在settings.py 中写入缓存
# 缓存memcahed无密码验证,
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
# 指定缓存使用的引擎
'LOCATION':'172.16.19.26:11211',
# 指定缓存服务器地址,常为本机地址
}
}分页
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
# Paginator 分页
# EmptyPage 空页面
# PageNotAnInteger 不是整型
P = Paginator(分页数据,3)
page_id = request.GET.get('page_id')
if page_id:
try:
变量 = p.page(page_id) #这一页的所有数据
except PageNotAnInteger: #如果传递的是非整型
变量 = p.page(1) # 返回第一页
except EmptyPage: #如果传递的是空页面
变量 = p.page(1) # 返回第一页
else:
变量 = p.page(1) # 返回第一页 -