python_day18 Django表关系
day18 Django 表关系
ORM 1、类名------->表名
2、类属性----->字段类型
3、类对象----->表记录
数据库迁移:
python manage.py makemigrations
python manage.py migrate
流程:
url: http://127.0.0.1:8070/index? GET 无请求数据
# 添加
url: http://127.0.0.1:8070/add GET 无请求数据
url: http://127.0.0.1:8070/add post 请求数据
重定向:http://127.0.0.1:8070/index/ get 无请求数据
# 删除
http://127.0.0.1:8070/del/5 GET 无请求数据
重定向:http://127.0.0.1:8070/index/
#编辑
http://127.0.0.1:8070/edit/6 GET 无请求数据
http://127.0.0.1:8070/edit/6 POST 请求数据
重定向:http://127.0.0.1:8070/index/
注意点:
(1)请求方式对应不同的逻辑
(2) render方法执行过程
(3) 重定向
单表操作 可以简写edit函数部分
def edit(request):
models.Book.objects.filter(id=id).update(**request.POST.dict())
方式2中的 **request.POST.dict()并不是万能的 单表,一对一表情况下可用
request和post需要一一对应起来
今日内容
1、ORM表关系:一对多 多对多 一对一
2、ORM查询API:
表与表关系
1、 确定是什么关系
if 一对多:
关联字段放在多的一方;
foreign key dep_id reference dep(id)
if 多对多:
创建第三章表
create table student_teacher(
id int primary key,
student_id int,
teacher_id int,
foreign key student_id reference student(id)
foreign key teacher_id reference teacher(id)
)
if 一对一:
foreign key ,关联字段可以放在两张表中任意一张
关联字段必须唯一约束
ORM表关系:
1、配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 's18day18', #你的数据库名称
'USER': 'root', #你的数据库用户名
'PASSWORD': '', #你的数据库密码
'HOST': '', #你的数据库主机,留空默认为localhost
'PORT': '3306', #你的数据库端口
}
}
2、 数据库引擎更改:
MYsqlDB---->pymysql
在应用的__init__文件中加入:
import pymysql
pymysql.install_as_MySQLdb()
单表操作:
# 插入数据
# 插入数据方式1,create有返回值:插入的记录对象:
book_obj=models.Book.objects.create(title=title,pubDate=pubdate,price=price,publish=publish)
print(book_obj.title)
print(book_obj.price)
# 插入数据方式2:
book_obj=models.Book(title=title,pubDate=pubdate,publish=publish)
book_obj.price=price
book_obj.save()
app01->models:
class Book(models.Model):
id=models.AutoField(primary_key=True)
title=models.CharField(max_length=32)
pubDate=models.DateField()
price=models.DecimalField(max_digits=6,decimal_places=2)
publisher=models.ForeignKey(to=Publish)
class Publish(models.Model):
name=models.CharField(max_length=32)
addr=models.CharField(max_length=32)
tel=models.BigIntegerField
settings:
DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': "s18day18",
'USER': "root",
'PASSWORD': "mysql",
'HOST': '127.0.0.1',
'POST': '3306',
}
}
Terminal:
pip3 install pymysql
app01->__init__.py:
import pymysql
pymysql.install_as_MySQLdb()
数据库迁移:
python manage.py makemigrations
python manage.py migrate
新建package:static
复制dist 引用bootstrap
settings最后加入一行:
STATICFILES_DIRS=[
os.path.join(BASE_DIR,"static")
]
以下内容基于上次项目基础上完成的。
urls:
views:
index.html:在上次页面基础上
{{ book_list.publisher.name }} 出版社名称即出现
一对多的添加:
urls:
views:
def index(request):
if request.method == "POST":
title=request.POST.get("title")
.....
publish_id=request.POST.get("publish_id")
book_obj=models.Book.objects.create(title=title,...,publisher_id=publish_id) 使用字段添加表记录
return redirect("/index/")
publish_list=models.Publish.objects.all()
return render(request,"add.html","publish_list":publish_list)
add.html:
<p>出版社<select name="publish" id="">
{% for publish in publish_list %}
<option value="{{ publish.id }}">{{ publish.name }}
{% endfor %}
添加页面中显示出版社名称,将出版社ID信息传送给前端页面
html页面form表单中 {{ csrf_token }} setting中不必注释MIDDING第四行信息
单表插入数据方式2:
book_obj=models.Book(title=title,....,publisher_id=publish_id)
book_obj.save() 类实例化对象后save就可以增加表记录
一对多表插入数据方式2:
publish_obj=models.Publish.objects.filter(name="renmin")[0]
models.Book.objects.create(title=title,...,publisher=publish_obj)
#publisher 与这本书关联的出版社对象
create有返回值:插入的记录对象
模板templates之标签 if标签
urls:
views.temp:
temp.html:
<h3>TEMP
{% if n > 20 %}
<p>大于20
{% else %}
<p>小于20
{% endif %}
obj=models.Book.objects.filter(id=1)[0]
<p>{{ obj.author.authordetail.name }}
={% with book_obj.publish.name="name" %} with标签用法 使用name代指前面的那些
<p>{{ name }}
{% endwith %}
{% crsf_token %} 这个标签用于跨站请求爱伪站保护
<hr>
<form action="/temp/" method="post">
<p><input type="text" name="user">
<input type="submit">
{% crsf_token %}标示身份用的
for循环内 {% empty %} <p>没有响应书籍
自定义标签与过滤器的流程:
1、setting中INSTALLED_APPS检查是否有应用app01
2、在app01中templatetags包
3、templatetags创建任意.py文件
4、from django import template
from django.utils.safestring import make_safe
register=template.library() #register的名字是固定的,不可改变
@register.filter 自定义标签
def multi(x,y):
return x*y;
temp.html 将python函数与html模板结合起来了
5、{% load my_tag.py %} <p>{{ a|multi:12 }} 即a*12
自定义过滤器与自定义标签的流程一模一样。
仅装饰器不同
@register.simple_tag
def multi_tag(x,y):
return x*y;
{% load my_tag.py %} <p>{% multi_tag 3 5 %}
自定义标签和自定义过滤器区别:
1、自定义标签只能接收到2个参数
2、自定义过滤器 可接受任意参数 不能与if等使用
html母版与继承
template下创建母版base.html
{% block content %}
{% endblock %}
new_index.html:
{% extends "base.html" %}
{% block content %}
扩展内容
{% endblock %}
追加内容 {{ block.super }}
查询相关API 13个方法 全部记住
urls:^query,qurry:
def query(request):
查询API
1 all()
book_list=models.Book.objects.all() #QuerySet [obj1,obj2...]
for book_obj in book_list:print(book_obj.title)
2 filter() filter(**kwargs)
book_list=models.Book.objects.filter(price=123) #QuerySet [obj1,obj2...]
book_list=models.Book.objects.filter(price=123,title="数学书") 且
from django.db.models import Q
book_list=models.Book.objects.filter(Q(price=123)|Q(title="数学书")) 或
3 get方法 get(**kwargs)
a=models.Book.objects.get(title="数学书")#返回model对象book_obj,返回结果有且只有一个
print(a)
print(a.title)
get方法:数据库中没有或存在多个都会报错,只能有一个对象。一般用法是.get(id=1)
4 first() last()
book_obj=models.Book.objects.all().first()==[0] 返回对象
book_obj=models.Book.objects.filter(price=123).first()
5 exclude 筛选出不符合条件的QuerySet
book_obj=models.Book.objects.exclude(price=123)
6 count QuerySet调用count()
book_obj=models.Book.objects.exclude(price=123).count()
7 order_by(*field)
book_obj=models.Book.objects.all().order_by("price") 从小到大
book_obj=models.Book.objects.all().order_by("-price") 从大到小
8 reverse 反向排序
book_obj=models.Book.objects.all().order_by("price").reverse() 从大到小
9 values QuerySet调用他们
book_obj=models.Book.objects.all().values("title") QuerySet[{},{},...]
book_obj=models.Book.objects.all().values("title","price")
10 values_list
book_obj=models.Book.objects.all().values_list("title") [(),(),...]
11 exists
ret=models.Book.objects.all().exists()
if ret:print("OK")
else print("NO")
LOGINS的配置 加入setting中任意位置
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
只要执行models 都会打印出sql语句 日志Terminal
完美的双下划线 近似于模糊查询
book_obj=models.Book.objects.filter(id__gt=8) id大于8
book_obj=models.Book.objects.filter(title__startwith="语文")
.filter(title__endwith="语文")
.filter(title__icontains="语文") i不区分大小写
查询相关API
<1> all(): 查询所有结果
<2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象
<3> get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,
如果符合筛选条件的对象超过一个或者没有都会抛出错误。
<5> exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象
<4> values(*field): 返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
model的实例化对象,而是一个可迭代的字典序列
<9> values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
<6> order_by(*field): 对查询结果排序
<7> reverse(): 对查询结果反向排序
<8> distinct(): 从返回结果中剔除重复纪录
<10> count(): 返回数据库中匹配查询(QuerySet)的对象数量。
<11> first(): 返回第一条记录
<12> last(): 返回最后一条记录
<13> exists(): 如果QuerySet包含数据,就返回True,否则返回False
双下划线之单表查询
models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值
models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in
models.Tb1.objects.filter(name__contains="ven")
models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and
startswith,istartswith, endswith, iendswith