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检查是否有应用app012、在app01中templatetags包3、templatetags创建任意.py文件4、from django import templatefrom django.utils.safestring import make_saferegister=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_tagdef 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):查询API1 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 Qbook_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 筛选出不符合条件的QuerySetbook_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大于8book_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