一、路由系统 URL

1.模板语言循环字典

1.简单的字典循环

  1.  
  1. <ul>
  2. {% for i in user_dict %}
  3. <li>{{ i }}</li>
  4. {% endfor %}
  5. </ul>
  6.  
  7. 获取字典中的key
  8.  
  9. <ul>
  10. {% for i in user_dict.keys %}
  11. <li>{{ i }}</li>
  12. {% endfor %}
  13. </ul>
  14.  
  15. 获取字典中的key,通过keys关键字,不要括号
  16.  
  17. <ul>
  18. {% for i in user_dict.values %}
  19. <li>{{ i }}</li>
  20. {% endfor %}
  21. </ul>
  22.  
  23. 获取字典中的value,通过values关键字,不要括号
  24.  
  25. <ul>
  26. {% for i in user_dict.items %}
  27. <li>{{ i }}</li>
  28. {% endfor %}
  29. </ul>
  30.  
  31. 获取字典中的key和value,得到的是个元组
  32.  
  33. <ul>
  34. {% for i,j in user_dict.items %}
  35. <li>{{ i }}---{{ j }}</li>
  36. {% endfor %}
  37. </ul>
  38. 分别获取字典中的key,value,

                                                                                                                                          

  1. {% for i in user_dict %} {% for i in user_dict.keys %} {% for i in user_dict.values %} {% for i in user_dict.items %} {% for i,j in user_dict.items %}

循环字典,和python里是差不多的,就是后面没有括号():

  • 直接dict :循环的是key
  • dict.keys :循环key
  • dict.values :循环values
  • dict.items :循环key和values

2.一条对应关系对应多个页面

这里通过嵌套字典来实现

场景:一个页面会显示很多用户的某个信息,然后我们点击查看详情,会出来用户的多条信息,但是这些用户信息不是在同一个页面上,例如我们看博客园里面的博客,每次查看如,

https://www.cnblogs.com/mlq2017/p/10054661.html        /10054661这个值,换一篇博客,这个nid就会变,

1.通过GET方式实现:

  1. #index.html
  2.  
  3. <body>
  4. <ul>
  5. {% for i,j in user_dict.items %}
  6. <li><a target="_blank" href="/detail/?nid={{ i }}">{{ j.name}}</a></li>
  7. {% endfor %}
  8.  
  9. </ul>
  10. </body>
  11.  
  12. #detail,html
  13.  
  14. <!DOCTYPE html>
  15. <html lang="en">
  16. <head>
  17. <meta charset="UTF-8">
  18. <title>Title</title>
  19. </head>
  20. <body>
  21. <h1>详细信息</h1>
  22. <h3>用户名:{{ user_info.name }}</h3>
  23. <h3>年龄:{{ user_info.age }}</h3>
  24. <h3>邮箱:{{ user_info.email }}</h3>
  25. </body>
  26. </html>
  27.  
  28. #urls.py
  29.  
  30. path('index/', views.index),
  31. path('detail/', views.detail),
  32.  
  33. #wiews.py
  34. from django.shortcuts import render
  35. USER_DICT = {
  36. "":{"name":"root1","age":"","email":"123@163.com"},
  37. "":{"name":"root2","age":"","email":"223@163.com"},
  38. "":{"name":"root3","age":"","email":"323@163.com"},
  39. "":{"name":"root4","age":"","email":"423@163.com"},
  40. }
  41.  
  42. def detail(request): #通过GET,html里面用 /?+{{key}}
  43. a = request.GET.get("nid")
  44. user_info = USER_DICT[a]
  45. print(user_info)
  46. return render(request,"detail.html",{"user_info":user_info})
  47.  
  48. def index(request):
  49.  
  50. return render(request,"index.html",{"user_dict":USER_DICT})

这里用到了如下方法:

1.html里面使用:href="/detail/?nid={{ i }}"   通过?加上字典的key跳转链接

2.views里面的detail里面通过GET获取nid:  然后通过nid获取字典的值,将值传给rengder(),再后在页面获取每个值中的信息

2.通过正则方式实现:

上面的HTML代码只有一个地方需要修改,做成动态匹配

  1. {% for i,j in user_dict.items %}
  2. <li><a target="_blank" href="/detail-{{ i }}.html">{{ j.name }}</a></li>
  3. {% endfor %}

相应的urls.py里面用到正则匹配

  1. from django.contrib import admin
  2. from django.urls import path,re_path
  3. from app import views
  4. urlpatterns = [
  5. path('admin/', admin.site.urls),
  6. path('index/', views.index),
  7. re_path('detail-(\d+).html', views.detail),
  8.  
  9. ]

既然我们用到正则,那这里就要导入正则,使用正则匹配

  1. from django.urls import re_path
    下面的匹配为:
    re_path('detail-(\d+).html', views.detail),
    这里要注意,之前的视频是很老的,方法不一样,按照视频上说的做,会一直报错

然后是views.py里面的修改了

  1. def detail(request,nid): #正则匹配
  2. #return HttpResponse(nid)
  3. user_info = USER_DICT[nid]
  4. print(nid)
  5. return render(request,"detail.html",{"user_info":user_info})

这里我们需要在detail里面再给一个形参,接收传过来的动态参数:这里返回的是字典的key,

然后通过nid直接获取字典的第一层值

建议使用正则的时候用下面的方法

  1. re_path('detail-(?P<nid>\d+).html', views.detail),

将形参进行绑定,就不用考虑传入的位置

1.当html后面接很多-(\d+)时,如,re_path('detail-(\d+)-(\d+).html', views.detail),在detail里面传多个形式参数的时候def detail(request,nid,uid): 位置就要一一对应,

      如果用上面的方式,我们就可以任意写形参的位置

2.当我们写正则的时候绑定了多个参数,在detail里面传多个形式参数的时候def detail(request,nid,uid,……):,我们就要穿多个参数,对于这样的,我们可以使用

  1. def detail(request,*args,**kwargs):

这样,我们通过re_path('detail-(\d+)-(\d+).html', views.detail) 这样的就会把值传给*args

   我们通过re_path('detail-(?P<nid>\d+).html', views.detail),这样的就会吧值传给**kwargs

总结实战:

a.

  re_path('detail-(\d+)-(\d+).html', views.detail),

  def func(request,nid,uid):

  def func(request,*args):

  args = (2,9)

  def func(request,*args,**kwargs):

b.

  re_path('detail-(?P<nid>\d+)-(?P<nid>\d+).html', views.detail),

  def func(request,nid,uid):

  def func(request,*args,**kwargs):

  *args为空,**kwargs为字典接受上面的值

三.关于url中的name

1.当频繁修改url,就要修改urls.py,又要修改html页面,

  我们可以在urls里面给url进行绑定,之后无论怎么修改,只需要修改url里面的值就行

  1. 在绑定是添加name进行绑定
    path('index/', views.index,name = "indexx"),
  2.  
  3. detail.html里面,提交表单时,这么改
  4. <form action="{% url "indexx" %}">
  5. <input type="text" />
  6. </form>

2.当我们还要在绑定的url后面继续使用匹配,如:path('index/(\d+)/', views.index,name = "indexx"),

  此时我们无法通过action="{% url "indexx" %}" 进行提交,可以用

  1.跳转到固定的页面

  1. <form action="{% url "indexx" 11 %}">

  后面这个11,表示只能跳转到这个页面,并且这种模板语言,后面只能写固定值

  2.跳转到当前页面

    这里要用到request中的path_info,获取当前页面的url

  1. detail函数里面,我们试着打印request.path_info
  2.  
  3. print(request.path_info) # 输出结果为:/detail-1.html

  distail里面不需要改,因此我们可以在action里面这么写

  1. <form action="{{ request.path_info }}">

用 path() 方法实现捕获参数

课上讲的是旧版本,现在Django已经2.0了,url()方法被path()方法替代,用法也有区别。
re_path() 可以看做是2.0里向下兼容的一个方法,也就是旧的1.0的 url() 方法。在2.0里用 path() 方法也可以实现捕获组的对应关系。使用 path() 方法需要注意:

    1. 要捕获一段url中的值,需要使用尖括号,而不是之前的圆括号;
    2. 可以转换捕获到的值为指定类型,比如int。默认情况下,捕获到的结果保存为字符串类型,不包含 '/' 这个特殊字符;
    3. 匹配模式的最开头不需要添加 '/' ,因为默认情况下,每个url都带一个最前面的 '/' ,既然大家都有的部分,就不用浪费时间特别写一个了。
  1. path('detail2-<int:nid>-<int:uid>.html', views.detail2),

上面的例子,就是捕获一个0或正整数,并且返回一个int类型,再用冒号把命名也完成了。除了int,还有下面这些。
默认情况下,Django内置下面的路径转换器:

    • str:匹配任何非空字符串,但不含斜杠/,如果你没有专门指定转换器,那么这个是默认使用的;
    • int:匹配0和正整数,返回一个int类型;
    • slug:可理解为注释、后缀、附属等概念,是url拖在最后的一部分解释性字符。该转换器匹配任何ASCII字符以及连接符和下划线,比如’ building-your-1st-django-site‘ ;
    • uuid:匹配一个uuid格式的对象。为了防止冲突,规定必须使用破折号,所有字母必须小写,例如’075194d3-6885-417e-a8a8-6c931e272f00‘ 。返回一个UUID对象;
    • path:匹配任何非空字符串,重点是可以包含路径分隔符’/‘。这个转换器可以帮助你匹配整个url而不是一段一段的url字符串。

小结

上面各种实现的方法由浅入深,并且一个比一个好,推荐用最后面的实现方式:

  • 基于正则的url比使用get方式获取参数的好
  • 命名捕获组比普通捕获组好
  • 推荐还是用最后的 path() 方法来实现,如果是1.x的版本,那么就是推荐基于正则的命名捕获组的方法。

另外,在定义函数的时候也可以写成这种万能的模式: def detail2(request, *args, **kwargs): ,这样的话,要使用 args[0] (普通捕获组)或 kwargs['nid'] (命名捕获组)来取值。

路由分发

之前所有的url对应关系都写在了项目名下的urls里面,当我们的项目有多个app的时候,所有的页面都写在一起也不好。应该是每个app各自管理自己的那部分url。这就需要路由分发。

1.首先我们在项目名下的urls里面导入include,

  1. from django.contrib import admin
  2. from django.urls import path,re_path
  3. from django.urls import include #导入include
  4.  
  5. urlpatterns = [
  6. path('admin/', admin.site.urls),
  7. path('app/',include('app.urls')) #添加app的绑定
  8. ]

    如果有多个app,就继续在下面添加绑定  path('app1/',include('app1.urls')) 这样的

2.然后在app里面创建一个同样的urls.py

3.导入views,py

  1. from django.urls import path,re_path
  2. from app import views
  3. urlpatterns = [
  4. path('index/', views.index),
  5. ]

默认值

命名空间

二、视图

提交数据不仅有POST和GET,还有其他的提交方法,比如:PUT、DELETE、HEAD、OPTION

form表单提交数据

1,request.POST.get()

2,request.GET.get()

3,request.POST.getlist()

4,request.FILES.get()

先上代码:

  1. #login。html
  2.  
  3. <!DOCTYPE html>
  4. <html lang="en">
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>Title</title>
  8. </head>
  9. <body>
  10. <form action="" method="post" enctype="multipart/form-data">
  11. <p>
  12. <input type="text" name="user" placeholder="用户名">
  13. </p>
  14. <p>
  15. <input type="password" name="pwd" placeholder="密码">
  16. </p>
  17. <p>
  18. 男:<input type="radio" name="gender" value="">
  19. 女:<input type="radio" name="gender" value="">
  20. 人妖:<input type="radio" name="gender" value="">
  21. </p>
  22. <p>
  23. 男:<input type="checkbox" name="favl" value="">
  24. 女:<input type="checkbox" name="favl" value="">
  25. 人妖:<input type="checkbox" name="favl" value="">
  26. </p>
  27. <p>
  28. <select name="city" multiple="multiple">
  29. <option value="sz">深圳</option>
  30. <option value="bj">北京</option>
  31. <option value="sh">上海</option>
  32. </select>
  33. </p>
  34. <p>
  35. <input name="file" type="file">
  36. </p>
  37. <p>
  38. <input type="submit" value="提交">
  39. <span style="color: red">{{ error_msg }}</span>
  40. </p>
  41.  
  42. </form>
  43. </body>
  44. </html>
  45.  
  46. views.py
  47.  
  48. from django.shortcuts import render,redirect,HttpResponse
  49.  
  50. # Create your views here.
  51.  
  52. def login(request):
  53. if request.method == "POST":
  54. obj = request.POST.get("gender")
  55. print("obj",obj) #输出为1
  56. obj1 = request.POST.get("favl")
  57. obj2 = request.POST.getlist("favl")
  58. print("obj1",obj1) #这里checkbox是多选框,但是只获取到一个值,实际要获取多个,这里不能用get
  59. print("obj2", obj2) #obj2 ['11', '33'] 这里获取到了每个选中的值
  60. obj3 = request.POST.getlist("city")
  61. print("obj3", obj3) #obj3 ['sz', 'bj', 'sh']
  62. obj4 = request.POST.get("file") #obj4 None <class 'NoneType'> 这里没获取到
  63. print("obj4", obj4,type(obj4))
  64. obj5 = request.FILES.get("file")
  65. print("obj5", obj5, type(obj5)) #这里获取到的是文件名和文件,
  66. #from django.core.files.uploadedfile import InMemoryUploadedFile
  67. f = open(obj5.name,"wb")
  68. for data in obj5.chunks():
  69. f.write(data)
  70. f.close()
  71. elif request.method == "GET":
  72. pass
  73. else:
  74. return HttpResponse("index")
  75.  
  76. return render(request,"login.html",)
  77.  
  78. #error_msg = ""
  79. # def login(request):
  80. # if request.method == "POST":
  81. # u = request.POST.get("user")
  82. # p = request.POST.get("pwd")
  83. # if u == 'aaa' and p == '123':
  84. # return HttpResponse("home")
  85. # else:
  86. # error_msg = "用户名或密码错误"
  87. # return render(request,"login.html",{"error_msg":error_msg})
  88. # elif request.method == "GET":
  89. # pass
  90. # else:
  91. # return HttpResponse("index")
  92. #
  93. # return render(request,"login.html",)
  94.  
  95. #urls.py
  96.  
  97. from app import views
  98. urlpatterns = [
  99. path('admin/', admin.site.urls),
  100. path('login/', views.login),
  101. ]

注释部分第一节已经写过,都是通过get获取

对于从网页只获取一个值的我们可以用get(text,password,radio),

  1. obj = request.POST.get("gender")
  2. print("obj",obj) #输出为1

但是如果是多选,就需要用getlist(checkbox,select),

  1. obj1 = request.POST.get("favl")
  2. obj2 = request.POST.getlist("favl")
  3. print("obj1",obj1) #这里checkbox是多选框,但是只获取到一个值,实际要获取多个,这里不能用get
  4. print("obj2", obj2) #obj2 ['11', '33'] 这里获取到了每个选中的值
  5. obj3 = request.POST.getlist("city")
  6. print("obj3", obj3) #obj3 ['sz', 'bj', 'sh']

普通表单无法上传文件,要上传文件,还需要在form标签中加  enctype="multipart/form-data"

另文件我们需要用request.FILES.get(),这样获取到的不是文件的名称,而是一个类,既能获取到文件名,又能获取到文件,文件名通过obj5.name获取,文件内容用 obj5.chunks()

  1. obj4 = request.POST.get("file") #obj4 None <class 'NoneType'> 这里没获取到
  2. print("obj4", obj4,type(obj4))
  3. obj5 = request.FILES.get("file")
  4. print("obj5", obj5, type(obj5)) #obj5 作业.png <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>这里获取到的是文件名和文件,
  5. #from django.core.files.uploadedfile import InMemoryUploadedFile
  6. f = open(obj5.name,"wb")
  7. for data in obj5.chunks():
  8. f.write(data)
  9. f.close()

CBV 和 FBV

  • FBV(function base views) 就是在视图里使用函数处理请求。
  • CBV(class base views) 就是在视图里使用类处理请求。

到目前为止,所有的处理都是写在一个函数里的。Django还提供另外一个方式,我们也可以通过类来处理。

之前用FBV,这里也可以把之前的函数改成类处理请求,

  1. #home.html
  2.  
  3. <!DOCTYPE html>
  4. <html lang="en">
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>Title</title>
  8. </head>
  9. <body>
  10. <form action="/home/" method="post">
  11. <input type="text" name="user" />
  12. <input type="submit" value="提交" />
  13. </form>
  14. </body>
  15. </html>
  16.  
  17. #views.py
  18.  
  19. from django.shortcuts import render,redirect,HttpResponse
  20.  
  21. #FBV和CBV
  22. from django.views import View
  23.  
  24. class Home(View):
  25.  
  26. def get(self,request): #当输入http://127.0.0.1:8000/home/地址时,是get请求,因此下面的打印的结果为GET
  27. print(request.method)
  28. return render(request,"home.html")
  29.  
  30. def post(self,request):
  31. print(request.method) #当输入内容时,是post请求,执行了这里,打印结果为POST
  32. return render(request,"home.html")
  33.  
  34. #urls.py
  35.  
  36. from app import views
  37. urlpatterns = [
  38. path('admin/', admin.site.urls),
  39. #path('login/', views.login), 提交表单的
  40. path('home/', views.Home.as_view()),
  41.  
  42. ]

以上代码执行和之前使用FBV效果是一样的,我们在类里写上对应的提交方式,当执行是,会自动到类里面去找对应的函数。

CBV的写法为

1.先导入View,在视图里面创建类

  1. from django.views import View
  2.  
  3. class Home(View):

2.修改urls里面,这里添加url对应关系和FBV不同,应此需要特别注意:中间写上类名,后面固定跟一个 .as_view()

3.在类中定义相应的方法,

先去看看继承的View类里有什么,在源码的base.py这个文件里。首先里面定义了一个公有属性:

点击View会看到

  1. http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

所以除了GET,POST,还可以处理这么多的请求方法,用起来,在类里照着别的一样定义一个同名方法就可以了。

3.在类中可以引入父类,就是Django内部定义的父类,这样我们既能定义自己的类,还可以继承父类,修改父类(装饰器)

继续看源码的View,调用了as_view()方法里面会再调用一个dispatch()方法。这个dispatch()方法里是通过映射获取我们的 request.method 即提交的方法来调用我们的处理方法的。dispatch()的源码如下:

  1. def dispatch(self, request, *args, **kwargs):
  2. # Try to dispatch to the right method; if a method doesn't exist,
  3. # defer to the error handler. Also defer to the error handler if the
  4. # request method isn't on the approved list.
  5. if request.method.lower() in self.http_method_names:
  6. handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
  7. else:
  8. handler = self.http_method_not_allowed
  9. return handler(request, *args, **kwargs)

结论就是,根据不同的请求类型提交到不同的处理方法,是用过dispatch()方法里通过映射来实现的。先执行dispatch()方法然后再调用对应的提交类型的处理方法。

  1. class Home(View):
  2.  
  3. def dispatch(self, request, *args, **kwargs):
  4. #调用父类中的dispatch
  5. result = super(Home,self).dispatch(request, *args, **kwargs)
  6. return result
  7.  
  8. def get(self,request): #当输入http://127.0.0.1:8000/home/地址时,是get请求,因此下面的打印的结果为GET
  9. print(request.method)
  10. return render(request,"home.html")
  11.  
  12. def post(self,request):
  13. print(request.method) #当输入内容时,是post请求,执行了这里,打印结果为POST
  14. return render(request,"home.html")

在类中添加dispatch()方法后,执行效果和不添加它的效果是一样的

所以通过继承和重构dispatch()方法,可以在处理方法执行前和执行后自定义一些操作。如果需要的话就在我们的类里继承并重构,

  1. def dispatch(self, request, *args, **kwargs):
  2. #调用父类中的dispatch
  3. print("before") //处理前执行的操作
  4. result = super(Home,self).dispatch(request, *args, **kwargs)
  5. print("after") //处理后执行的操作
  6. return result

上面看了View代码,我们看到了,当提交方式都不匹配的时候是执行下面的代码,页面是返回405

  1. def http_method_not_allowed(self, request, *args, **kwargs):
  2. logger.warning(
  3. 'Method Not Allowed (%s): %s', request.method, request.path,
  4. extra={'status_code': 405, 'request': request}
  5. )

这里我们就可以重构自己的方法了:

  1. def http_method_not_allowed(self, request, *args, **kwargs):
  2. return redirect('/home/')

给views.py分类

默认所有的处理函数都是写在views.py这个文件里的。如果处理函数很多,全部写在一个文件里也会很乱。这是可以考虑创建一个views包来替代原来的views.py文件。然后在views包里创建多个py文件来写我们的处理函数。比如:

  • views/account.py 是用户相关的操作,登录认证之类的
  • views/test.py 是用来测试的处理函数
  • views/order.py 订单相关的操作

三、模板

  1.  
  1.  
  1.  

四、ORM操作

django数据库错误相关问题

连接sqlite数据库

默认使用的是sqlite3作为数据库,使用数据库需要一下步骤
一、创建你的数据库表结构

在app01里面的models.py添加类

  1. from django.db import models
  2. # Create your models here.
  3. class Userinfo(models.Model):
  4. username = models.CharField(max_length=32);
  5. password = models.CharField(max_length=64);

上面的类等到去数据库创建表的时候,表名是 “app01_userinfo” ,也就是 [app名]_[类名] 。

二、设置settings.py文件
在 INSTALLED_APPS 注册你的app,把你的app追加到这个列表里:

  1. INSTALLED_APPS = [
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8. 'app01.apps.AppConfig',
  9. ]

注:如果是在pycharm里面创建项目的时候创建的app,默认是已经加上了的;通过命令添加的,需要上面的操作:'app02.apps.AppConfig',

配置数据库连接,默认已经配置好了一个sqlite3,所以不需要修改:

  1. DATABASES = {
  2. 'default': {
  3. 'ENGINE': 'django.db.backends.sqlite3',
  4. 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
  5. }
  6. }

三、去终端执行2条命令

  1. python manage.py makemigrations
  2. python manage.py migrate

第一条命令会在 app 目录下的 migrations 目录下创建一个文件(0001_initial.py),记录我们对 models.py 所做的变动。
第二条命令是真正去操作数据库了,除了创建我们自己写的表以外,还创建了很多 django 自己的表。
上面两条命令都是作用于全局的,如果要限定作用于只在某个app,可以在最后加上app的名称:

  1. python manage.py makemigrations app01
  2. python manage.py migrate app01

关于SQLite:

SQLite是一种嵌入式数据库,它的数据库就是一个文件。由于SQLite本身是C写的,而且体积很小,所以,经常被集成到各种应用程序中,甚至在iOS和Android的App中都可以集成。
Python就内置了SQLite3,所以,在Python中使用SQLite,不需要安装任何东西,直接使用。

使用SQLite

安装Navicat Premium 可以连接上SQLite

1.在pycharm里面右键点击SQLite,然后点击 copy path

2.打开Navicat Premium  ,点击连接,选择SQlite,将C:\Users\ZYP\PycharmProjects\day19\db.sqlite3  复制到文件路径里面,给连接取个名字。用户名和密码不用填,点击连接

打开后,效果如下面截图

连接mysql

在settings里面设置如下:

  1. DATABASES = {
  2. 'default': {
  3. 'ENGINE': 'django.db.backends.mysql',
  4. 'NAME':'dbname',
  5. 'USER': 'root',
  6. 'PASSWORD': 'xxx',
  7. 'HOST': '',
  8. 'PORT': '',
  9. }
  10. }
  11. 1
  12. 2
  13. 3
  14. 4
  15. 5
  16. 6
  17.  
  18. # 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
  19.  
  20. # 如下设置放置的与project同名的配置的 __init__.py文件中
  21.  
  22. import pymysql
  23. pymysql.install_as_MySQLdb() 

注:上面的数据库名,使用mysql时,需要自己手动创建

数据的增删改查

ORM操作

先添加如下代码:

  1. #在APP01里面的urls.py里面
  2.  
  3. path("orm/", views.orm),
  4.  
  5. #views.py
  6. from app01 import models
  7.  
  8. def orm(request):
  9.  
  10. return HttpResponse("orm")

既然要操作数据库,这里肯定要导入models模块,表就用之前讲的userinfo

1.1添加数据,网页上输入http://127.0.0.1:8000/app01/orm/后,使用Navicat Premium 看下表里面的内容,此时已经添加了三条数据

  1. #添加数据
  2. for row in list:
        list = [
        {"username": "root", "password": "admin"},
        {"username": "admin", "password": "admin"},
        {"username": "user", "password": "123456"},
          ]
  3. models.Userinfo.objects.create(username=row['username'],password=row["password"])
  4. return HttpResponse("ORM")

1.2添加数据

  1. # 第二种方法
  2. obj = models.Userinfo(username="root",password="")
  3. obj.save()

1.3添加数据

  1. # 第三种方法
  2. dic = {"username": "root", "password": "admin"}
  3. models.Userinfo.objects.create(**dic)

2.查询数据

  1. #查询数据all.filter
  2. result = models.Userinfo.objects.all() #查询所有
  3. result = models.Userinfo.objects.filter(username="root").all() #while条件,查询指定的数据
  4. for i in result:
  5. print(i.id,i.username,i.password)

filter()里面还可以传入多个参数,就是多个条件,他们之间的关系是逻辑与(and)。

还有一个first()方法,取出第一个值,这样返回就不是列表而直接就是对象了。可以直接用,也可以用在filter()方法后面

  1. models.UserInfo.objects.first()
  2. models.UserInfo.objects.filter(username='root', password='').first()
  3. # 上面就是一个验证用户登录的逻辑了,返回结果是None或者是找到的第一个对象

QuerySet 对象,分别打印出查询结果和这个对象的query属性:

  1. res = models.UserInfo.objects.all()
  2. print(res) # 结果在下面
  3. # <QuerySet [<UserInfo: UserInfo object (1)>, <UserInfo: UserInfo object (2)>, <UserInfo: UserInfo object (3)>]>
  4. print(res.query) # 结果写下面
  5. # SELECT "cmdb_userinfo"."id", "cmdb_userinfo"."username", "cmdb_userinfo"."password" FROM "cmdb_userinfo

因此要看到对象的值,需要用for循环每个元素

3.删除数据

  1. #删数据 delete
  2. models.Userinfo.objects.filter(username="admin").delete()

4.修改数据

  1. #改数据update
  2. models.Userinfo.objects.filter(username="root").update(password = "")

后台管理实例

修改settings

  1. #settings中的设置
  2.  
  3. MIDDLEWARE = [
  4. 'django.middleware.security.SecurityMiddleware',
  5. 'django.contrib.sessions.middleware.SessionMiddleware',
  6. 'django.middleware.common.CommonMiddleware',
  7. #'django.middleware.csrf.CsrfViewMiddleware',
  8. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  9. 'django.contrib.messages.middleware.MessageMiddleware',
  10. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  11. ]
  12. 去掉注释的部分
  13.  
  14. 绑定mysql
  15.  
  16. DATABASES = {
  17. 'default': {
  18. 'ENGINE': 'django.db.backends.mysql',
  19. 'NAME':'testdb',
  20. 'USER': 'root',
  21. 'PASSWORD': 'root',
  22. 'HOST': '127.0.0.1',
  23. 'PORT': '',
  24. }
  25. }

在总urls里面导入include

  1. # 总urls.py
  2. from django.contrib import admin
  3. from django.urls import path
  4. from django.urls import include
  5. urlpatterns = [
  6. path('admin/', admin.site.urls),
  7. path('ORM/', include("ORM.urls")),
  8. ]
  9.  
  10. #orm中的urls
  11.  
  12. from django.urls import path,re_path
  13. from ORM import views
  14. urlpatterns = [
  15. path('login/', views.login),
  16. path('home/', views.home),
  17. path('user_info/', views.user_info),
  18. re_path('detail-(?P<nid>\d+)', views.detail),
  19. ]

mysql需要在项目名下的项目里面修改__init__

  1. import pymysql
  2.  
  3. pymysql.install_as_MySQLdb()

添加三个页面

  1. #login
  2.  
  3. <!DOCTYPE html>
  4. <html lang="en">
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>Title</title>
  8. </head>
  9. <body>
  10. <form action="/ORM/login/" method="post" enctype="multipart/form-data">
  11. <p>
  12. <input type="text" name="user" placeholder="用户名">
  13. </p>
  14. <p>
  15. <input type="password" name="pwd" placeholder="密码">
  16. </p>
  17. <p>
  18. <input type="submit" value="提交">
  19. <span style="color: red">{{ error_msg }}</span>
  20. </p>
  21.  
  22. </form>
  23. </body>
  24. </html>
  25.  
  26. #home
  27.  
  28. <!DOCTYPE html>
  29. <html lang="en">
  30. <head>
  31. <meta charset="UTF-8">
  32. <title>Title</title>
  33. <style>
  34. body{
  35. margin: 0 auto;
  36. }
  37. .head{
  38. height: 48px;
  39. background-color: #66c9f3;
  40. }
  41. .left{
  42. width: 200px;
  43. position: absolute;
  44. left: 0;
  45. top: 48px;
  46. bottom: 0;
  47. background-color: #dddddd;;
  48. }
  49. .menu{
  50. display: block;
  51. padding: 10px;
  52. }
  53. .right{
  54. background-color: #bce8f1;
  55. position: absolute;
  56. top: 48px;
  57. left: 200px;
  58. right: 0px;
  59. bottom: 0;
  60. }
  61. </style>
  62. </head>
  63. <body>
  64. <div class="head">后台管理系统</div>
  65. <div class="left">
  66. <a class="menu" href="/ORM/user_info/">用户管理</a>
  67. <a class="menu" href="/ORM/user_group/">用户组管理</a>
  68. </div>
  69. <div class="right"></div>
  70. </body>
  71. </html>
  72.  
  73. #user_info
  74.  
  75. <!DOCTYPE html>
  76. <html lang="en">
  77. <head>
  78. <meta charset="UTF-8">
  79. <title>Title</title>
  80. <style>
  81. body{
  82. margin: 0 auto;
  83. }
  84. .head{
  85. height: 48px;
  86. background-color: #66c9f3;
  87. }
  88. .left{
  89. width: 200px;
  90. position: absolute;
  91. left: 0;
  92. top: 48px;
  93. bottom: 0;
  94. background-color: #dddddd;;
  95. }
  96. .menu{
  97. display: block;
  98. padding: 10px;
  99. }
  100. .right{
  101. background-color: #bce8f1;
  102. position: absolute;
  103. top: 48px;
  104. left: 200px;
  105. right: 0px;
  106. bottom: 0;
  107. }
  108. </style>
  109. </head>
  110. <body>
  111. <div class="head">后台管理系统</div>
  112. <div class="left">
  113. <a class="menu" href="/ORM/user_info/">用户管理</a>
  114. <a class="menu" href="/ORM/user_group/">用户组管理</a>
  115. </div>
  116. <div class="right">
  117. <h3>用户列表</h3>
  118. <table border="1px">
  119. <thead>
  120. <tr>
  121. <th>ID</th>
  122. <th>用户名</th>
  123. </tr>
  124. {% for row in userlist%}
  125. <tr>
  126. <td><a href="/ORM/detail-{{row.id}}">{{row.id}}</a></td>
  127. <td>{{row.username}}</td>
  128. </tr>
  129. {% endfor %}
  130. </thead>
  131. </table>
  132. </div>
  133. </body>
  134. </html>
  135.  
  136. #detail
  137.  
  138. <!DOCTYPE html>
  139. <html lang="en">
  140. <head>
  141. <meta charset="UTF-8">
  142. <title>Title</title>
  143. <style>
  144. body{
  145. margin: 0 auto;
  146. }
  147. .head{
  148. height: 48px;
  149. background-color: #66c9f3;
  150. }
  151. .left{
  152. width: 200px;
  153. position: absolute;
  154. left: 0;
  155. top: 48px;
  156. bottom: 0;
  157. background-color: #dddddd;;
  158. }
  159. .menu{
  160. display: block;
  161. padding: 10px;
  162. }
  163. .right{
  164. background-color: #bce8f1;
  165. position: absolute;
  166. top: 48px;
  167. left: 200px;
  168. right: 0px;
  169. bottom: 0;
  170. }
  171. </style>
  172. </head>
  173. <body>
  174. <div class="head">后台管理系统</div>
  175. <div class="left">
  176. <a class="menu" href="/ORM/user_info/">用户管理</a>
  177. <a class="menu" href="/ORM/user_group/">用户组管理</a>
  178. </div>
  179. <div class="right">
  180. <h3>详细信息</h3>
  181. <h5>id:{{ user.id }}</h5>
  182. <h5>用户名:{{ user.username }}</h5>
  183. <h5>密码:{{ user.password }}</h5>
  184. </div>
  185. </body>
  186. </html>

models创建表

  1. from django.db import models
  2.  
  3. # Create your models here.
  4. class User(models.Model):
  5. username = models.CharField(max_length=16)
  6. password = models.CharField(max_length=32)

去终端执行2条命令

  1. python manage.py makemigrations
  2. python manage.py migrate

views主要代码:

  1. from django.shortcuts import render,HttpResponse,redirect
  2. from ORM import models
  3.  
  4. def initialized_db():
  5. USER = [
  6. {"username": "aaa", "password": ""},
  7. {"username": "bbb", "password": ""},
  8. {"username": "ccc", "password": ""},
  9. {"username": "ddd", "password": ""},
  10. ]
  11. find = models.User.objects.first()
  12. print("find",find)
  13. if find == None:
  14. for row in USER:
  15. models.User.objects.create(username =row["username"],password = row["password"])
  16. initialized_db()
  17.  
  18. def login(request):
  19. error_msg = ""
  20. if request.method == "GET":
  21. return render(request,"login.html")
  22. elif request.method == "POST":
  23. user = request.POST.get("user",None)
  24. pwd = request.POST.get("pwd",None)
  25. result = models.User.objects.filter(username = user,password = pwd).first()
  26. #print(result)
  27. if result:
  28. return redirect("/ORM/home/")
  29. else:
  30. error_msg = "用户名或密码错误"
  31. return render(request,"login.html",{"error_msg":error_msg})
  32. else:
  33. return redirect("/login/")
  34.  
  35. def home(request):
  36.  
  37. return render(request,"home.html")
  38.  
  39. def user_info(request):
  40. userlist = models.User.objects.all()
  41. #print(userlist.query) #打印出来的是select语句
  42. return render(request,"user_info.html",{"userlist":userlist})
  43.  
  44. def detail(request,nid):
  45. a = models.User.objects.filter(id=nid)
  46. user = models.User.objects.filter(id = nid).first() #这里要用first,否则就要用循环
  47. #print(type(a),type(user)) #<class 'django.db.models.query.QuerySet'> <class 'ORM.models.User'>
  48. return render(request,"detail.html",{"user":user})

 增加用户信息

在页面上添加单条用户信息,并立即显示在页面上

  1. #user_info 添加如下:
  2.  
  3. <h3>添加用户</h3>
  4. <form method="post" action="/ORM/user_info/">
  5. <input type="text" name = "user" placeholder="用户名" />
  6. <input type="password" name = "password" placeholder="密码" />
  7. <input type="submit" value="添加" />
  8. </form>
  9.  
  10. views.py 添加并修改如下:
  11.  
  12. def user_info(request):
  13. if request.method == "GET":
  14. userlist = models.User.objects.all()
  15. #print(userlist.query) #打印出来的是select语句
  16. return render(request,"user_info.html",{"userlist":userlist})
  17. else:
  18. if request.method == "POST":
  19. username = request.POST.get("user")
  20. password = request.POST.get("password")
  21. models.User.objects.create(username = username,password = password)
  22. return redirect("/ORM/user_info/")

删除用户信息

  1. 修改user_info.html
  2. #直接修改表格,也可以再添加一列来放删除
  3.  
  4. <tr>
  5. <td><a href="/ORM/detail-{{row.id}}">{{row.id}}</a></td>
  6. <td>{{row.username}} |
  7. <a href="/ORM/dele-{{row.id}}">删除</a>
  8. </td>
  9. </tr>
  10.  
  11. urls.py 添加如下:
  12.  
  13. re_path('dele-(?P<nid>\d+)', views.dele),
  14.  
  15. #views.py 添加如下
  16.  
  17. def dele(request,nid):
  18. models.User.objects.filter(id = nid).delete()
  19. return redirect("/ORM/user_info/")

修改用户信息

  1. #继承home页面后,并修改右侧内容为
  2.  
  3. <div class="right">
  4. <h3>编辑用户信息</h3>
  5. <form action="user_edit-{{obj.id}}.html" method="post">
  6. <input style="display: none" type="text" name="id" value="{{obj.id}}"/>
  7. <input type="text" name="username" value="{{obj.username}}"/>
  8. <input type="text" name="password" value="{{obj.password}}"/>
  9. <input type="submit" value="提交"/>
  10. </form>
  11. </div>
  12.  
  13. #urls.py
  14.  
  15. re_path('user_edit-(?P<nid>\d+)', views.user_edit),
  16.  
  17. #views.py
  18.  
  19. def user_edit(request,nid):
  20. if request.method == "GET":
  21. obj = models.User.objects.filter(id = nid).first()
  22. return render(request,"user_edit.html",{"obj":obj})
  23. else:
  24. if request.method == "POST":
  25. nid = request.POST.get("id")
  26. username = request.POST.get("username")
  27. password = request.POST.get("password")
  28. models.User.objects.filter(id = nid).update(username = username,password = password)
  29. return redirect("/ORM/user_info/")

注意:<form action="user_edit-{{obj.id}}.html" method="post">  这里的写法

ORM表结构

修改表结构

1.修改过表结构之后,需要再执行一下下面的2行命令,把新的表结构应用到数据库。

  1. python manage.py makemigrations
  2. python manage.py migrate

2.修改数据长度:当修改数据长度比之前长的没什么影响,但是修改后的数据长度比之前短,就会造成数据丢失

3.删除一列,重新执行命令就后自动删掉了,没什么特别的

4.增加一列:当增加一列

  1. # Create your models here.
  2. class User(models.Model):
  3. username = models.CharField(max_length=16)
  4. password = models.CharField(max_length=32)
  5. email = models.CharField(max_length=32)

  在终端执行第一条命令时,会提示,这是因为Django默认内容不能为空,这时你可以根据提示操作

  1.在终端输入字符串作为默认值,然后再输入第二条命令

  2.在新添加的一列后面添加null = True,此时表格新添加的一列就都可以为空了

    email = models.CharField(max_length=32,null=True)

5.数据类型

  基本数据类型:字符串,数字,时间,二进制

Django的ORM提供了非常多的字段类型,比如:EmailField、URLField、GenericIPAddressField。这些其实都是字符串类型而已,并且确实对我们没任何用(并不能帮我们做数据验证)。这些字段类型的只有在用Django的后台管理页面 admin 的时候才能发挥数据验证的效果。只有通过admin提交数据的时候才会验证你的数据格式是否正确。后面写怎么登录及哪里会显示格式错误

models对象的数据类型

  1. AutoField(Field)
  2. - int自增列,必须填入参数 primary_key=True
  3.  
  4. BigAutoField(AutoField)
  5. - bigint自增列,必须填入参数 primary_key=True
  6.  
  7. 注:当model中如果没有自增列,则自动会创建一个列名为id的列
  8. from django.db import models
  9.  
  10. class UserInfo(models.Model):
  11. # 自动创建一个列名为id的且为自增的整数列
  12. username = models.CharField(max_length=32)
  13.  
  14. class Group(models.Model):
  15. # 自定义自增列
  16. nid = models.AutoField(primary_key=True)
  17. name = models.CharField(max_length=32)
  18.  
  19. SmallIntegerField(IntegerField):
  20. - 小整数 -32768 32767
  21.  
  22. PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
  23. - 正小整数 0 32767
  24. IntegerField(Field)
  25. - 整数列(有符号的) -2147483648 2147483647
  26.  
  27. PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
  28. - 正整数 0 2147483647
  29.  
  30. BigIntegerField(IntegerField):
  31. - 长整型(有符号的) -9223372036854775808 9223372036854775807
  32.  
  33. 自定义无符号整数字段
  34.  
  35. class UnsignedIntegerField(models.IntegerField):
  36. def db_type(self, connection):
  37. return 'integer UNSIGNED'
  38.  
  39. PS: 返回值为字段在数据库中的属性,Django字段默认的值为:
  40. 'AutoField': 'integer AUTO_INCREMENT',
  41. 'BigAutoField': 'bigint AUTO_INCREMENT',
  42. 'BinaryField': 'longblob',
  43. 'BooleanField': 'bool',
  44. 'CharField': 'varchar(%(max_length)s)',
  45. 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
  46. 'DateField': 'date',
  47. 'DateTimeField': 'datetime',
  48. 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
  49. 'DurationField': 'bigint',
  50. 'FileField': 'varchar(%(max_length)s)',
  51. 'FilePathField': 'varchar(%(max_length)s)',
  52. 'FloatField': 'double precision',
  53. 'IntegerField': 'integer',
  54. 'BigIntegerField': 'bigint',
  55. 'IPAddressField': 'char(15)',
  56. 'GenericIPAddressField': 'char(39)',
  57. 'NullBooleanField': 'bool',
  58. 'OneToOneField': 'integer',
  59. 'PositiveIntegerField': 'integer UNSIGNED',
  60. 'PositiveSmallIntegerField': 'smallint UNSIGNED',
  61. 'SlugField': 'varchar(%(max_length)s)',
  62. 'SmallIntegerField': 'smallint',
  63. 'TextField': 'longtext',
  64. 'TimeField': 'time',
  65. 'UUIDField': 'char(32)',
  66.  
  67. BooleanField(Field)
  68. - 布尔值类型
  69.  
  70. NullBooleanField(Field):
  71. - 可以为空的布尔值
  72.  
  73. CharField(Field)
  74. - 字符类型
  75. - 必须提供max_length参数, max_length表示字符长度
  76.  
  77. TextField(Field)
  78. - 文本类型
  79.  
  80. EmailField(CharField):
  81. - 字符串类型,Django Admin以及ModelForm中提供验证机制
  82.  
  83. GenericIPAddressField(Field)
  84. - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4Ipv6
  85. - 参数:
  86. protocol,用于指定Ipv4Ipv6 'both',"ipv4","ipv6"
  87. unpack_ipv4 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"
  88.  
  89. URLField(CharField)
  90. - 字符串类型,Django Admin以及ModelForm中提供验证 URL
  91.  
  92. SlugField(CharField)
  93. - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
  94.  
  95. CommaSeparatedIntegerField(CharField)
  96. - 字符串类型,格式必须为逗号分割的数字
  97.  
  98. UUIDField(Field)
  99. - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
  100.  
  101. FilePathField(Field)
  102. - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
  103. - 参数:
  104. path, 文件夹路径
  105. match=None, 正则匹配
  106. recursive=False, 递归下面的文件夹
  107. allow_files=True, 允许文件
  108. allow_folders=False, 允许文件夹
  109.  
  110. FileField(Field)
  111. - 字符串,路径保存在数据库,文件上传到指定目录
  112. - 参数:
  113. upload_to = "" 上传文件的保存路径
  114. storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
  115.  
  116. ImageField(FileField)
  117. - 字符串,路径保存在数据库,文件上传到指定目录
  118. - 参数:
  119. upload_to = "" 上传文件的保存路径
  120. storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
  121. width_field=None, 上传图片的高度保存的数据库字段名(字符串)
  122. height_field=None 上传图片的宽度保存的数据库字段名(字符串)
  123.  
  124. DateTimeField(DateField)
  125. - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]
  126.  
  127. DateField(DateTimeCheckMixin, Field)
  128. - 日期格式 YYYY-MM-DD
  129.  
  130. TimeField(DateTimeCheckMixin, Field)
  131. - 时间格式 HH:MM[:ss[.uuuuuu]]
  132.  
  133. DurationField(Field)
  134. - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型
  135.  
  136. FloatField(Field)
  137. - 浮点型
  138.  
  139. DecimalField(Field)
  140. - 10进制小数
  141. - 参数:
  142. max_digits,小数总长度
  143. decimal_places,小数位长度
  144.  
  145. BinaryField(Field)
  146. - 二进制类型

把主键拿出来说下

自增id,之前定义表结构的时候,省略了主键,让Django帮我创建了自增id。也可以自己定义主键和自增id:

  1. id = models.AutoField(primary_key=True),一定要加后面的 primary_key=True
  1. class User(models.Model):
  2. id = models.AutoField(primary_key=True) # 数据类型是自增,并且设为主键
  3. g = models.CharField(max_length=32)

6.字段的参数

  1. null 数据库中字段是否可以为空
  2. db_column 数据库中字段的列名
  3. db_tablespace
  4. default 数据库中字段的默认值
  5. primary_key 数据库中字段是否为主键
  6. db_index 数据库中字段是否可以建立索引
  7. unique 数据库中字段是否可以建立唯一索引
  8. unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引
  9. unique_for_month 数据库中字段【月】部分是否可以建立唯一索引
  10. unique_for_year 数据库中字段【年】部分是否可以建立唯一索引
  11.  
  12. verbose_name Admin中显示的字段名称
  13. blank Admin中是否允许用户输入为空
  14. editable Admin中是否可以编辑
  15. help_text Admin中该字段的提示信息
  16. choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
  17. 如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)
  18.  
  19. error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息;
  20. 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
  21. 如:{'null': "不能为空.", 'invalid': '格式错误'}
  22.  
  23. validators 自定义错误验证(列表类型),从而定制想要的验证规则
  24. from django.core.validators import RegexValidator
  25. from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
  26. MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
  27. 如:
  28. test = models.CharField(
  29. max_length=32,
  30. error_messages={
  31. 'c1': '优先错信息1',
  32. 'c2': '优先错信息2',
  33. 'c3': '优先错信息3',
  34. },
  35. validators=[
  36. RegexValidator(regex='root_\d+', message='错误了', code='c1'),
  37. RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
  38. EmailValidator(message='又错误了', code='c3'), ]
  39. )
  40.  
  41. 参数

db_column :数据库中字段的列名。默认列明就是我们的变量名,可以通过这个参数设置成不一样的  

  1. class UserInfo(models.Model):
  2. username = models.CharField(max_length=32) # 列名就是变量名 username
  3. password = models.CharField(max_length=64, db_column='pwd') # 数据库中的列名是 pwd

auto_now :自动生成一个当前时间,数据更新时(包括创建),注意更新数据的写法,和前面的不同
auto_now_add :自动生成一个当前时间,数据创建时

  1. class UserInfo(models.Model):
  2. # 用户注册时会生成用户名和密码
  3. username = models.CharField(max_length=32)
  4. password = models.CharField(max_length=64)
  5. # 创建记录时会生成当前时间存放在ctime里,这个就是用户的注册时间
  6. ctime = models.DateTimeField(auto_now_add=True)
  7. # 用户修改密码会更新uptime的时间,这个就是上次修改密码的时间
  8. uptime = models.DateTimeField(auto_now=True)
  9.  
  10. #创建数据
  1. # models.UserInfo.objects.filter(id=nid).update(password='1234') 这种方法更新是不会刷新 auto_now 的时间的
  2. # 用save()方法更新可以刷新 auto_now 的时间
  3. # obj = models.UserInfo.objects.filter(id=nid).first()
  4. # obj.password = '4321'
  5. # obj.save()

choices :Admin中显示选择框的内容。(用不变动的数据放在内存中从而避免连表操作,连表操作会涉及到性能问题)

  1. class UserInfo(models.Model):
  2. username = models.CharField(max_length=32)
  3. password = models.CharField(max_length=64)
  4. # 用户有各种类型
  5. user_type_choices = (
  6. (1, '管理员')
  7. (2, '普通用户')
  8. (3, '访客')
  9. )
  10. # 定义一个用户类型的字段
  11. user_type_id = models.IntegerField(choices=user_type_choices, default=2)
  12. # 这样数据库里是一个整数类型,值是1、2、3。使用字段名取值 obj.user_type_id 获取到的是数值
  13. # 如果要获取后面的内容,使用 get_FOO_display() 方法, 即 obj.get_user_type_id_display()
  14. # 但是我们在admin里看选择框的时候看到的是“管理员”、“普通用户”、“访客”,这就是因为把选项所对应的内容放到了内存中了
  15. # 有了Django这个功能就不用再搞一张表,存放各个数值对应的内容了,还要做外键关联,用的时候还要连表查询
  16. # 即使不用admin,我们也可以在自己的代码里读取这个属性获取到内容,避免连表查询

error_messages :自定义错误信息(字典类型)。字典key:null、blank、invalid、invalid_choice、unique、unique_for_date

  1. class UserInfo(models.Model):
  2. username = models.CharField(max_length=32)
  3. password = models.CharField(max_length=64, error_messages={'null': "不能为空", 'invalid': '格式错误'})

help_text :Admin中该字段的提示信息。默认没有提示信息,设置后会显示在input框的下方

外键操作

一对多

创建外键关联-修改表结构

  1. usergroup = models.ForeignKey(User_Group,on_delete=models.CASCADE,default=1)
  1. ForeignKey创建外键

第一次创建的时候,我没有添加on_delete=models.CASCADE

在使用python manage.py makeigrations 进行迁移的时候的出错了,报错如下:

经过筛查,在创建多对一的关系的,需要在Foreign的第二参数中加入on_delete=models.CASCADE  主外关系键中,级联删除,也就是当删除主表的数据时候从表中的数据也随着一起删除

  1. on_delete=models.CASCADE
  1. default=1 设置外键默认值

外键关系创建完后,在user表里面会生成一列usergroup_id,并且生成了一个usergroup类

此时要查询usergroup表中的内容,在html中可以使用 {{row.usergroup.dept}},row为views传过来的user表中所有对象

通过对象获取部门

Django基础--2的更多相关文章

  1. Python之路-(js正则表达式、前端页面的模板套用、Django基础)

    js正则表达式 前端页面的模板套用 Django基础 js正则表达式: 1.定义正则表达式 /.../  用于定义正则表达式 /.../g 表示全局匹配 /.../i 表示不区分大小写 /.../m ...

  2. Django 基础教程

    Django 基础教程 这是第一篇 Django 简介 »  Django 是由 Python 开发的一个免费的开源网站框架,可以用于快速搭建高性能,优雅的网站! 你一定可以学会,Django 很简单 ...

  3. python的django基础篇

    一.Django基础 Django 是用Python开发的一个免费开源的Web框架,可以用于快速搭建高性能,优雅的网站! Django的特点: 强大的数据库功能:拥有强大的数据库操作接口(QueryS ...

  4. Python学习(二十六)—— Django基础一

    转载自:http://www.cnblogs.com/liwenzhou/p/8258992.html 一.Web框架本质 我们可以这样理解:所有的Web应用本质上就是一个socket服务端,而用户的 ...

  5. Django基础(一)

    Django基础(一) 知识预览 Django基本命令 二 路由配置系统(URLconf) 三 编写视图 四 Template 五 数据库与ORM admin的配置 一 什么是web框架? 框架,即f ...

  6. python3之Django基础篇

    一.Django基础 Django 是用Python开发的一个免费开源的Web框架,可以用于快速搭建高性能,优雅的网站! Django的特点: 强大的数据库功能:拥有强大的数据库操作接口(QueryS ...

  7. DJango 基础 (1)

    django基础 知识点: 基本认知 工具准备 新建项目 目录及文件说明 开发服务器 创建视图函数 新建应用(app) 1.基本认知 Django是用Python开发的一个免费开源的Web框架,可以用 ...

  8. Django基础和基本使用

    Django基础 Django是Python下的一款著名的Web框架 框架 任何语言进入到高级部分时,会有认证.session.http.连接数据库等等功能操作,没有框架时需要自己实现 框架 是整个或 ...

  9. {Django基础十之Form和ModelForm组件}一 Form介绍 二 Form常用字段和插件 三 From所有内置字段 四 字段校验 五 Hook钩子方法 六 进阶补充 七 ModelForm

    Django基础十之Form和ModelForm组件 本节目录 一 Form介绍 二 Form常用字段和插件 三 From所有内置字段 四 字段校验 五 Hook钩子方法 六 进阶补充 七 Model ...

  10. {Django基础九之中间件} 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证

    Django基础九之中间件 本节目录 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证 六 xxx 七 xxx 八 xxx 一 前戏 我们在前面的课程中已经学会了 ...

随机推荐

  1. 利用JPanel和JLabel设置背景图片

    //创建面板1,放置背景图片1 JPanel jPanelTop=new JPanel(); jPanelTop.setBounds(,-,,); //x=0,y=-5用来设置面板距离窗体左上角的距离 ...

  2. HTML5拖拽——将本地文件拖拽到网页中显示

    HTML5标准中的提供的用于文件输入输出(I/O)的对象 File: 代表一个文件对象 FileList: 代表一个文件列表,类数组对象 FileReader 用于从文件中提取内容 FileWrite ...

  3. 读经典——《CLR via C#》(Jeffrey Richter著) 笔记_类型的各种成员

    [Class中,可能包含的成员] 常量, 字段, 实例构造器, 类型构造器, 方法, 操作符重载, 转换操作符, 属性, 事件, 类型(Class)

  4. PAT - 1067 试密码 (20 分)

    当你试图登录某个系统却忘了密码时,系统一般只会允许你尝试有限多次,当超出允许次数时,账号就会被锁死.本题就请你实现这个小功能. 输入格式: 输入在第一行给出一个密码(长度不超过 20 的.不包含空格. ...

  5. UVALive 3645 时序模型

    按航班拆点 注意返边的条件 #include<bits/stdc++.h> using namespace std; const int maxn = 1e6+11; const int ...

  6. 求js数组的最大值和最小值

    数组 ,,,,,,,,,]; 方法1 - 字符串拼接法 利用toString或join把数组转换为字符串,再和Math的max和min方法分别进行拼接,最后执行eval方法 var max = eva ...

  7. 01-消息中间件概述和ActiveMq入门

    1.mq解决的问题 系统异步处理 应用解耦 流量削峰 日志处理 消息通信 2.消息中间件的2中模型 2.1 Point-to-Point(P2P) / 点对点 / 类比:送快递 特点: + 一个消费生 ...

  8. ArrayList代码分析

    集合算是java中最常用的部分了,阅读该部分jdk代码可以让我们更加清楚的了解其实现原理,在使用时也能心中有数,有利于写出高质量的代码. ArrayList 底层数组实现,初始长度10,超过长度后的自 ...

  9. B树和B+树对比,为什么MySQL数据库索引选择使用B+树?

    一 基础知识 二叉树 根节点,第一层的节点 叶子节点,没有子节点的节点. 非叶子节点,有子节点的节点,根节点也是非叶子节点. B树 B树的节点为关键字和相应的数据(索引等) B+树 B+树是B树的一个 ...

  10. [Eclipse]自动注释功能

    1) 新建一个file时,加上一些注释的方法. window->preference->java->code     styple->code     template 当你选 ...