Django基础

本节内容:

    1、什么是web框架(web应用程序)

    2、Django介绍

    3、Django在PyCharm下的创建

    4、Django的工作流程

    5、Djang的四个重点

 

 

一、web框架

 

       web(World Wide Web)即全球广域网,也称为万维网,它是基于超文本和HTTP的、全球性的、动态交互的、跨平台分布式图形信息系统。是建立在lnternet上的一种网络服务,为浏览者在lnternet上查找和浏览信息提供图形化得、易于访问的直观界面,其中的文档及超级链接lnternet上的节点,组织成一个互为关联的网状结构。(百度搜索

 web的本意是蜘蛛网和网的意思,在网页设计中我们称为网页的意思。现广泛译作网络、互联网等技术领域。表现为三种形式,即超文本(hypertext)、超媒体(hypermedia)、超文本传输协议(HTTP)等。
一、超文本(hypertext)
超文本是一种用户接口方式,用以显示文本及与文本相关的内容。现时超文本普遍以电子文档的方式存在,其中的文字包含有可以链接到其他字段或者文档的超文本链接,允许从当前阅读位置直接切换到超文本链接所指向的文字。
超媒体室内效果图大课堂
超文本的格式有很多,最常使用的是超文本标记语言(标准通用标记语言下的一个应用)及富文本格式(RTF)。我们日常浏览的网页都属于超文本。
超文本链接一种全局性的信息结构,它将文档中的不同部分通过关键字建立链接,使信息得以用交互方式搜索。
二、超媒体(hypermedia)
超媒体是超文本(hypertext)和多媒体在信息浏览环境下的结合。它是超级媒体的简称。用户不仅能从一个文本跳到另一个文本,而且可以激活一段声音,显示一个图形,甚至可以播放一段动画。
Internet采用超文本和超媒体的信息组织方式,将信息的链接扩展到整个Internet上。Web就是一种超文本信息系统,Web的一个主要的概念就是超文本链接。它使得文本不再像一本书一样是固定的线性的,而是可以从一个位置跳到另外的位置并从中获取更多的信息,还可以转到别的主题上。想要了解某一个主题的内容只要在这个主题上点一下,就可以跳转到包含这一主题的文档上。正是这种多连接性把它称为Web。
三、超文本传输协议(HTTP)HyperText Transfer Protocol超文本在互联网上的传输协议。

    框架:特指为解决一个开放性问题(需求不一样)而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演。

  对于web的应运:,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

  web应运流程:

//首先浏览器发送一个HTTP请求(里面是有很多内容的,请求头和请求体)

//服务器接收到这个请求,生成一个HTML文档。

//服务器要把这个HTML文档,作为HTTP的响应体发送给浏览器(还有个响应头,这里没有体现这个过程)

//最后一步是浏览器当收到HTTP这个响应体之后,渲染一下,把这个页面(HTML文档)给用户展示


//这个过程中漏掉的是HTTP协议下的解析和设定过程(这个过程,自己写是完全没有问题的,前提是你得会 HTTP规范,这个工作是相当繁杂的)这个接口就是WSGI (Web Server Gateway Interface。)

Web 服务器
Gateway网关
Interface接口
View Code

 

 

 

二、Django介绍

 

     Django是一个开放源代码的Web应运框架,由Python写成。采用MTV框架模式,即模型M、T模板、视图V。

   Model(模型):负责业务对象与数据库的对象(ORM)s

       Template(模版):负责如何把页面展示给用户

       View(视图):负责业务逻辑,并在适当的时候调用Model和Template

  Django是一个Web框架——一套用于帮助开发交互式网站的工具。Django能够响应网页请求,还能让你轻松 的读写数据库、管理用户等。

  他最初是被开发,用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站。并与2005年7月在BSD许可证下发布。

这套框架是以比利时的吉普赛爵士吉他手Django Reinhardt来命名的。

此外,Django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template

 

 

 

 

 三、Django在PyCharm下的创建(可以在终端安装创建,但是步骤比较多)

 

第一步

 

第二部

 

 

 第三步

 

 

 第四步(第一个文件名字就比如是微信,是一个总的 。第二个文件名就相当于,微信下的其他功能,聊天,支付,朋友圈,他们是各自独立的,都有各自独立的功能,各自的执行语句。但是都是属于微信的app)

 

 文件的名字介绍

 

 

四、Django的工作流程(简单的介绍,后面会详细的编写)

简单的介绍一下这些文件 都是干什么的(和上面那张图对应一下)

 

 

图片的页面是引入 静态文件 方法

 

 

1,创建URL

 

 2、写视图函数(视图函数和html文档不在一个文件夹下为什么可以读到:jango已经把路径写好了,写在settings配置文件里面,他是jango运行首先要做的一件事情,会把所有的配置读到自己脑子里面)

3、显示页面的HTML文档(form后面的login.html意思就是交给这个URL去处理,把里面的那些值。都封装到对应URL的视图函数参数里了)

 

 4、启动

 

5,链接

 

 

 

 

五、Django、四个重点(四个圈起来的)

 

 

 

 

 

 

 一、Django(URL匹配相对应的函数)

 

  URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。

urlpatterns = [
    path( 'URL路径(正则表达式)' , views视图函数,参数,别名),
]

#在Django2.0以后 URL换成了path,里面原先的正则表达式,换成直接单引号里面的写就行,开头不用加^    结尾不用加$ 

参数说明:

  • 一个正则表达式字符串
  • 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
  • 可选的要传递给视图函数的默认参数(字典形式)
  • 一个可选的name参数

 

上面那种是FBV        URL——》def函数

也可以通过类来实现  CBV 

        URL——》类

 

类的得这么写   
 path('login.html/',views.Login.as_view()),

  

#     先引入views
from django import views

# 继承里面方法
class Login(views.View):
    #如果是get请求走这个函数 
    def get(self,requese, *args, **kwargs):
       return render(requese, 'login.html',{'msg':''})

    # 如果是post请求经过一些验证走这个
    def post(self,request,*args,**kwargs):
        user = request.POST.get('user')
        pwd = request.POST.get('pwd')
        c = models.Administrator.objects.filter(username=user, password=pwd,).count()
        if c:
            request.session['is_login'] = True
            request.session['username'] = user
            rep = redirect('/index.html')
            return rep
        else:
            message = "用户名或密码错误"
            return render(request, "login.html", {'msg': message})
类的实现方法

 

类的这种 先知道一下

 

 

路由分发后blog下的url

 

 简单的写完URL后就可以写视图函数了,(URL视图函数后面可以加name=名字,为的是以后假如,URL index想换名字了,他一换,前端有关这个全得跟着改,以及一系列的操作,就相当于起一个别名,以后主名改成什么,我都可以通过这个别名找到这个URL)form表单提交是时候 {% url "别名"%}

 

 

 

 

 

二,Django Views(视图函数)

http请求中产生两个核心对象:

        http请求:HttpRequest对象

        http响应:HttpResponse对象

所在位置:django.http

之前我们用到的参数request就是HttpRequest (就是函数后面,括号里面加的参数)

 

 

 

简单的几个方法

1、HttpRequest对象的属性和方法:

 

# path:       请求页面的全路径,不包括域名
#
# method:     请求中使用的HTTP方法的字符串表示。全大写表示。例如
#
#                    if  req.method=="GET":
#
#                              do_something()
#
#                    elseif req.method=="POST":
#
#                              do_something_else()
#
# GET:         包含所有HTTP GET参数的类字典对象
#
# POST:       包含所有HTTP POST参数的类字典对象
#
#              服务器收到空的POST请求的情况也是可能发生的,也就是说,表单form通过
#              HTTP POST方法提交请求,但是表单中可能没有数据,因此不能使用
#              if req.POST来判断是否使用了HTTP POST 方法;应该使用  if req.method=="POST"
View Code

 

2 HttpResponse对象:

 

  对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建。每个view请求处理方法必须返回一个HttpResponse对象,必须是字符串。

 

  HttpResponse类在django.http.HttpResponse

 

  在HttpResponse对象上扩展的常用方法:

页面渲染:         render()(推荐)<br>                 render_to_response(),
页面跳转:         redirect("路径")
locals():    可以直接将函数中所有的变量传给模板

  

 

实例

 

登录页面login.html

 补充

-----------------------------------url.py

 path("login",   views.login),
 path("kuan_back",   views.kuan_back),

-----------------------------------views.py
def login(req):
    if req.method=="POST":
        if 1:
            # return redirect("/kuan_back/")
            name="wangkuan"

            return render(req,"my backend.html",locals())

    return render(req,"login.html",locals())


def kuan_back(req):

    name="王宽"

    return render(req,"my backend.html",locals())

-----------------------------------login.html

<form action="/login/" method="post">
    <p>姓名<input type="text" name="username"></p>
    <p>性别<input type="text" name="sex"></p>
    <p>邮箱<input type="text" name="email"></p>
    <p><input type="submit" value="submit"></p>
</form>
-----------------------------------my backend.html
<h1>用户{{ name }}你好</h1>

#总结: render和redirect的区别:
#   1 if render的页面需要模板语言渲染,需要的将数据库的数据加载到html,那么所有的这一部分
#     除了写在kuan_back的视图函数中,必须还要写在login中,代码重复,没有解耦.

#   2 the most important: url没有跳转到/kuan_back/,而是还在/login/,所以当刷新后
#     又得重新登录.
View Code

 

 

 

 

                    三、Template 基础

 

 

 什么是模板语言:

    HTML + 逻辑控制语句

 

为什么叫模板 ,不叫HTML文件

  因为里面有逻辑控制代码,如果没有,就是单纯的HTML文件(里面有了控制的内容,控制的变量,控制的语句在了,他就是一个模板)

 

 

作用:

  前端,后端的纽带作用(中间的过度过程,后端的一些内容,要显示到前端,通过一些固定的语法)

 

 

 

1,模板语句 :{{变量}}

  后端获取当前时间,用一个变量接收,然后再把当前获取的时间传递给前端输出

----------------------------urls.py
path("current_time",views.current_time)


----------------------------views.py

def current_time(req):

    now=datetime.datetime.now()

    return render(req,'current_time.html'{'current_date':now})


-----------------------------current_time.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1>当前时间{{ current_date }}</h1>

</body>
</html>
{{变量}}
return render(req, 'current_datetime.html', {'current_date':now})
render 是方法

req 是请求对象
'current_datetime.html'    是模板
{'current_date':now}      是上下文

 

 

 

 

 

2、深度的变量查找---------万能的句点号(.)

  在 Django 模板中遍历复杂数据结构的关键是句点字符 (.)。

    

 

  根据列表的索引取值

 

   HTML 里  . 2 就是取 索引位置第2个

  浏览器

 

  

 

 

 

字典的形式

 

根据  .  键取值  

 

浏览器输出

 

 

 

 

 

输出当前时间

 

看还有时间两个属性

 

 

 

 

自己创建一个

HTML

浏览器输出

 

 

 

 

 

 

 

3、-------  {% if %}的使用  

{% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的布尔值,系统则会显示{% if %}和{% endif %}间的所有内容

结果

 

加elif 

结果

 

 例如:

 

 

 

4,--------------------{%for%}的使用

{% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容

{%for i in obj%}

  循环列表

      HTML

 

 输出

 

取索引值

对应的就输出了

 

取字点的键

 

不加 0 就从1 开始

 结果

 取值,对象  .  键 就行

 

 

 

5、-------变量的过滤器(filter)的使用

 

语法格式:      {{obj|filter:param}}

 

  

 1  add          :   给变量加上相应的值
   #
   # 2  addslashes   :    给变量中的引号前加上斜线
   #
   # 3  capfirst     :    首字母大写
   #
   # 4  cut          :   从字符串中移除指定的字符
   #
   # 5  date         :   格式化日期字符串
   #
   # 6  default      :   如果值是False,就替换成设置的默认值,否则就是用本来的值
   #
   # 7  default_if_none:  如果值是None,就替换成设置的默认值,否则就使用本来的值


#value2=5
{{ value2|add:3 }}<br>


#value3='he  llo wo r ld'
{{ value3|cut:' ' }}<br>
#把中间空格全去了


#import datetime
#value4=datetime.datetime.now()
{{ value4|date:'Y-m-d' }}<br>
#获取时间 中间用- 隔开


#value5=[]
{{ value5|default:'空的' }}<br>
#如果value 是空的 就显示中文空的






#value6='<a href="#">跳转</a>'

{"obj":value6 }

{% autoescape off %}
  {{ obj }}
{% endautoescape %}

#如果你在后端写了HTML 格式的 前端是不认识的 ,然后申明一下 安全的
#可以进行渲染

^^^^^^^^下面简单方法
{{ obj|safe }}
#这个和上面的结果是一样的
#如果你在后端写了HTML 格式的 前端是不认识的 ,然后申明一下 安全的
#可以进行渲染






#value7='1234'
{{ value7|filesizeformat }}

#查看数据大小占有量,  多少KB

{{ value7|length }}
#长度

{{ value7|slice:":-1" }}
#切片 拿到 1  2  3



#value8='http://www.baidu.com/?a=1&b=3'
{{ value8|urlencode }}
#编码 看到的就不是明文了  后面的



value9='hello I am kuan'

{{value9|truncatechars:'6'}}
#结果是hello I 按字符截最后六个
{{value9|truncatewords:'2'}}
#结果是hel按单词截 最后两个
方法

 

6,

------{%csrf_token%}:csrf_token标签

     用于生成csrf_token的标签,用于防治跨站攻击验证。注意如果你在view的index里用的是render_to_response方法,加了也不会生效

     其实,这里是会生成一个input标签,和其他表单标签一起提交给后台的。(form表单提交数据,不加这个 禁止提交的,类似于一个通行证的东西,)

7,------{% url %}:  引用路由配置的地址

#写完URL   视图函数,后面可以加name=别名 万一URL改名字了 这也不用改 依然可以找到

<form action="{% url "别名"%}" >
          <input type="text">
          <input type="submit"value="提交">
          {%csrf_token%}
</form>
别名

8、------{% verbatim %}: 禁止render ,视图函数里的render不进行渲染了

{% verbatim %}
         {{ hello }}
{% endverbatim %}
#页面显示的还是{{ hello }}

 

 

9、自定义filter和simple_tag

------a、在app中创建templatetags模块(必须的)

------b、创建任意 .py 文件,如:my_tags.py 

  ----------(filter参数不能超两个)

from django import template
from django.utils.safestring import mark_safe

register = template.Library()   #register的名字是固定的,不可改变


@register.filter
def filter_multi(v1,v2):
    return  v1 * v2
filter
from django import template
from django.utils.safestring import mark_safe

register = template.Library()   #register的名字是固定的,不可改变



@register.simple_tag
def simple_tag_multi(v1,v2):
    return  v1 * v2
simple_tag

 

------c、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}

------d、使用simple_tag和filter(如何调用)

-------------------------------.html
{% load xxx %}   #首行
    
    
    
    
 # num=12
{{ num|filter_multi:2 }} #24
filter
{% simple_tag_multi 2 5 %}  参数不限,但不能放在if for语句中
simple_tag

 

------e、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.

 

 

 

10、模板继承 extend

  模板继承简单来讲,比如博客园,外面的框架,都是一样只有里面的内容是,每次都不一样的,按我们之前的方法,每一个页面跳转都得写一个HTML,这样就造成了大量的重复,然而我们只需要写好一个大体的HTML(重复的地方我们只写好一个HTML)不重复的地方我们写上一个盒子,

  以后要是写HTML就需要把这个盒子调用一下,里面写不同的内容就可以了(不用每次HTML都去写重复的css,设计一样的长宽高,)

 

 本质上来说,模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载。

举例 ,商城我们登录成功以后,可以看到订单,购物车,外面的框架是一样的,只有购物车,订单里面的内容不一样

from django.contrib import admin
from django.urls import path,include
from blog import views
urlpatterns = [
    path('admin/', admin.site.urls),
#订单路由
    path("ordered/",views.ordered),
#购物车路由
    path("shopping_car/",views.shopping_car),
]
URL
def ordered(req):

    return render(req,"ordered.html")


def shopping_car(req):

    return render(req,"shopping_car.html")
对应的视图函数
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .page-header{
            height: 50px;
            background-color: rebeccapurple;
        }
        .page-body .menu{
           height: 500px;
            background-color: antiquewhite;
            float: left;
            width: 20%;
        }
        .page-body .content{
            height: 500px;
            background-color: cornflowerblue;
            float: left;
            width: 80%;
        }
        .page-footer{
            height: 30px;
            background-color: darkcyan;
            clear:both;
        }
    </style>



</head>
<body>

<div>
    <div class="page-header"></div>
    <div class="page-body">
        <div class="menu">
            <a href="/ordered/">订单</a><br>
            <a href="/shopping_car/">购物车</a>
        </div>
        
{#        这就是盒子  名字自己定义,但是不能重复#}
        {% block abc %}
        
        {% endblock %}


    </div>
    <div class="page-footer"></div>
</div>
总的HTML框架 base.html
{% extends "base.html" %}
{#必须写在第一行,要引入总框架#}

{% block abc %}
    <div class="content">
        订单2
    </div>
{% endblock %}
订单的HTML
{% extends "base.html" %}
{#必须写在第一行,引入总的框架#}

{% block abc %}
    <div class="content">
        购物车2
    </div>
{% endblock %}
购物车HTML

  以下是其工作方式:

      在加载 订单.html 模板时,模板引擎发现了 {% extends %} 标签, 注意到该模板是一个子模板。 模板引擎立即装载其父模板,即本例中的 base.html 。此时,模板引擎注意到 base.html 中的一个 {% block %} 标签(可以是多个),并用子模板的内容替换这些 block 。因此,引擎将会使用我们在 block abc %} 中定义的标题, 所以,网页标题一块将由{% block abc %}替换。

  这个方法可最大限度地重用代码,并使得向公共区域(如区域级的导航)添加内容成为一件轻松的工作。

以下是使用模板继承的一些诀窍:

<1>如果在模板中使用 {% extends %} ,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作用。

 <2>一般来说,基础模板中的 {% block %} 标签越多越好。 记住,子模板不必定义父模板中所有的代码块,因此
    你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义。 俗话说,钩子越
    多越好。

 <3>如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个 {% block %} 中。
    如果你需要访问父模板中的块的内容,使用 {{ block.super }}这个标签吧,这一个魔法变量将会表现出父模
    板中的内容。 如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了。

 <4>不允许在同一个模板中定义多个同名的 {% block %} 。 存在这样的限制是因为block 标签的工作方式是双向的。
    也就是说,block 标签不仅挖了一个要填的坑,也定义了在父模板中这个坑所填充的内容。如果模板中出现了两个
    相同名称的 {% block %} 标签,父模板将无从得知要使用哪个块的内容。
诀窍

 

 

 

 

 

四,Models

 

models的作用是定义出对象的模型,一般都是和数据库里表对应,一个表一个models类,表里的字段对应的models类的属性

 

ORM(对象关系映射)

用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作

优点: 1 ORM使得我们的通用数据库交互变得简单易行,而且完全不用考虑该死的SQL语句。快速开发,由此而来。

          2 可以避免一些新手程序猿写sql语句带来的性能问题。

 

 下面要开始Django ORM语法

创建表:单表

              关联表 :(一对一)(一对多{重点})(多对多{重点})

 操作表:

    (增、删、改、查){重点}

怎样在Pycharm里生成数据库表,在Django的models.py里写

简单看一下格式(下面会仔细介绍)

 多对多还可以重新自己建立个表,通过两个字段和两个表建立外键来实现多对多

 __str__方法

 

这个方法的目的是,当返回打印对象的时候,不要显示一堆内存地址,(看不懂它是什么)我是想打印出来跟他实例相关的一些信息,一打印我就知道它是谁。

 

#然后下面打开终端执行
python manage.py makemigrations
python manage.py migrate

#执行完这两句 数据库表生成

  

 

常用的字段类型参数

<1> CharField
        #字符串字段, 用于较短的字符串.
        #CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.

<2> IntegerField
       #用于保存一个整数.

<3> FloatField
        # 一个浮点数. 必须 提供两个参数:
        #
        # 参数    描述
        # max_digits    总位数(不包括小数点和符号)
        # decimal_places    小数位数
                # 举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
                #
                # models.FloatField(..., max_digits=5, decimal_places=2)
                # 要保存最大值一百万(小数点后保存10位)的话,你要这样定义:
                #
                # models.FloatField(..., max_digits=19, decimal_places=10)
                # admin 用一个文本框(<input type="text">)表示该字段保存的数据.

<4> AutoField
        # 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 
        # 自定义一个主键:my_id=models.AutoField(primary_key=True)
        # 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.

<5> BooleanField
        # A true/false field. admin 用 checkbox 来表示此类字段.

<6> TextField
        # 一个容量很大的文本字段.
        # admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).

<7> EmailField
        # 一个带有检查Email合法性的 CharField,不接受 maxlength 参数.

<8> DateField
        # 一个日期字段. 共有下列额外的可选参数:
        # Argument    描述
        # auto_now    当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.
        # auto_now_add    当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
        #(仅仅在admin中有意义...)

<9> DateTimeField
        #  一个日期时间字段. 类似 DateField 支持同样的附加选项.

<10> ImageField
        # 类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
        # 如果提供这两个参数,则图片将按提供的高度和宽度规格保存.     
<11> FileField
     # 一个文件上传字段.
     #要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting, 
     #该格式将被上载文件的 date/time 
     #替换(so that uploaded files don't fill up the given directory).
     # admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .

     #注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
            #(1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件. 
            # (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对 
            #  WEB服务器用户帐号是可写的.
            #(2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
            # 使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT). 
            # 出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField 
            # 叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.

<12> URLField
      # 用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且
      # 没有返回404响应).
      # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)

<13> NullBooleanField
       # 类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
       # admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据.

<14> SlugField
       # "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs
       # 若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50.  #在
       # 以前的 Django 版本,没有任何办法改变50 这个长度.
       # 这暗示了 db_index=True.
       # 它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate 
       # the slug, via JavaScript,in the object's admin form: models.SlugField
       # (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields.

<13> XMLField
        #一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.

<14> FilePathField
        # 可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.
        # 参数    描述
        # path    必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目. 
        # Example: "/home/images".
        # match    可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名.  
        # 注意这个正则表达式只会应用到 base filename 而不是
        # 路径全名. Example: "foo.*\.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
        # recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
        # 这三个参数可以同时使用.
        # match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:
        # FilePathField(path="/home/images", match="foo.*", recursive=True)
        # ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif

<15> IPAddressField
        # 一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
<16># CommaSeparatedIntegerField
        # 用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.
参数
    <1> null : 数据库中字段是否可以为空

    <2> blank: django的 Admin 中添加数据时是否可允许空值

    <3> default:设定缺省值

    <4> editable:如果为假,admin模式下将不能改写。缺省为真

    <5> primary_key:设置主键,如果没有设置django创建表时会自动加上:
        id = meta.AutoField('ID', primary_key=True)
        primary_key=True implies blank=False, null=False and unique=True. Only one
        primary key is allowed on an object.

    <6> unique:数据唯一

    <7> verbose_name  Admin中字段的显示名称

    <8> validator_list:有效性检查。非有效产生 django.core.validators.ValidationError 错误


    <9> db_column,db_index 如果为真将为此字段创建索引

    <10>choices:一个用来选择值的2维元组。第一个值是实际存储的值,第二个用来方便进行选择。
                如SEX_CHOICES= (( ‘F’,'Female’),(‘M’,'Male’),)
                gender = models.CharField(max_length=2,choices = SEX_CHOICES)
Field重要参数

分析代码:

       <1>  每个数据模型都是django.db.models.Model的子类,它的父类Model包含了所有必要的和数据库交互的方法。并提供了一个简介漂亮的定义数据库字段的语法。

       <2>  每个模型相当于单个数据库表(多对多关系例外,会多生成一张关系表),每个属性也是这个表中的字段。属性名就是字段名,它的类型(例如CharField)相当于数据库的字段类型(例如varchar)。大家可以留意下其它的类型都和数据库里的什么字段对应。

       <3>  模型之间的三种关系:一对一,一对多,多对多。

             一对一:实质就是在主外键(author_id就是foreign key)的关系基础上,给外键加了一个UNIQUE=True的属性;(不能再重复)

             一对多:就是主外键关系;(foreign key)

             多对多:(ManyToManyField) 自动创建第三张表(当然我们也可以自己创建第三张表:两个foreign key)

 

增、删、改、查

在视图函数   相对应的函数里写

 

 

 

 -------------------------------------(create  ,  save) -------------------------------

 两种形式四种方法

  推荐: dic={"title":"go","price":45}

      models.Book.objects.create(**dic)

from app01.models import *

    #create方式一:   models.表名.objects.create(字段='内容')

    #create方式二:   models.表名.objects.create(**{"name":"alex"})

#增加的是字典两个星**  列表 一个* 


    #save方式一:     创建对象=表名(name="alvin")
                    author.save() #保存

    #save方式二:     对象=表名()
                            对象.name="alvin"
                            对象.save()        

推荐第二种 前面加两个星的字典形式
因为按正常需求来说,不会每一条数据我们都自己定好,而更多的情况,我们们从前端,或其他地方接收到用户信息。用户输入过来,我们接受到,接收到的信息就是一个字典,我们不需要做什么修改,直接把这个字典放在那里面插入进去,插入字典前前面要加两个星

 

重点增(一对多和,多对多)

A表

 

C表

 

     当创建创建表的时候,给这个表里建立了外键 一对多,怎么样给外见的字段 增加数据 

    比如在A表下建立外键,和c表要进行关联(外键要建立在多的那个表里 一个出板社 可以出多本书  但是一本书只能有一个出版社 (要是键在出版社后面,一个出版社,得出过多少本书,也不能那么建立)

         aaa=models.Foreignkey("C")                    要想给aaa字段增加数据 就得 后面加 _id 

 

比如 这样加  models.A.objects.create(aaa_id=1)     这就在A表的外键add_id列 增加了ccc表里对应的那个ID 1

为什么后面加_id,只是你在建立外键的时候Django 内部自动帮你生成的

 不加_id还有一种方法

      pud=models.C.objects.filter(id=1)

      models.A.objects.create(aaa=pud[0])

 

 因为filter(id=1)取到的是一个集合,pud必须是一个对象,不能是对象集合因为绑定的出版社只能有一个(因为是一对多,所以只能有一个对象)

 pud取到的id=1的出版社 集合        通过后面加上[0] 渠道索引,就是对象  不是集合

虽然外键建立在了A表里,但只要绑定了关系,C表也不是单纯的单表了,也是关联表

 

 

 多对多(键在两个表那个表也行)(ManyToManyField()) 自动生成第三张表                   自己创建第3 张表 可以通过两个外键 建立多对多

多对多的情况就是 一个作者可以写多本书,一本书也可以有多个作者一块编写,彼此间的关系就是多对多

 class Book (models.Model)

  字段名 F =models.ManyToManyField("另一张表名[作者表]")

 如果是这种创建方式,只能通过下面这种添加              add 方法

 

正向查询,在Book表里面增加

  abc1=models.作者表.objects.get(id=3)

    abc2=models.作者表.objects.get(id=4)

 取到了id等于3  4 的作者

   book=models.Book.objects.filter(id=3)[0]

取到书id等于3的一本书 ,第一个位置对象

  book.F.add(*[abc1,abc2])   

如果你要取消你所建立的关系  通过 book.F.remove(*[abc1,abc2])

3    3

3    4            这两条数据就删除了   下面反向的也是一样

这的F就是在Book建立多对多时候的字段                           第三张表里的字段是自己生成的   取得两张表的主键ib生成字段      

反向查询,作者表里添加,因为是多对多的关系,也可以在作者表里去插入数据,但是作者表里不能调用 F 字段了,因为没有,就得通过一个方法(.book_set) book就是Book的表名,得换成小写的

a=models.作者表.objects.get(id=3)

b=models.作者.objects.get(id=4)

c=models.Book.objects.filter(id=3)[0]

给两个作者插入了同一本书

a.book_set.objects.add(c)

b.book_set.objects.add(c)

要给book id等于3的这本书建立多对多的关系

 

自己创建多对多

class 表名(models.Model)

   book= models.Foreignkey("Book")

  author=models.Foreignkey("Author")

还有两个字段的联合唯一 ,两个字段不能重复(根据需求)

class Book2Author(models.Model)

    book= models.Foreignkey("Book")

    author=models.Foreignkey("Author")
    
    #建立联合唯一
    class Meta:
        unique_together = ["book","author"]



给  两个字段添加数据

def 函数(req):
   models. Book2Author.objects.create(
    book_id=2,
    author_id=3,
)
    
联合唯一 增加数据

 

#一对多(ForeignKey):

    #方式一: 由于绑定一对多的字段,比如publish,存到数据库中的字段名叫publish_id,所以我们可以直接给这个
    #       字段设定对应值:
           Book.objects.create(title='php',
                               publisher_id=2,   #这里的2是指为该book对象绑定了Publisher表中id=2的行对象
                               publication_date='2017-7-7',
                               price=99)


    #方式二:
    #       <1> 先获取要绑定的Publisher对象:
        pub_obj=Publisher(name='河大出版社',address='保定',city='保定',
                state_province='河北',country='China',website='http://www.hbu.com')
    OR  pub_obj=Publisher.objects.get(id=1)

    #       <2>将 publisher_id=2 改为  publisher=pub_obj

#多对多(ManyToManyField()):

    author1=Author.objects.get(id=1)
    author2=Author.objects.filter(name='alvin')[0]
    book=Book.objects.get(id=1)
    book.authors.add(author1,author2)
    #等同于:
    book.authors.add(*[author1,author2])
    book.authors.remove(*[author1,author2])
    #-------------------
    book=models.Book.objects.filter(id__gt=1)
    authors=models.Author.objects.filter(id=1)[0]
    authors.book_set.add(*book)
    authors.book_set.remove(*book)
    #-------------------
    book.authors.add(1)
    book.authors.remove(1)
    authors.book_set.add(1)
    authors.book_set.remove(1)

#注意: 如果第三张表是通过models.ManyToManyField()自动创建的,那么绑定关系只有上面一种方式
#     如果第三张表是自己创建的:
     class Book2Author(models.Model):
            author=models.ForeignKey("Author")
            Book=  models.ForeignKey("Book")
#     那么就还有一种方式:
            author_obj=models.Author.objects.filter(id=2)[0]
            book_obj  =models.Book.objects.filter(id=3)[0]

            s=models.Book2Author.objects.create(author_id=1,Book_id=2)
            s.save()
            s=models.Book2Author(author=author_obj,Book_id=1)
            s.save()
View Code

 

 

 

 ----------------------------------------(delete)-----------------------------

级联删除 和这个表里有 一对多 或多对多的 的其他表里  相关内容也会删除

表名.objects.filter(id=1).delete()
#查询到那个表里id等于1 的 通过.delete()删除

  

 

 -----------------------------------------update和save)--------------

表名.objects.filter(name='wangkuan').update(name='wk')

#update 不能用get   filter,渠道的是一个集合,就把所有等于wangkuan的替换成wk

#get 只会取到一个对象,没有就报错,他不能调用update

 推荐使用上面这个方法 他要比save效率高
update方法只会改你规定,字段的内容
save会把其他的即使你没有,改的也会重新改一遍,很多没有意义的操作



对象=表名.objects.get(id=5)     找到以后
对象.字段='内容'             重新赋值
对象.save              保存
update save

 

 

 

 -----------------------------------------------------查--------------------

------------------查询API(提前设定的函数,快捷方式) 

# 查询相关API:
变量接收=models.objects.filter(id=2)
#  <1>filter( = )      通过一组组的键值对来放 比如 name=wk,age=18  用逗号隔开,拿到的是集合对象

#  <2>all():            查询所有结果,也是集合对象里面没有参数

#  <3>get( = ):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个(单个行的对象),如果符合筛选条件的对象超过一个或者没有都会抛出错误。

变量接收=models.objects.filter(id=2)[0]

为什么加[0] 因为取到的是一个集合类似于一个列表,取第一个值,切片(因为它里面也是有序的)



#-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()--------

变量接收=models.objects.filter(id=2)    这样整行都去出来了

通过一个方法

变量接收=models.objects.filter(id=2).values("字段名")比如 name

就是把id=2 的name列 取出来了   是字典的形式

[{"name""wk"}]

为什么放在字典里面,因为你也许取出来的不只有一个

以下的这些方法 都是在 .filter  .all 后调用




#  <4>values(  ):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列
                                     
#  <5>exclude( = ):     它包含了与所给筛选条件不匹配的对象 比如id=2   出来id=2 的都取出来

#  <6>order_by("id"):      对查询结果排序,比如对id进行排序 是字符串 但是他认识   id前加- 负号 反着排

#  <7>reverse():             对查询结果反向排序

#  <8>distinct():            从返回结果中剔除重复纪录(去重)

#  <9>values_list(“字段”):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

#  <10>count():              返回数据库中匹配查询(QuerySet)的对象数量。(把你取到的集合技算一下,到底有多少条)

# <11>first():               返回第一条记录

# <12>last():                返回最后一条记录

#  <13>exists():             如果QuerySet包含数据,就返回True,否则返回False。(查询里面有没有这个数据)
方法

---------->惰性机制:

所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它并不会马上执行sql,而是当调用QuerySet的时候才执行。

QuerySet特点:

       <1>  可迭代的

       <2>  可切片

    #objs=models.Book.objects.all()#[obj1,obj2,ob3...]

    #QuerySet:   可迭代

    # for obj in objs:#每一obj就是一个行对象
    #     print("obj:",obj)
    # QuerySet:  可切片

    # print(objs[1])
    # print(objs[1:4])
    # print(objs[::-1])
View Code

 

 

 根据书名来找出版社的名字

 正向查找

def 函数(req):
    obj=models.Book.objects.filter(title="GO")[0]
#先找到书名
    a=obj.创建外键的字段名.name
    print(a)
取到出版社名字
View Code

反向查找

通过出版社找出,出过那几本书

#先找到出版社
obj=models.出版社表.objects.filter(name="人民出版社")[0]

a=obj.书小写的表名_set.all().values("书的字段").distinct()#去重

print(a)
View Code

双下滑线

#    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")   name字段里包含ven的取出来

#    models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
#
#    models.Tb1.objects.filter(id__range=[1, 2])   # 范围 id 1 2 之间的
#
#    __startswith=,必须以什么开头
istartswith,       
 endswith,以什么结尾
 iendswith,
双下滑线__单表操作
# 正向查找(条件)

#     ret3=models.Book.objects.filter(title='Python').values('id')
#     print(ret3)#[{'id': 1}]

      #正向查找(条件)之一对多

      ret4=models.Book.objects.filter(title='Python').values('publisher__city')
      print(ret4)  #[{'publisher__city': '北京'}]

      #正向查找(条件)之多对多
      ret5=models.Book.objects.filter(title='Python').values('author__name')
      print(ret5)
      ret6=models.Book.objects.filter(author__name="alex").values('title')
      print(ret6)

      #注意
      #正向查找的publisher__city或者author__name中的publisher,author是book表中绑定的字段
      #一对多和多对多在这里用法没区别

# 反向查找(条件)

    #反向查找之一对多:
    ret8=models.Publisher.objects.filter(book__title='Python').values('name')
    print(ret8)#[{'name': '人大出版社'}]  注意,book__title中的book就是Publisher的关联表名

    ret9=models.Publisher.objects.filter(book__title='Python').values('book__authors')
    print(ret9)#[{'book__authors': 1}, {'book__authors': 2}]

    #反向查找之多对多:
    ret10=models.Author.objects.filter(book__title='Python').values('name')
    print(ret10)#[{'name': 'alex'}, {'name': 'alvin'}]

    #注意
    #正向查找的book__title中的book是表名Book
    #一对多和多对多在这里用法没区别
关联查询

F查询和Q查询

仅仅靠单一的关键字参数查询已经很难满足查询要求。此时Django为我们提供了F和Q查询:

F  使用查询条件的值,专门取对象中某列值的操作

# F 使用查询条件的值,专门取对象中某列值的操作

    # from django.db.models import F
    # models.Tb1.objects.update(num=F('num')+1)
F

 Q  分装关键查询

Q 构建搜索条件

可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象。
& and        | or          ~  not 

    from django.db.models import Q


obj=models.Book.objects.filter(Q(id=3)|Q(title="php"))

#找到book表里id=3或 title=php的

models.Book.objects.filter(Q(price__ge=50)&(Q(id=3)|Q(title="php")))

#大于50的

每个查找函数都接受关键字参数(例如filter()),
# exclude(), get())也可以作为一个或多个Q对象传递


还可以加关键字   要放在最后面

.filter(Q(price__ge=50)&(Q(id=3)|Q(title="php")).color="yellow")

#加个大于50  id=3 或书名是PHP 颜色是黄色的
Q

 

 

 admin的配置

 

admin是django强大功能之一,它能共从数据库中读取数据,呈现在页面中,进行管理。默认情况下,它的功能已经非常强大,如果你不需要复杂的功能,它已经够用,但是有时候,一些特殊的功能还需要定制,比如搜索功能,下面这一系列文章就逐步深入介绍如何定制适合自己的admin应用。

如果你觉得英文界面不好用,可以在setting.py 文件中修改以下选项

LANGUAGE_CODE = 'en-us'  #LANGUAGE_CODE = 'zh-hans'

  

 当我们访问http://127.0.0.1:8080/admin/时,会出现:

 

 

 

 前提是先把默认的数据库生 在设定所以我们需要为进入这个项目的后台创建超级管理员:python manage.py createsuperuser设置好用户名和密码后便可登录啦!

 

 

 掌握一些常用的设置技巧

  •     list_display:     指定要显示的字段
  •     search_fields:  指定搜索的字段
  •     list_filter:        指定列表过滤器
  •     ordering:       指定排序字段

 

 

 

posted @ 2018-10-10 12:59  取经之路  阅读(146)  评论(0)    收藏  举报