python学习笔记十六 django深入学习一

django 请求流程图

django 路由系统

在django中我们可以通过定义urls,让不同的url路由到不同的处理函数

from . import views

urlpatterns = [
    url(r‘^articles/2003/$‘, views.special_case_2003),   #精确匹配
    url(r‘^articles/([0-9]{4})/$‘, views.year_archive),  #动态路由
    url(r‘^articles/([0-9]{4})/([0-9]{2})/$‘, views.month_archive),
    url(r‘^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$‘, views.article_detail),
]

注意: url的位置对于url的匹配是有影响的,url按照正则匹配,上面的匹配到了,下面的就不会被匹配了。

 默认url

urlpatterns = [
    url(r‘^$‘, views.index),
    url(r‘index2/$‘, views.index2),
]

当匹配不到任何url的时候,将执行默认url。

动态url

动态url传参

当我们想查找某年内的文章时,每点击一个url就需要写一个url匹配,这样显然是不合理的,所以我们可以通过动态url匹配,通过正则来实现。可以将参数传给后端函数处理。

urlpatterns = [
    url(r‘^articles/([0-9]{4})/$‘, views.year_archive), #接收一个参数
    url(r‘^articles/([0-9]{4})/([0-9]{2})/$‘, views.month_archive), #接收多个参数
    url(r‘^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$‘, views.article_detail),
]

对于url(r‘^articles/([0-9]{4})/$‘, views.year_archive) 这条匹配规则,views函数必须为/([0-9]{4})有一个接收参数,否则将提示

动态url传入关键字参数

我的参数过多的时候,按照顺序传入就会显得很麻烦,这时候我们可以按照key:value形式传入参数

import views

urlpatterns = [
    url(r‘^articles/2003/$‘, views.special_case_2003),
    url(r‘^articles/(?P<year>[0-9]{4})/$‘, views.year_archive),
    url(r‘^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$‘, views.month_archive),
    url(r‘^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$‘, views.article_detail),
]

当我们请求/articles/2005/03/ 将会调用后端函数传入year和month参数 views.month_archive(request, year=‘2005‘,month=‘03‘),假设我们将在函数定义中把year和month写成y和m,

将会出现错误。

url转发

大部分情况下,我们不会把所有的url写在全局url配置中,这样会容易引发很多问题,比如:

新增加的url规则可能包含旧的url,导致旧的匹配不到,

添加错误的url导致站点出现问题

app间的松耦合问题

...

所以我们应该使用以下方式解决问题:

在全局urls.py中添加,二层路由

from django.conf.urls import url,include
from app01 import urls as payment_urls

urlpatterns = [
    url(r‘^payment/‘, include(payment_urls)),
]

在app中添加urls.py文件

from django.conf.urls import url,include
from app01 import views
urlpatterns = [
    url(r‘^$‘, views.index),
    url(r‘cash/$‘, views.pay_by_cash),
]

接下里可以通过 http://hostip:port/payment/ 或 http://hostip:port/payment/cash/ 访问

注意:django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。

django templates

django的模板给我们提供了丰富的替换规则,假设我们自己去定义一个替换规则如下:

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

当内容足够多的时候,就没法玩了。当然我们可以写入文件,然后通过django的模板语言渲染html。

Django 模版基本语法

>>> from django.template import Context,Template
>>> t = Template("my name is {{name}}.")   #针对变量
>>> c = Context({"name":"koka"})
>>> t.render(c)
‘my name is koka.‘

>>> from django.template import Template,Context
>>> person = {"name":"koka","age":"24"} #针对字典
>>> t = Template("{{ person.name }} is {{ person.age }} year old.")
>>> c = Context({"person":person})
>>> t.render(c)
‘koka is 24 year old.‘

>>> t = Template("Item 2 is {{ items.2 }}.") #针对列表
>>> c = Context({‘items‘:["apples","bananas","carrots"]})
>>> t.render(c)
‘Item 2 is carrots.‘

无论何时我们都可以像这样使用同一模板源渲染多个context,只进行 一次模板创建然后多次调用render()方法渲染会更为高效:

注意:

Django 模板解析非常快捷。 大部分的解析工作都是在后台通过对简短正则表达式一次性调用来完成。 这和基于 XML 的模板引擎形成鲜明对比,那些引擎承担了 XML 解析器的开销,且往往比 Django 模板渲染引擎要慢上几个数量级。我们来对比一下两种方式:

# Bad
for name in (‘John‘, ‘Julie‘, ‘Pat‘):
    t = Template(‘Hello, {{ name }}‘)  #建立多次模板
    print t.render(Context({‘name‘: name}))

# Good
t = Template(‘Hello, {{ name }}‘)
for name in (‘John‘, ‘Julie‘, ‘Pat‘):
    print t.render(Context({‘name‘: name}))

模板中的for和if语句,django模板语言是没有while循环的,假设写一个死循环一直获取不到数据,将是一件悲剧的事。

for: {% for item in item_list %}  <a>{{ item }}</a>  {% endfor %}

if: {% if ordered_warranty %}  {% else %} {% endif %}

#templates中定义index.html模板文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .header li{
            display: inline-block;
        }
    </style>
</head>
<body>
    <div class="header">
        <ul>
            <li>home</li>
            <li>page1</li>
            <li>page2</li>
            <li>page3</li>
        </ul>
    </div>
    <h1>Welcome to test center</h1><ul>
        {% for item in user_obj %}
            {% if item.username == "koka" %}
                <li style="background-color: red;">username:{{ item.username }} age:{{ item.age }}</li>
            {% else %}
                <li style="">username:{{ item.username }} age:{{ item.age }}</li>
            {% endif %}
        {% endfor %}
    </ul><footer> Power by koka</footer>
</body>
</html>

#view

from django.shortcuts import render,HttpResponse

# Create your views here.
def index(request):
    user_obj = [
        {"username":"koka", "age":"24"},
        {"username":"ajax", "age":"24"},
        {"username":"django","age":"24"}
    ]
    return render(request, ‘app01/index.html‘, {‘user_obj‘: user_obj}) #将数据插入模板文件

其他方法:

  • forloop.counter
  • forloop.first
  • forloop.last
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>Welcome to test center</h1>
    <ul>
        {% for item in user_obj %}
            {% if forloop.counter > 2 %}
                <li style="background-color: red;">username:{{ item.username }} age:{{ item.age }}</li>
            {% else %}
                <li style="">username:{{ item.username }} age:{{ item.age }}</li>
            {% endif %}
        {% endfor %}
    </ul>
</body>
</html>

效果如下:

divisibleby 取模

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>Welcome to test center</h1>
    <ul>
        {% for item in user_obj %}
            {% if forloop.counter|divisibleby:"2" %}
                <li style="background-color: red;">username:{{ item.username }} age:{{ item.age }}</li>
            {% else %}
                <li style="">username:{{ item.username }} age:{{ item.age }}</li>
            {% endif %}
        {% endfor %}
    </ul>
</body>
</html>

效果如下:

django母板与子板

母板:{% block title %}{% endblock %} 定义子板可以修改的范围

子板:{% extends "base.html" %} 继承母板

   {% block title %}{% endblock %} 重写母板中定义可以修改的范围

继承与重写

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .header li{
            display: inline-block;
        }
    </style>
</head>
<body>
    <div class="header">
        <ul>
            <li>home</li>
            <li>page1</li>
            <li>page2</li>
            <li>page3</li>
        </ul>
    </div>
    <h1>Welcome to test center</h1>
    {% block tab %}
    <ul>
        {% for item in user_obj %}
            {% if item.username == "koka" %}
                <li style="background-color: red;">username:{{ item.username }} age:{{ item.age }}</li>
            {% else %}
                <li style="">username:{{ item.username }} age:{{ item.age }}</li>
            {% endif %}
        {% endfor %}
    </ul>
    {% endblock %}
    <footer> Power by koka</footer>
</body>
</html>

母板

{% extends ‘app01/index.html‘ %}

{% block tab %}
    <h1>this is my page</h1>
    <form style="color: aqua" action="#" method="post">
        UserName:<input name="username" type="text">
        Password:<input name="pwd" type="password">
    </form>
{% endblock %}

子板

多重继承

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .header li{
            display: inline-block;
        }
    </style>
</head>
<body>
    <div class="header">
        <ul>
            <li>home</li>
            <li>page1</li>
            <li>page2</li>
            <li>page3</li>
        </ul>
    </div>
    <h1>Welcome to test center</h1>
    {% block tab %}
    <ul>
        {% for item in user_obj %}
            {% if item.username == "koka" %}
                <li style="background-color: red;">username:{{ item.username }} age:{{ item.age }}</li>
            {% else %}
                <li style="">username:{{ item.username }} age:{{ item.age }}</li>
            {% endif %}
        {% endfor %}
    </ul>
    {% endblock %}
    <footer> Power by koka</footer>
</body>
</html>

母板 index

{% extends ‘app01/index.html‘ %}

{% block tab %}
    <h1>this is sub page</h1>
    {% block f-content %}
        {% include ‘app01/register_form.html‘ %}
    {% endblock %}
{% endblock %}
{% extends "app01/page1.html" %}
{% block f-content %}
    <h1>this is sub-sub-page</h1>
{% endblock %}

include

在讲解了模板加载机制之后,我们再介绍一个利用该机制的内建模板标签: {% include %} 。该标签允许在(模板中)包含其它的模板的内容。 标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引号硬编码的字符串。 每当在多个模板中出现相同的代码时,就应该考虑是否要使用 {% include %} 来减少重复。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <form style="color: aqua" action="#" method="post">
        UserName:<input name="username" type="text">
        Password:<input name="pwd" type="password">
    </form>
</body>
</html>

form_register

{% extends ‘app01/index.html‘ %}

{% include ‘app01/register_form.html‘ %}

  django admin

django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用django admin 则需要以下步骤:

1.注册app

INSTALLED_APPS = [
    ‘django.contrib.admin‘,
    ‘django.contrib.auth‘,
    ‘django.contrib.contenttypes‘,
    ‘django.contrib.sessions‘,
    ‘django.contrib.messages‘,
    ‘django.contrib.staticfiles‘,
    ‘app01‘,
]

2.数据库配置

DATABASES = {
    ‘default‘: {
       #sqlite配置如下
         ‘ENGINE‘: ‘django.db.backends.sqlite3‘,
          ‘NAME‘: os.path.join(BASE_DIR, ‘db.sqlite3‘),
        # mysql配置如下
        # ‘ENGINE‘: ‘django.db.backends.mysql‘,
        # ‘NAME‘: ‘s12day16‘,
        # ‘HOST‘: ‘‘,
        # ‘PORT‘: ‘‘,
        # ‘USER‘: ‘root‘,
        # ‘PASSWORD‘: ‘‘,
    }
}

3.models配置

from django.db import models

# Create your models here.

class Publisher(models.Model):
    name = models.CharField(max_length=32)
    address = models.CharField(max_length=64,unique=True)
    city = models.CharField(max_length=64)
    state_province = models.CharField(max_length=32)
    country = models.CharField(max_length=32)
    website = models.URLField()
    def __unicode__(self):
        return "%s" % self.name
    def __str__(self):
        return "%s" % self.name
class Author(models.Model):
    first_name = models.CharField(max_length=32)
    last_name = models.CharField(max_length=32)
    email = models.EmailField()
    def __unicode__(self):
        return "%s %s" %(self.first_name,self.last_name)
    def __str__(self):
        return "%s %s" %(self.first_name,self.last_name)
class Book(models.Model):
    title = models.CharField(max_length=64)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()
    def __unicode__(self):
        return "%s" % self.title
    def __str__(self):
        return "%s" % self.title

models

4.创建数据库

终端下执行下面两条命令:

python manage.py makemigrations 生成数据库配置文件

python manage.py migrate 创建数据库

5.配置admin

from django.contrib import admin

# Register your models here.
from app01 import models

admin.site.register(models.Author)
admin.site.register(models.Book)
admin.site.register(models.Publisher)

6.创建超级管理员

pyhton manage.py createsuperuser

7.登录admin管理后台

http://hostip:port/admin

设置字段可选

在摆弄了一会之后,你或许会发现管理工具有个限制:编辑表单需要你填写每一个字段,然而在有些情况下,你想要某些字段是可选的。 举个例子,我们想要Author模块中的email字段成为可选,即允许不填。 在现实世界中,你可能没有为每个作者登记邮箱地址。

为了指定email字段为可选,你只要编辑Book模块(回想第五章,它在mysite/books/models.py文件里),在email字段上加上blank=True。代码如下:

class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField(**blank=True** )

设置日期型和数字型字段可选

在SQL中, NULL的值不同于空字符串,就像Python中None不同于空字符串("")一样。这意味着某个字符型字段(如VARCHAR)的值不可能同时包含NULL和空字符串。

如果你想允许一个日期型(DateFieldTimeFieldDateTimeField)或数字型(IntegerFieldDecimalFieldFloatField)字段为空,你需要使用null=True * 和* blank=True

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField(**blank=True, null=True** )

修改了表结构,需要重新同步数据库。

自定义字段标签

在编辑页面中,每个字段的标签都是从模块的字段名称生成的。 规则很简单: 用空格替换下划线;首字母大写。例如:Book模块中publication_date的标签是Publication date。

然而,字段名称并不总是贴切的。有些情况下,你可能想自定义一个标签。 你只需在模块中指定verbose_name

class Author(models.Model):
    first_name = models.CharField(max_length=30,verbose_name=‘名‘)
    last_name = models.CharField(max_length=40,verbose_name=‘姓‘)
    email = models.EmailField(blank=True, **verbose_name=‘邮箱‘** )

自定义ModelAdmin类

自定义列表

自定义显示字段否则将是tableobj

class Author(models.Model):
    first_name = models.CharField(max_length=32)
    last_name = models.CharField(max_length=32)
    email = models.EmailField()
    def __unicode__(self):
        #1.9以前
        return "%s %s" %(self.first_name,self.last_name)
    def __str__(self):
        #1.9以后
        return "%s %s" %(self.first_name,self.last_name)

我们可以在这基础上改进,添加其它字段,从而改变列表的显示。

这个页面应该提供便利,比如说:在这个列表中可以看到作者的邮箱地址。如果能按照姓氏或名字来排序,那就更好了。

from django.contrib import admin

# Register your models here.
from app01 import models

class AuthorAdmin(admin.ModelAdmin):
    //
    我们新建了一个类AuthorAdmin,它是从django.contrib.admin.ModelAdmin派生出来的子类,保存着一个类的自定义配置,以供管理工具使用。     我们只自定义了一项:list_display, 它是一个字段名称的元组,用于列表显示。 当然,这些字段名称必须是模块中有的。
    //
    list_display = (‘first_name‘, ‘last_name‘, ‘email‘)

admin.site.register(models.Author,AuthorAdmin)  //用AuthorAdmin选项注册Author模块。admin.site.register()函数接受一个ModelAdmin子类作为第二个参数。
admin.site.register(models.Book)
admin.site.register(models.Publisher)

效果如下:

添加一个快速查询栏

class AuthorAdmin(admin.ModelAdmin):
    list_display = (‘first_name‘, ‘last_name‘, ‘email‘)
    **search_fields = (‘first_name‘, ‘last_name‘)**

过滤器

class BookAdmin(admin.ModelAdmin):
    list_display = (‘title‘, ‘publisher‘, ‘publication_date‘)
    list_filter = (‘publication_date‘,)

admin.site.register(models.Book,BookAdmin)

`` 过滤器`` 同样适用于其它类型的字段,而不单是`` 日期型`` (请在`` 布尔型`` 和`` 外键`` 字段上试试)。当有两个以上值时,过滤器就会显示。

另外一种过滤日期的方式是使用date_hierarchy选项

class BookAdmin(admin.ModelAdmin):
    list_display = (‘title‘, ‘publisher‘, ‘publication_date‘)
    date_hierarchy = ‘publication_date‘

请注意,date_hierarchy接受的是* 字符串* ,而不是元组。因为只能对一个日期型字段进行层次划分。

改变默认的排序方式

class BookAdmin(admin.ModelAdmin):
    list_display = (‘title‘, ‘publisher‘, ‘publication_date‘)
    list_filter = (‘publication_date‘,)
    date_hierarchy = ‘publication_date‘
    **ordering = (‘-publication_date‘,)**

自定义编辑表单

自定义字段顺序

首先,我们先自定义字段顺序。 默认地,表单中的字段顺序是与模块中定义是一致的。 我们可以通过使用ModelAdmin子类中的fields选项来改变它:

class BookAdmin(admin.ModelAdmin):
    list_display = (‘title‘, ‘publisher‘, ‘publication_date‘)
    list_filter = (‘publication_date‘,)
    date_hierarchy = ‘publication_date‘
    ordering = (‘-publication_date‘,)
    **fields = (‘title‘, ‘authors‘, ‘publisher‘, ‘publication_date‘)**

完成之后,编辑表单将按照指定的顺序显示各字段。 它看起来自然多了——作者排在书名之后。 字段顺序当然是与数据条目录入顺序有关, 每个表单都不一样。

禁止编辑项

class BookAdmin(admin.ModelAdmin):
    list_display = (‘title‘, ‘publisher‘, ‘publication_date‘)
    list_filter = (‘publication_date‘,)
    date_hierarchy = ‘publication_date‘
    ordering = (‘-publication_date‘,)
    **fields = (‘title‘, ‘authors‘, ‘publisher‘)**  #不包含某一项即可

ctrl多选框

class BookAdmin(admin.ModelAdmin):
    list_display = (‘title‘, ‘publisher‘, ‘publication_date‘)
    list_filter = (‘publication_date‘,)
    date_hierarchy = ‘publication_date‘
    ordering = (‘-publication_date‘,)
    **filter_horizontal = (‘authors‘,)**

 

ModelAdmin类还支持filter_vertical选项。 它像filter_horizontal那样工作,除了控件都是垂直排列,而不是水平排列的。

filter_horizontalfilter_vertical选项只能用在多对多字段 上, 而不能用于 ForeignKey字段。 默认地,管理工具使用`` 下拉框`` 来展现`` 外键`` 字段。

文本框

使用`` raw_id_fields`` 选项。它是一个包含外键字段名称的元组,它包含的字段将被展现成`` 文本框`` ,而不再是`` 下拉框`` 。

class BookAdmin(admin.ModelAdmin):
    list_display = (‘title‘, ‘publisher‘, ‘publication_date‘)
    list_filter = (‘publication_date‘,)
    date_hierarchy = ‘publication_date‘
    ordering = (‘-publication_date‘,)
    filter_horizontal = (‘authors‘,)
    **raw_id_fields = (‘publisher‘,)**

更多django admin的内容请参考: http://docs.30c.org/djangobook2/chapter06/

django models

到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞:

  • 创建数据库,设计表结构和字段
  • 使用sqlapi 来连接数据库,并编写数据访问层代码
  • 业务逻辑层去调用数据访问层执行数据库操作

第一个模型

我们来假定下面的这些概念、字段和关系:

  • 一个作者有姓,有名及email地址。
  • 出版商有名称,地址,所在城市、省,国家,网站。
  • 书籍有书名和出版日期。 它有一个或多个作者(和作者是多对多的关联关系[many-to-many]), 只有一个出版商(和出版商是一对多的关联关系[one-to-many],也被称作外键[foreign key])
from django.db import models

# Create your models here.
class Publisher(models.Model):
    #首先要注意的事是每个数据模型都是 django.db.models.Model 的子类。
    #它的父类 Model 包含了所有必要的和数据库交互的方法,并提供了一个简洁漂亮的定义数据库字段的语法。
    name = models.CharField(max_length=32)
    address = models.CharField(max_length=64,unique=True)
    city = models.CharField(max_length=64)
    state_province = models.CharField(max_length=32)
    country = models.CharField(max_length=32)
    website = models.URLField()
    def __unicode__(self):
        return "%s" % self.name
    def __str__(self):
        return "%s" % self.name
class Author(models.Model):
    #每个模型相当于单个数据库表,每个属性也是这个表中的一个字段。
    first_name = models.CharField(max_length=32)
    last_name = models.CharField(max_length=32)
    email = models.EmailField(verbose_name="邮箱")
    def __unicode__(self):
        return "%s %s" %(self.first_name,self.last_name)
    def __str__(self):
        return "%s %s" %(self.first_name,self.last_name)
class Book(models.Model):
    #“每个数据库表对应一个类”这条规则的例外情况是多对多关系。
    # Book 有一个 多对多字段 叫做 authors 。 该字段表明一本书籍有一个或多个作者,但 Book 数据库表却并没有 authors 字段。
    #相反,Django创建了一个额外的表(多对多连接表)来处理书籍和作者之间的映射关系。
    title = models.CharField(max_length=64)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()
    def __unicode__(self):
        return "%s" % self.title
    def __str__(self):
        return "%s" % self.title

Django会自动为每个模型生成一个自增长的整数主键字段每个Django模型都要求有单独的主键。id

剩下的步骤参考django admin生成数据库的操作。(注册,生成配置文件,创建数据库)

1、models.AutoField  自增列 = int(11)
  如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
2、models.CharField  字符串字段
  必须 max_length 参数
3、models.BooleanField  布尔类型=tinyint(1)
  不能为空,Blank=True
4、models.ComaSeparatedIntegerField  用逗号分割的数字=varchar
  继承CharField,所以必须 max_lenght 参数
5、models.DateField  日期类型 date
  对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
6、models.DateTimeField  日期类型 datetime
  同DateField的参数
7、models.Decimal  十进制小数类型 = decimal
  必须指定整数位max_digits和小数位decimal_places
8、models.EmailField  字符串类型(正则表达式邮箱) =varchar
  对字符串进行正则表达式
9、models.FloatField  浮点类型 = double
10、models.IntegerField  整形
11、models.BigIntegerField  长整形
  integer_field_ranges = {
    ‘SmallIntegerField‘: (-32768, 32767),
    ‘IntegerField‘: (-2147483648, 2147483647),
    ‘BigIntegerField‘: (-9223372036854775808, 9223372036854775807),
    ‘PositiveSmallIntegerField‘: (0, 32767),
    ‘PositiveIntegerField‘: (0, 2147483647),
  }
12、models.IPAddressField  字符串类型(ip4正则表达式)
13、models.GenericIPAddressField  字符串类型(ip4和ip6是可选的)
  参数protocol可以是:both、ipv4、ipv6
  验证时,会根据设置报错
14、models.NullBooleanField  允许为空的布尔类型
15、models.PositiveIntegerFiel  正Integer
16、models.PositiveSmallIntegerField  正smallInteger
17、models.SlugField  减号、下划线、字母、数字
18、models.SmallIntegerField  数字
  数据库中的字段有:tinyint、smallint、int、bigint
19、models.TextField  字符串=longtext
20、models.TimeField  时间 HH:MM[:ss[.uuuuuu]]
21、models.URLField  字符串,地址正则表达式
22、models.BinaryField  二进制
23、models.ImageField   图片
24、models.FilePathField 文件

更多字段

1、null=True
  数据库中字段是否可以为空
2、blank=True
  django的 Admin 中添加数据时是否可允许空值
3、primary_key = False
  主键,对AutoField设置主键后,就会代替原来的自增 id 列
4、auto_now 和 auto_now_add
  auto_now   自动创建---无论添加或修改,都是当前操作的时间
  auto_now_add  自动创建---永远是创建时的时间
5、choices
GENDER_CHOICE = (
        (u‘M‘, u‘Male‘),
        (u‘F‘, u‘Female‘),
    )
gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
6、max_length
7、default  默认值
8、verbose_name  Admin中字段的显示名称
9、name|db_column  数据库中的字段名称
10、unique=True  不允许重复
11、db_index = True  数据库索引
12、editable=True  在Admin里是否可编辑
13、error_messages=None  错误提示
14、auto_created=False  自动创建
15、help_text  在Admin中提示帮助信息
16、validators=[]
17、upload-to

更多参数

参考地址:
https://docs.djangoproject.com/en/1.9/ref/models/fields/

数据库的基本操作

添加数据

python manage.py shell

方式一:

>>> p1 = models.Publisher(name="Apress",address="2855 Tele Aven",city="Bkl",state_province="CA",country=‘U.S.A.‘,website="http://apress.com/") #当你使用Django modle API创建对象时Django并未将对象保存至数据库内,除非你调用`` save()`` 方法:
>>> p1.save() #后台插入数据库因为 Publisher 模型有一个自动增加的主键 id ,所以第一次调用 save() 还多做了一件事: 计算这个主键的值并把它赋值给这个对象实例:

方式二:

>>> models.Author.objects.create(first_name="lo",last_name="lo",email="[email protected]")
<Author: lo lo>
>>> models.Author.objects.create(first_name="la",last_name="la",email="[email protected]")
<Author: la la>

插入和更新数据

>>> p2 = models.Publisher(name="wlgc",address="cnblog", city="BJ",state_province="BJ",country="CN",website="http://www.wlgc.com/")
>>> p2.save()
>>> p2.id
4
接下来再调用 save() 将不会创建新的记录,而只是修改记录内容(也就是 执行 UPDATE SQL语句,而不是 INSERT 语句):
>>> p2.address = ‘WLGC‘
>>> p2.save()

注意,并不是只更新修改过的那个字段,所有的字段都会被更新。 这个操作有可能引起竞态条件(表之间的关联冲突),这取决于你的应用程序。

查找数据

>>> models.Publisher.objects.all() #查找所有[<Publisher: DB出版社>, <Publisher: dbrc出版社>, <Publisher: Apress>, <Publisher: wlgc>]     
>>> models.Publisher.objects.all().last()<Publisher: wlgc>

>>> models.Publisher.objects.all().first()<Publisher: DB出版社>   

数据过滤

`` filter()`` 方法对数据进行过滤
>>> models.Publisher.objects.filter(name="Apress")
[<Publisher: Apress>]

你可以传递多个参数到 filter() 来缩小选取范围:>>> models.Publisher.objects.filter(country="U.S.A.", state_province="CA")[<Publisher: Apress>]

范围匹配id在1-3之间>>> models.Publisher.objects.filter(id__range=[1,3])[<Publisher: DB出版社>, <Publisher: dbrc出版社>]       

模糊匹配

>>> models.Publisher.objects.filter(name__contains="press")
[<Publisher: Apress>]
>>> models.Publisher.objects.filter(name__icontains="press")
[<Publisher: Apress>]
name 和 contains 之间有双下划线。和Python一样,Django也使用双下划线来表明会进行一些魔术般的操作。这里,contains部分会被Django翻译成LIKE语句,icontains不区分大小写:

获取单个对象

>>> models.Publisher.objects.get(name="Apress")
<Publisher: Apress>
这样,就返回了单个对象,而不是列表(更准确的说,QuerySet)

注意:使用get请求到一个列表或者空字段时将会报错

结果是多个对象,会导致抛出异常:
>>> Publisher.objects.get(country="U.S.A.")
Traceback (most recent call last):
    ...
MultipleObjectsReturned: get() returned more than one Publisher --
    it returned 2! Lookup parameters were {‘country‘: ‘U.S.A.‘}

查询没有返回结果也会抛出异常:
>>> Publisher.objects.get(name="Penguin")
Traceback (most recent call last):
    ...
DoesNotExist: Publisher matching query does not exist.

这个 DoesNotExist 异常 是 Publisher 这个 model 类的一个属性,即 Publisher.DoesNotExist。在你的应用中,你可以捕获并处理这个异常,像这样:
try:
    p = Publisher.objects.get(name=‘Apress‘)
except Publisher.DoesNotExist:
    print "Apress isn‘t in the database yet."
else:
    print "Apress is in the database."

更新多个对象(update)

>>> models.Author.objects.filter(id=3).update(first_name="db")1>>> models.Publisher.objects.all().update(country=‘CN‘)4update()方法会返回一个整型数值,表示受影响的记录条数。

删除对象(delete)

>>> models.Publisher.objects.get(name="Apress").delete()
(1, {‘app01.Publisher‘: 1})
>>> models.Publisher.objects.all().delete() #删除所有Publisher

关联查找

>>> b1 = models.Book.objects.get(id=2)
>>> b1.authors.select_related()
[<Author: sp chai>]
时间: 2024-10-12 03:52:42

python学习笔记十六 django深入学习一的相关文章

C++学习笔记十六-模板和泛型编程(二)

C++学习笔记十六-模板和泛型编程(二) 16.4 类模板成员 1.模板作用域中模板类型的引用: 通常,当使用类模板的名字的时候,必须指定模板形参.这一规则有个例外:在类本身的作用域内部,可以使用类模板的非限定名.例如,在默认构造函数和复制构造函数的声明中,名字 Queue 是 Queue<Type> 缩写表示.实质上,编译器推断,当我们引用类的名字时,引用的是同一版本.因此,复制构造函数定义其实等价于: Queue<Type>(const Queue<Type> &a

Opencv学习笔记(六)SURF学习笔记

原创文章,转载请注明出处:http://blog.csdn.net/crzy_sparrow/article/details/7392345 本人挺菜的,肯定有非常多错误纰漏之处 ,希望大家不吝指正. 看了harris角点检測之后,開始研究SURF角点检測,发现挺复杂的,一时也仅仅了解了大概,把了解的东西总结下,以便下次深入学习. SURF角点检測算法是对SIFT的一种改进,主要体如今速度上,效率更高.它和SIFT的主要差别是图像多尺度空间的构建方法不同. 在计算视觉领域,尺度空间被象征性的表述

python学习笔记十五 django基础

Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Session等诸多功能. 1.创建django程序 通过命令行 django-admin startproject mysite 创建project 一个工程可以包含多个app,app共用一个project的配置文件 cd mysite python manage.py startapp app01 创建app01 pyt

MYSQL进阶学习笔记十六:MySQL 监控!(视频序号:进阶_35)

知识点十六:MySQL监控(35) 一.为什么使用MySQL监控 随着软件后期的不断升级,myssql的服务器数量越来越多,软硬件故障的发生概率也越来越高.这个时候就需要一套监控系统,当主机发生异常时,此时通过监控系统发现和处理. 这个监控实际上是在我们的开发完成之后,这个时候软件就开始在运行,这个运行我们就需要去关注到mysql服务器是否正常,那么我们要观察它就需要给它提供一些监控,这监控就是当它发生故障之后, 那么我们这个监控就会告诉我们到底什么地方发生了一些异常或者一些错误,这个时候我们就

python 学习笔记十九 django项目bbs论坛

跨站请求伪造保护 CSRF 中间件和模板标签提供对跨站请求伪造简单易用的防护.某些恶意网站上包含链接.表单按钮或者JavaScript ,它们会利用登录过的用户在浏览器中的认证信息试图在你的网站上完成某些操作,这就是跨站攻击.还有另外一种相关的攻击叫做“登录CSRF”,攻击站点触发用户浏览器用其它人的认证信息登录到其它站点. 全局: 中间件 django.middleware.csrf.CsrfViewMiddleware 局部: @csrf_protect,为当前函数强制设置防跨站请求伪造功能

Python学习笔记十六_模块结构调整

一.什么是模块结构调整 当一个脚本中有大量的配置.方法及接口时,脚本往往显得十分臃肿.为了代码更易读,可以将一个繁杂的脚本根据不同的功能放在不同的文件夹中分类管理,即模块结构调整. 二.模块结构调整实例 下面根据一个具体的例子来看一下如何拆分调整代码 1.根据正常人的思维写代码完成功能 代码需求: (1) 注册接口: (a) 写一个注册接口,密码存成密文 (b) 数据存到redis,redis的key用string类型 (c) Amy  7869d295e566295b51eec5d6bed67

python学习笔记(十六) - ORM框架(SQLAlchemy)

所谓的ORM就是Object-Relational Mapping,把关系数据库的表结果映射到对象上. 1. 安装SQLAlchemy: easy_install sqlalchemy 2. 导入SQLAlchemy,并初始化DBSession: # 导入: from sqlalchemy import Column, String, create_engine from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declara

django 框架学习:十六.django 后台管理系统

前言 每个网站一般都有后台管理系统,为了方便管理,django框架也有后台管理系统,后台管理系统主要可以实现以下功能: 基于admin模块,可恶意实现类似数据库客户端的功能,对数据库进行增删改查. 基于该模块的数据管理功能,可以二次定制一些使用的功能. settings.py 配置 在INSTALLED_APPS中,默认已经添加相关模块. 'django.contrib.admin'  管理站点'django.contrib.auth'  认证系统'django.contrib.contentt

spring in action学习笔记十六:配置数据源的几种方式

第一种方式:JNDI的方式. 用xml配置的方式的代码如下: 1 <jee:jndi-lookup jndi-name="/jdbc/spittrDS" resource-ref="true" id="dataSource"/> 用注解方式的代码如下: 1 @Bean 2 public JndiObjectFactoryBean jndiObjectFactoryBean(){ 3 JndiObjectFactoryBean jndi