zoukankan      html  css  js  c++  java
  • Django基础(二)—— models

    六:Models示例

    Django本身提供了非常强大易使用的ORM组件,并且支持多种数据库。

    配置连接数据文件

    在自己创建的project 目录下编辑settings.py

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',    # mysql 数据库
            'NAME': 'dbname',             #确保此数据库已存在
            'HOST':'',
            'PORT':'',
            'USER':'root',
            'PASSWORD':''
        }
    }

     

    假设下面的概念,字段关系:

    1,一个作者有姓,名及email地址

    2,出版商有名称,地址,所在城市,省,国家,网站

    3,书籍有书名和出版日期。它有一个或多个作者,只有一个出版商

    #models.py
    # 一张表定义一个类,这里不再需要单独定义关联表
    
    from django.db import models
     
    class Publisher(models.Model):
        name = models.CharField(max_length=30)
        address = models.CharField(max_length=50)
        city = models.CharField(max_length=60)
        state_province = models.CharField(max_length=30)
        country = models.CharField(max_length=50)
        website = models.URLField()
     
    class Author(models.Model):
        first_name = models.CharField(max_length=30)
        last_name = models.CharField(max_length=40)
        email = models.EmailField()
     
    class Book(models.Model):
        title = models.CharField(max_length=100)
        authors = models.ManyToManyField(Author) # 多对多
        publisher = models.ForeignKey(Publisher)   # 一对多
        publication_date = models.DateField()

    模型安装

    代码完成后,就需要创建表了。

    第一步,在Django项目中 激活这些模型。将上面的模型所在的app添加到配置文件的安装应用列表中。

    # settings.py
    
    INSTALLED_APPS = (
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.sites',
       'app01',      # 自己所创建的Django项目名
    )

     

    按照模型的配置生成表结构

    命令行模式:

    python manage.py makemigrations                    # 生成同步记录

    python manage.py migrate                                 # 开始同步数据库

     

    基本数据访问

    数据同步完成之后就可以在命令行模式 使用 python manage.py shell 就可以进入Django提供的高级python API

    >>> from books.models import Publisher
    >>> p1 = Publisher(name='Apress', address='2855 Telegraph Avenue',
    ...     city='Berkeley', state_province='CA', country='U.S.A.',
    ...     website='http://www.apress.com/')        # 添加数据
    >>> p1.save()            # 保存到数据库
    >>> p2 = Publisher(name="O'Reilly", address='10 Fawcett St.',
    ...     city='Cambridge', state_province='MA', country='U.S.A.',
    ...     website='http://www.oreilly.com/')
    >>> p2.save()
    >>> publisher_list = Publisher.objects.all()    #读取数据
    >>> publisher_list
    [<Publisher: Publisher object>, <Publisher: Publisher object>]

    如果需要一步创建与存储到数据库,就需要使用 objects.create() 方法

    >>> p1 = Publisher.objects.create(name='Apress',
    ...     address='2855 Telegraph Avenue',
    ...     city='Berkeley', state_province='CA', country='U.S.A.',
    ...     website='http://www.apress.com/')        # 直接写如数据库
    >>> p2 = Publisher.objects.create(name="O'Reilly",
    ...     address='10 Fawcett St.', city='Cambridge',
    ...     state_province='MA', country='U.S.A.',
    ...     website='http://www.oreilly.com/')
    >>> publisher_list = Publisher.objects.all()
    >>> publisher_list

     

    __unicode__() 和 __str__()

    当我们打印整个publisher 列表时,我们没有得到想要的信息,无法把对象区分。

    [<Publisher: Publisher object>, <Publisher: Publisher object>]

    为了解决这个问题,只需要为publisher对象添加一个方法。这个方法告诉python 如果将对象以unicode的方式显示出来。

    def __str__(self):
            return self.name
    # name为需要显示的字段名。可以返回多个
    # return "<%s %s>" %(self.first_name,self.last_name)

    注:在python 2.x 里面使用 __unicode_()  python3.x 里面使用 __str__()

    插入和更新数据

    插入数据:

    p = Publisher(name='Apress',
    ...         address='2855 Telegraph Ave.',
    ...         city='Berkeley',
    ...         state_province='CA',
    ...         country='U.S.A.',
    ...         website='http://www.apress.com/')
    
    p.save()        # 这一步才会插入数据库

    更新数据:

    >>> p.name = 'Apress Publishing'    # 直接赋值,就是更改数据
    >>> p.save()            # 保存

     

    查找对象

    >>> Publisher.objects.all()
    [<Publisher: Apress>, <Publisher: O'Reilly>]
    # 相当于SQL 语句
    SELECT id, name, address, city, state_province, country, website
    FROM books_publisher;

    注意:Django 在选择所有数据时并没有使用 select * ,而是显示列出了所有字段。因为 select * 会更慢,而且最重要的是列出所有字段遵循了python 界的一个信条:明言胜于暗示

    数据过滤

    filter() 方法进行数据过滤

    >>> Publisher.objects.filter(name='Apress')
    [<Publisher: Apress>]

    可以使用多个 filter() 来缩小范围:

    >>> Publisher.objects.filter(country="U.S.A.", state_province="CA")
    [<Publisher: Apress>]

    进行模糊匹配:

    >>> Publisher.objects.filter(name__contains="press")
    [<Publisher: Apress>]
    # 在name和contains 之间有两个下划线。

    # Django 使用双下划线来表明会进行一些操作。

    转为原生的SQL:

    SELECT id, name, address, city, state_province, country, website
    FROM books_publisher
    WHERE name LIKE '%press%';

     

    获取单个对象

    使用get() 方法获取单个对象

    >>> Publisher.objects.get(name="Apress")
    <Publisher: Apress>

    这里返回的是单个对象,而不是列表。所以如果结果是多个对象,就会导致抛出异常。

    如果没有查询到结果也会抛出异常:

    >>> 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."

    数据排序

    使用order_by() 方法进行排序

    >>> Publisher.objects.order_by("name")
    [<Publisher: Apress>, <Publisher: O'Reilly>]

    对多个字段进行排序

    >>> Publisher.objects.order_by("state_province", "address")
     [<Publisher: Apress>, <Publisher: O'Reilly>]

    倒序,在前面加一个 - 前缀:

    >>> Publisher.objects.order_by("-name")
    [<Publisher: O'Reilly>, <Publisher: Apress>]

    尽管和灵活,但是每次都要用 order_by() 显得有点啰嗦。大多数只会通过某些字段进行排序,这中情况下Django 可以指定模型的缺省排序方式:

    class Publisher(models.Model):
        name = models.CharField(max_length=30)
        address = models.CharField(max_length=50)
        city = models.CharField(max_length=60)
        state_province = models.CharField(max_length=30)
        country = models.CharField(max_length=50)
        website = models.URLField()
     
        def __unicode__(self):
            return self.name
     
        class Meta:
            ordering = ['name']
    # 缺省排序字段

    class Meta ,内嵌于Publisher这个类的定义中(如果class Publisher是顶格的,那么class Meta 在它之下不要缩进4个空格)。可以在任意一个模型中使用Meta类,来设置一些与特定模型相关的选择。Meta 还可以设置其他选项。如果设置了这个选项,那么触发检索时特意额外使用了 order_by() ,否则,当你使用Django的数据库API去检索时,Publisher对象的相关返回值默认都会按照name字段排序。

    连锁查询

    同时进行过滤和排序查询

    >>> Publisher.objects.filter(country="U.S.A.").order_by("-name")
    [<Publisher: O'Reilly>, <Publisher: Apress>]

    限制返回的数据

    只显示第一条数据

    >>> Publisher.objects.order_by('name')[0]
    <Publisher: Apress>

    [ ] 内类似一个列表

    比如取第一条和第二条

    >>> Publisher.objects.order_by('name')[0:2]

    但是不支持 负索引

    更新多个对象

    在插入和更新数据中,使用save()方法,这个方法会更新一行里面的说有列。

    >>> p = Publisher.objects.get(name='Apress')
    >>> p.name = 'Apress Publishing'
    >>> p.save()
    
    #  原生的SQL语句:
    SELECT id, name, address, city, state_province, country, website
    FROM books_publisher
    WHERE name = 'Apress';
     
    UPDATE books_publisher SET
        name = 'Apress Publishing',
        address = '2855 Telegraph Ave.',
        city = 'Berkeley',
        state_province = 'CA',
        country = 'U.S.A.',
        website = 'http://www.apress.com'
    WHERE id = 52;
    #假设ID为52

    从原生的SQL来看save() 方法是更新了一行内的所有字段。

    如果想只更新某一个字段

    >>> Publisher.objects.filter(id=52).update(name='Apress Publishing')

    转为的原生SQL

    UPDATE books_publisher
    SET name = 'Apress Publishing'
    WHERE id = 52;

    update()方法对任何结果集都有效。因此可以同时更新多条记录

    >>> Publisher.objects.all().update(country='USA')
    2
    
    #update()方法会返回一个整数数值,表示受到影响的记录条数。

    删除对象

    使用delete()方法

    >>> p = Publisher.objects.get(name="O'Reilly")
    >>> p.delete()
    >>> Publisher.objects.all()
    [<Publisher: Apress Publishing>]
    
    # 同也可以删除多条数据
    >>> Publisher.objects.filter(country='USA').delete()
    >>> Publisher.objects.all().delete()
    >>> Publisher.objects.all()
    []

    在删除数据的时候要小心,一旦使用all()方法,所有的数据将会被删除。

    如果需要删除部分的数据,就不需要调用all()方法。

    >>> Publisher.objects.filter(country='USA').delete()
  • 相关阅读:
    localStorage用法
    es6写法
    div滚动条
    搜索框聚焦和失焦
    初步理解前端模块化开发
    clam安装
    div行高不确定,文字和图片居中
    html页面设置<span>的高度和宽度
    一款好用的wangEditor编辑器
    3月23 防360网页的示意图
  • 原文地址:https://www.cnblogs.com/binges/p/5488428.html
Copyright © 2011-2022 走看看