通过换位思考,先站在一张表上分析,然后再在另一张表分析
确定多对多、一对多,一对一
_主键字段名
_
连接形成。(1)步骤一:
书籍表:
class Book(models.Model):
title = models.CharField(max_length=32)
# 小数总共八位 小数占两位
price = models.DecimalField(max_digits=8,decimal_places=2)
出版社表:
class Publish(models.Model):
title = models.CharField(max_length=32)
email = models.EmailField()
作者表:
class Author_detail(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
phone = models.BigIntegerField()
addr = models.CharField(max_length=32)
(2)步骤二:
书籍表:
class Book(models.Model):
title = models.CharField(max_length=32)
# 小数总共八位 小数占两位
price = models.DecimalField(max_digits=8,decimal_places=2)
外键一:
# 书跟出版社是一对多 并且书是多的一方 所以外键字段健在书表中
publish_id = models.ForeignKey(to='Publish') # to用来指代跟哪张表有关系 默认关联的就是表的主键字段
"""
一对多外键字段 创建的时候 同步到数据中 表字段会自动加_id后缀
如果你自己加了_id 我orm头铁 再在后面加一个_id
所以你在写一对多外键字段的时候 不要自作聪明的加_id
"""
外键二:
# 书跟作者是多对多的关系 外键字段建在任意一方都可以 但是建议你建在查询频率较高的那一方
author = models.ManyToManyField(to='Author') # django orm会自动帮你创建书籍和作者的第三张关系表
# author这个字段是一个虚拟字段 不能在实际的表中展示出来 仅仅只是起到一个告诉orm建第三章表的关系的作用
出版社表:
class Publish(models.Model):
title = models.CharField(max_length=32)
email = models.EmailField()
作者表:
class Author_detail(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
phone = models.BigIntegerField()
addr = models.CharField(max_length=32)
外键:
# 一对一的表关系 外键字段建在任意一方都可以 但是建议你建在查询频率较高的那一方
author_detail = models.OneToOneField(to='Author_detail') # fk + unique
"""
一对一外键字段 创建的时候 同步到数据中 表字段会自动加_id后缀
如果你自己加了_id 我orm头铁 再在后面加一个_id
所以你在写一对一外键字段的时候 不要自作聪明的加_id
"""
urls.py文件中的url方法的括号中的第一个参数其实是一个正则表达式,客户端发送的链接地址相当于一个大的字符串,该正则表达式就会在这个字符串中匹配,只要该正则表达式能够匹配到内容,就会立刻执行后面的视图函数,而不再往下继续匹配了。
urlpatterns = [
url(r'^admin/', admin.site.urls), # url第一个参数是一个正则表达式
url(r'^test/$', views.test), # 一旦正则表达式能够匹配到内容 会立刻结束匹配关系 直接执行后面对应的函数
url(r'^testadd/$', views.testadd),
]
本来浏览器会直接按照用户输入的地址到后端匹配,如果匹配不上,就会报404错误,但是Django项目中,Django会让浏览器把原来的地址的后面追加一个/
,再去后端匹配一次,这次若在匹配不到就会报404错误。
APPEND_SLASH = False
, 该参数默认是True。路由匹配只匹配前端地址中的url部分,不匹配?后面的get携带的参数
url方法的第一个参数中含有无名分组后,会将分组内正则表达式匹配到的内容当做位置参数传递给后面的视图函数,所以视图函数除了默认接收的request参数(request也是一个位置参数),还要添加一个位置参数
url(r'^test/([0-9]{4})/', views.test)
def test(request , 位置参数2) # 位置参数2的名字任意
url方法的第一个参数中含有有名分组后,会将分组内的正则表达式匹配到的内容当做关键字参数传递给视图函数,所以视图函数除了默认接收的request参数(request也是一个位置参数),还要添加一个分组名当做位置参数
url(r'^testadd/(?P<year>\d+)/', views.testadd),
def test(request , year)
第一种反向解析:urls.py文件的url方法的第一个参数中的正则是精确正则,即匹配的是一条具体不变的内容。
url(r'^home/', views.home,name='xxx'), # 给路由与视图函数对应关系起别名为xxx
前端反向解析
{% url 'xxx' %}
后端反向解析
from django.shortcuts import render,HttpResponse,redirect,reverse
url = reverse('xxx')
在解析的时候 你需要手动指定正则匹配的内容是什么
url(r'^home/(\d+)/', views.home,name='xxx'), # 给路由与视图函数对应关系起别名
前端反向解析
<p><a href="{% url 'xxx' 12 %}">111</a></p>
<p><a href="{% url 'xxx' 1324 %}">111</a></p>
<p><a href="{% url 'xxx' 14324 %}">111</a></p>
<p><a href="{% url 'xxx' 1234 %}">111</a></p>
后端反向解析
url = reverse('xxx',args=(1,))
url1 = reverse('xxx',args=(3213,))
url2 = reverse('xxx',args=(2132131,))
# 手动传入的参数 只需要满足能够被正则表达式匹配到即可
在解析的时候 你需要手动指定正则匹配的内容是什么
有名分组的反向解析和无名分组一样,但是最正规的写法是:
url(r'^home/(?P<year>\d+)/', views.home,name='xxx'), # 给路由与视图函数对应关系起别名
前端反向解析
# 可以直接用无名分组的情况
<p><a href="{% url 'xxx' 12 %}">111</a></p>
# 你也可以规范写法
<p><a href="{% url 'xxx' year=1232 %}">111</a></p> # 了解即可
后端反向解析
# 可以直接用无名分组的情况
url = reverse('xxx',args=(1,))
# 你也可以规范写法
url = reverse('xxx',kwargs={'year':213123}) # 了解即可
# 路由:
url(r'^edit_user/(\d+)/',views.edit_user,name='edit')
def edit_user(request,edit_id):
# edit_id就是用户想要编辑数据主键值
pass
# 前端反向解析
{% for user_obj in user_list %}
<a href='/edit_user/{{user_obj.id}}/'>编辑</a>
<a href='{% url 'edit' user_obj.id %}'>编辑</a>
{% endfor %}
(*********)
路由分发解决的就是项目的总路由匹配关系过多的情况。
使用路由分发 会将总路由不再做匹配的活 而仅仅是做任务分发(请求来了之后 总路由不做对应关系,只询问你要访问哪个app的功能 然后将请求转发给对应的app去处理)
实例:
from app01 import urls as app01_urls
from app02 import urls as app02_urls
urlpatterns = [
url(r'^admin/', admin.site.urls), # url第一个参数是一个正则表达式
# 路由分发
url(r'^app01/',include(app01_urls)), # 路由分发需要注意的实现 就是总路由里面不能以$结尾
url(r'^app02/',include(app02_urls)),
]
# 子路由
from django.conf.urls import url
from app01 import views
urlpatterns = [
url('^reg/',views.reg)
]
from django.conf.urls import url
from app02 import views
urlpatterns = [
url('^reg/',views.reg)
]
最省事的写法(******)
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls'))
#总路由
url(r'^app01/',include('app01.urls',namespace='app01')),
url(r'^app02/',include('app02.urls',namespace='app02'))
# 后端
print(reverse('app01:reg'))
print(reverse('app02:reg'))
# 前端
<a href="{% url 'app01:reg' %}"></a>
<a href="{% url 'app02:reg' %}"></a>
其实上面的名称空间知识点可以完全不用 你只需要保证起别名的时候 在整个django项目中不冲突即可。
参考建议:
起别名的时候统一加上应用名前缀
urlpatterns = [
url(r'^reg/',views.reg,name='app02_reg')
]
urlpatterns = [
url('^reg/',views.reg,name='app01_reg')
]
.html
结尾的网址,一般就是静态网页。用处:
每创建一个虚拟环境就类似于你重新下载了一个纯净python解释器
给每一个项目 装备该项目所需要的模块 不需要的模块一概不装,之后该项目用到上面 你就装什么
urls.py中路由匹配的方法有区别
# django.2.xxx版本用的是path
urlpatterns = [
path('admin/', admin.site.urls),
]
# django1.X用的是url
urlpatterns = [
url(r'^reg.html',views.reg,name='app02_reg')
]
# 区别 django2.X里面path第一个参数不是正则也不支持正则 写什么就匹配什么
# 虽然path不支持正则,感觉也好用 django2.X还有一个re_path的方法 该方法就是你django1.X里面url 。 使用方法就是直接在导包的那行代码,在path后面在加一个re_path
# 虽然path不支持支持正则,但是它提供了五种转换器,能够将匹配到的数据自动转换成对应的类型
# 除了有默认五种转换器之外, 还支持你自定义转换器
前期你在使用post朝后端发请求的时候 需要去settings配置文件中注释掉一个中间件csrf
使用file_obj = request.FILES.get(前端标签中的name的值)
if request.method == "POST":
print(request.FILES) # django会将文件类型的数据自动放入request.FILES里面
file_obj = request.FILES.get('myfile') # 文件对象
# print(file_obj)
# print(file_obj.name)
with open(file_obj.name,'wb') as f:
for line in file_obj:
f.write(line)
原文:https://www.cnblogs.com/Mcoming/p/11933068.html