————Model:数据————
1.连接MySQL数据库(settings.py设置范例):
# 配置数据库
DATABASES = {
'default': {
# 数据库引擎
'ENGINE': 'django.db.backends.mysql',
# 数据库名称
'NAME': 'axf',
# 账号和密码
'USER': 'root',
'PASSWORD': '123456',
# IP和端口
'HOST': 'localhost',
'PORT': '3306'
}
}
2.ORM(ObjectRelationalMapping=对象关系映射):
将具体语言下的【数据及其结构(通常以 类 表示)】映射为数据库的【 表结构和数据 】
在Django中,一旦 数据结构 发生 变化 ,就需要重新进行 数据迁移
3.数据迁移的操作
python manage.py makemigrations 生成数据迁移py文件
python manage.py migrate 执行数据迁移
4.数据定义
①数据类型
基本字段类型:
models.IntegerField(default=1)
models.FloatField(default=0)
models.BooleanField(default=False)
models.NullBooleanField() #支持null、true、false三种值#
models.TextField(db_column='ps') #大文本字段,一般超过4000使用#
models.DateTimeField(auto_now=True)
#使用Python的datetime.datetime实例表示的日期和时间
#若auto_now=True,每次保存对象时,自动设置该字段为当前时间
#若auto_now_add=True,当对象第一次被创建时自动设置当前时间(一次性的时间戳)
#注意:auto_now_add, auto_now,default三者是互斥的
其它字段类型:
model.DecimalField(max_digits=None, decimal_places=None)
#使用python的Decimal实例表示的十进制浮点数
#max_digits=总位数
#decimal_places=小数位数
model.DateField([auto_now=False, auto_now_add=False]) #使用Python的datetime.date实例表示的日期#
model.TimeField #使用Python的datetime.time实例表示的时间#
models.AutoField(primary_key=True)
#一个根据实际ID自动增长的IntegerField,通常不指定,如果不指定,一个主键字段将自动添加到模型中
model.FileField #上传文件字段
icon = models.ImageField(upload_to='icons')
#继承于FileField,框架对上传的对象进行校验,确保它是个有效的image
表关系字段:
暂无(查看后文)
定义字符串范例:
username = models.CharField(max_length=32, unique=True)
定义布尔值范例:
sex = models.BooleanField(default=False)
②字段约束
primary_key=False
#django会为表增加自动增长的主键列
#如果使用选项设置某属性为主键列后,则django不会再生成默认的主键列
max_length=None
unique=False
null=False #如果为True,则默认以空值NULL填充
blank=False #如果为True,则该字段允许为空白(即空字符串),这个约束常常用于表单验证
default=NOT_PROVIDED
db_index=False #若值为 True, 则在表中会为此字段创建索引
db_column=None #字段的名称,如果未指定,则使用属性的名称
【完整的约束源码】:
class Field(RegisterLookupMixin):
...
def __init__(self, verbose_name=None, name=None, primary_key=False,
max_length=None, unique=False, blank=False, null=False,
db_index=False, rel=None, default=NOT_PROVIDED, editable=True,
serialize=True, unique_for_date=None, unique_for_month=None,
unique_for_year=None, choices=None, help_text='', db_column=None,
db_tablespace=None, auto_created=False, validators=(),
error_messages=None):
...
③元信息
class Meta:
db_table = 'Flower'
ordering = ["-f_color"]
④范例:用户定义
# 用户数据模型
class UserModel(models.Model):
# 用户名密码邮箱
username = models.CharField(max_length=32, unique=True)
password = models.CharField(max_length=256)
email = models.CharField(max_length=64, unique=True)
# False 代表女
sex = models.BooleanField(default=False)
# 头像,图片字段,上传到静态资源文件夹下的icons/
icon = models.ImageField(upload_to='icons')
# 是否被逻辑删除
is_delete = models.BooleanField(default=False)
class Meta:
db_table = "t_user"
5.数据查询
①查询语法:
XXX.objects.all()
XXX.objects.get(k1=v1,k2=v2)
过滤器:
XXX.objects.filter(条件语句)
XXX.objects.exclude(条件语句)
②过滤器
filter(条件语句):获取符合条件的
exclude(条件语句):去除不符合条件的
③条件语句
格式:
格式1—>属性名=值(忽略大小写)
格式2—>属性名__运算符=临界值
运算符:
gt 、lt、gte、lte
startswith(大小写敏感)、endswith、contains、exact
istartswith(忽略大小写)、iendswith、icontains、iexact
④缓存的二次筛选
查询时允许多个过滤器串联使用(链式调用)
只有第一次会执行数据库查询,后续操作是对已有结果集的筛选
⑤Q对象:实现复杂条件
条件与—>Q(条件语句) & Q(条件语句)
条件或—>Q(条件语句) | Q(条件语句)
条件非—>~ Q(条件语句)
⑥
表关系
一对一(OneToOneField)
#将关系字段定义在任意一方
#举栗子:Person-IDCard,从表IDCard持有外键
class IDCard(models.Model):
i_num = models.CharField(max_length= 18)
# False 代表女
i_sex = models.BooleanField(default=False)
# 一张身份证对应着一个人
i_person = models.OneToOneField(Person, on_delete=models.SET_NULL, null=True)
#一访问一
格式:对象.模型
类小写
举栗子:idcard = person.idcard
一对多(ForeignKey)
#将关系字段定义在多方
#举栗子:Person-Hobby,多方Hobby持有外键
class Hobby(models.Model):
h_name = models.CharField(max_length=16)
h_cost = models.FloatField(default=1000)
h_person = models.ForeignKey(Person, on_delete=models.PROTECT)
#一访问多
格式:对象.模型
类小写
_set
举栗子:hobbies = person.hobby_set
多对多(ManyToManyField)
#将关系字段定义在任意一方
#举栗子:Buyer-Goods,从表Goods声明关联关系
class Goods(models.Model):
g_name = models.CharField(max_length=128)
g_price = models.FloatField(default=1)
# 声明商品和买家有多对多关系
g_buyers = models.ManyToManyField(Buyer)
#多a访问多b
goods.g_buyers.add(buyer)
buyers = goods.g_buyers.all()
goods_list = buyer.goods_set.all()
on_delete
#定义删除对象时如何处理其级联数据(其外键/关系字段指向的数据)
#可选值:
models.CASCADE —>默认值,默认删除级联数据
models.PROTECT —> 不存在级联数据的时候允许删除&当存在级联数据的时候删除会抛出保护异常
models.SET_NULL —> 级联数据赋值为空
models.SET_DEFAULT —>前提是字段本身有默认值
models.SET() —>删除的时候重新动态指向一个实体
维护表关系思路
1.在从表中添加关系字段,其类型即为【对方对象(或对象容器)】
2.框架自动为主表添加对应的关系字段,其类型即为【对方对象(或对象容器)】:.对方类名,IDE会自动提示可用的属性
6.Manager
显式属性
—> 开发者手动定义的,直接看的到的
隐式属性
—> 系统/框架根据需求,自动创建的对象
—>objects是model.Manager对象
—>当我们手动创建了Manager对象的时候,它就不会自动生成了
好处
—>配置默认的数据创建方式和查询方式
创建类并指定管理器
—>举栗子
class Dog(models.Model):
d_name = models.CharField(max_length=16)
d_legs = models.IntegerField(default=4)
is_delete = models.BooleanField(default=False)
# 交由管理器进行管理
d_manager = MyManager()
定义管理器类
—>
class MyManager(models.Manager):
定义创建实例方法:
# 创建狗的实例,默认两条腿
def create_model(self,d_name, d_legs = 2):
dog = self.model()
dog.d_name = d_name
dog.d_legs = d_legs
return dog
定义查询方法:
# 默认不包含被逻辑删除的狗狗
# 先调用model.Manager get_queryset
def get_queryset(self):
return super(MyManager,self).get_queryset().exclude(is_delete=True)
使用
管理器类
—>
创建实例:
dog = Dog.d_manager.create_model("中国田园犬")
查询实例:
dogs = Dog.d_manager.all()
dogs = Dog.d_manager.all().filter(is_delete=False)
dogs = Dog.d_manager.filter(d_legs__lt=100)
dogs = Dog.d_manager.filter(Q(d_legs__lt=20)|Q(d_legs__gt=150))
7.继承
定义父类
—>
# 动物父类
class Animal(models.Model):
#名字和腿数
a_name = models.CharField(max_length=16, default='Animal')
a_legs = models.IntegerField(default=4)
class Meta:
#表名是抽象的,框架不会为当前类创建表
abstract = True
定义子类
—>
# 动物子类狗狗
class Dog(Animal):
#已经有了a_name和a_legs
#定义自己独有的字段
d_fun = models.TextField()
8.常用API
查询 —>
flowers = Flower.objects.all()
flowers = Flower.objects.all().order_by("-id")[0:2]
flowers = Flower.objects.filter(f_color__gt=100).filter(f_color__lt=150)
flowers = Flower.objects.filter(f_color__gt=100).exclude(f_color__gt=150).filter(f_name__contains="水")
flowers = Flower.objects.filter(f_name__endswith="1")
flowers = Flower.objects.filter(f_name="rose")
flowers = Flower.objects.filter(pk__in=[1,2,3,4])
flowers = Flower.objects.filter(f_time__year="2019")
students = Student.objects.filter(s_grade_id__gt=F('id')-5)
----------------------------------------------------------------------------
flower = Flower.objects.get(pk=10)
flower = Flower.objects.get(f_color=255)
----------------------------------------------------------------------------
flower = flowers.last()
flower = flowers.first()
if flowers.count() == 0:
if flowers.exists():
----------------------------------------------------------------------------
dogs = Dog.objects.filter(~Q(d_legs__lt=100))
插入 —>
grade = Grade()
grade.g_name = 'fuck'
grade.save()
----------------------------------------------------------------------------
person = Person.objects.create(p_name="小黄%d"%random.randrange(110))
p = Buyer.objects.create(b_name="清醒%d下" % flag)
goods = Goods.objects.create(g_name="娃娃%d" % flag, g_price=flag)
删除 —>
通过查询得到一个特定的grade对象
grade.delete()
修改 —>
通过查询得到一个特定的grade对象
grade.gname='shit'
grade.save()
————Template:模板(界面)————
1.模板目录位置
应用下
—> 不需要注册
—> 无法跨应用地进行复用
工程下
—> 需要注册(settings.py范例)
# django默认的模板配置
TEMPLATES = [ { ...,
# 模板路径
'DIRS': [os.path.join(BASE_DIR, 'templates'),],
...},]
—> 可以在不同应用中复用
2.
模板语法
读取数据
—>
{{ xxx }}
{{ xxx.attr }}
{{ xxx.method }}
{{ xxx.i }}
{{ xxx.key }}
注释
—>
{# 模板注释是不可见的 #}
{% comment %}...{% endcomment %} #注释掉一吨内容
模板内计算
—>
加减 —> {{ value|add:10 }}
—> {{ value|add:-10 }}
乘除 —> {% widthratio a b c %} # a/b*c
大小写转换 —> {{ animal.a_name|lower }}
—> {{ animal.a_name|upper }}
判断是否整除 —> {% if forloop.counter|divisibleby:2 %}
连接容器内元素 —> {{ animals|join:'=' }}
加载静态文件
—> {% load static %}
—> {% load staticfiles %}
—> #访问静态资源
—> settings.py配置:
·静态文件夹位置
·访问路由
·静态文件访问路由
STATIC_URL = '/static/'
# 静态文件存储目录:根目录/static/
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
流程控制 ——> 遍历
{% if forloop.first %}
{% if forloop.last %}
{{ forloop.counter0 }} #正序下标,索引从0开始
{{ forloop.counter }} #正序下标,索引从1开始算
{{ forloop.revcounter }} #逆序,索引从最大长度到1
—> forloop.revcounter0 #逆序,索引从最大长度到0
—> forloop.parentloop #获取上一层 for 循环的 forloop
—> {% empty %} #当列表为空时用 for empty:
举栗子:
{% for animal in animals %}
{{ animal.a_name }}
{% empty %}
动物都跑啦
{% endfor %}
流程控制 ——> if条件
—> {% if forloop.first %}...{% elif forloop.last %}...{% else %}...{% endif %}
—> {% ifequal value1 value2 %}...{% else %}...{% endifequal %}
—> {% ifnotequal value1 value2 %}...{% else %}...{% endifnotequal %}
转义开关 ——> 转义
—> {% autoescape off %} {{ content }} {% endautoescape %}
—> {{ content|safe }}
转义开关 ——> 抑制
—> {% autoescape on %} {{ content }} {% endautoescape %}
—> {{ content }}
父辈挖坑子孙填 ——>
—> {% block extCSS %}...{% endblock %}
—> {{ block.super }} #引用父模板对当前块的实现
继承与兼并 ——>
—> {% extends 'base_main.html' %} #继承父模板
—> {% include xxx.html %} #兼并另一个模板使之成为页面的一部分
3.
翻页框架
引入
——>
样式
—>
脚本
—>
<--------------------------------------------------------------------->
样式
——>
# 外层包裹,需要配合脚本使用
^.^ 对应脚本
# 翻页包装器
...
# 分页内容1
...
# 分页内容2
—> 如果需要分页器 :
—> 如果需要导航按钮 :
—> 如果需要滚动条 :
<---------------------------------------------------------------------->
脚本
——> 查看
^.^ 内容
$(function () {
var swiper = Swiper(".swiper-container",{});
})
4.模板渲染过程
加载模板
template = loader.get_template('Hello.html') #
渲染模板
result = template.render()) #
result = template.render(context={"haha":"你哈什么哈"}) # 渲染时给模板传递数据
5.访问静态资源
settings.py的配置:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
页面的配置:
{% load static %}
————View:业务(控制器)————
1.什么是视图
视图层=路由表(urls.py)+ 视图函数(views.py)
其角色相当于MVC中的Controller
其职能是协调models和Template的关系,并解除其耦合
过程:
路由表接收用户请求,并分配给相应的视图函数进行处理
视图函数调用模型获取数据
视图函数将数据交给模板渲染
视图函数将渲染结果返回给客户端
2.路由的定义
定义路由响应函数:
url(r'^hehe/(\d+)/', views.hehe_user, name='hehe')
# 将指定路由交由指定函数进行处理&当前函数被命名为'hehe'
将特定路由派发给子路由表:
url(r'^app/', include('App.urls', namespace='app'))
#将所有/app/xxx派发给App下的urls.py处理&namespace='app'上述子路由表被命名为'app'
【反向解析】=得到【指定路由表中的指定函数】对应的路由
3.路由参数
普通参数规则:
在url匹配规则中使用括号,
url规则中有多少括号,request参数后就要有多少参数,
一一对应,按位置对应(位置参数),
写法(\正则).
<---------------------------------------------------------------------->
普通参数示例:
url(r'^hehe/(\d+)/', views.hehe_user, name='hehe')
def hehe_user(request, user_id):
<---------------------------------------------------------------------->
关键字参数规则:
关键字参数 (?P\正则 ) ,P代表params
需要和视图函数的参数 (year),按照名称匹配
<---------------------------------------------------------------------->
关键字参数示例:
url(r'^getdate/(?P\d+)/(?P\d+)/(?P\d+)', views.get_date, name='getdate')
def get_date(request, year, month, day)
<---------------------------------------------------------------------->
反向解析路径:
模板中:
{% url 'namespace:name' value1 value2 ...%}
{% url 'namespace:name' key=value key=value ...%}
视图中:
reverse('namespace:name', args=(value1,value2...))
reverse('namespace:name', kwargs={key:value, key: value})
4.发起请求
直接声明url:
反向解析获得url:
#namespace='two'的那个urls.py #上述urls.py中定义的name='haha'的那个响应函数
<---------------------------------------------------------------------->
#namespace='two'的那个urls.py
#上述urls.py中定义的name='hehe'的那个响应函数
#路径参数为17951
#最终url形如:/two/hehe/17951/
<---------------------------------------------------------------------->
#namespace='two'的那个urls.py
#上述urls.py中定义的name='getdate'的那个响应函数
#getdate这个响应函数中定义了三个参数:year,month,date
#三个路径参数分别为: year=2018 month=3 day=31
#最终url形如:/two/getdate/2018/3/31/
5.返回响应
渲染页面并返回:
return HttpResponse(result) # 以HttpResponse形式返回渲染结果
return HttpResponse("HelloWorld ") # 直接在响应中给页面内容
return render(request, 'Hello.html') # 直接返回渲染结果
return render(request, 'AnimalList.html', context={"animals": animals, "data": data_dict})
#渲染模板时传递数据
请求重定向:
return HttpResponseRedirect("/four/wahaha")
return HttpResponseRedirect("/four/getdate/4/1/2018/")
return HttpResponseRedirect(reverse("two:haha"))
return HttpResponseRedirect(reverse("two:getdate", kwargs={"year":"2019","month":"11", "day":"11"}))
return redirect(reverse("axf:user_login"))
返回JSON数据:
return JsonResponse({"msg": "ok", "status": "200", "data": "精神一下"})
用途:1.响应前端AJAX请求 2.为移动端APP返回数据 ……
JSON VS XML:(太厚重,已过时)
6.Request对象
1.请求对象
2.视图函数中的第一个参数
3.是由Django框架根据用户的请求信息,为开发者自动创建的一个对象
4.包含了请求的所有信息:
path、method、encoding、GET、POST、FILES、COOKIES、session
is_ajax、META
5.用法举栗:
user_id = request.session.get("user_id")
request.session["user_id"] = user.id
if request.method == "GET":
goodsid = request.GET.get("goodsid",None) # 获得请求数据
username = request.POST.get("username",None) # 获取表单数据
icon = request.FILES.get("icon") # 获取上传的文件位置,类型是字符串
request.session.flush() # 清空session
7.Response对象
1.响应对象
2.由开发者自己创建
3.服务器和客户端交流的方式
4.分类:
HttpResponse -》 render
HttpResponseRedirect -》redirect
JsonResponse
5.属性和方法
content
status_code
content-type (text/html)or (image/jpeg)
write()
flush() -->将缓冲区的内容推到response.content中
8.错误页面定制
1.关闭DEBUG模式
2.settings.py中设置:ALLOWED_HOSTS=['*']
想要覆盖哪个错误,就书写相应的HTML:404.html、502.html