zoukankan      html  css  js  c++  java
  • Django学习笔记之——Models

    Django里的模型是对数据库对表的一次封装,是应用业务与数据之间的桥梁。

    1. 模型的Fields

    在上一节,我们在mysite/blog/models.py中创建了BlogPost这个Model。

    from django.db import models
    class BlogPost(models.Model):
        title = models.CharField(max_length=150)
        body = models.TextField()
        timestamp = models.DateTimeField()
    

    BlogPost里用了CharField,TextField, TextField域。难道就只有这三种,不可能!

    如下,我列出了其它的Field,并表明了它们的继承关系:

    Field
    |--AutoField
    |--BooleanField
    |--CharField
    |  |--EmailField
    |  |--SlugField
    |  `--URLField
    |--DateField
    |  `--DateTimeField
    |--DecimalField
    |--FilePathField
    |--FloatField
    |--IntegerField
    |  |--BigIntegerField
    |  |--PositiveIntegerField
    |  `--PositiveSmallIntegerField
    |--IPAddressField
    |--GenericIPAddressField
    |--NullBooleanField
    |--TextField
    |--TimeField
    `--BinaryField
    

    别问我是怎么知道的。看源码呀~在 django/db/models/fields/__init__.py 中定义。

    如果你是去看了这个文件,那么不难知道 Field类的__init__(self)函数带了很多参数吧。

    Field类在构造的时候可以指定以下参数:
    verbose_name=None   #显示名
    name=None           #域名
    primary_key=False   #是否为主键
    max_length=None     #在CharFiled中用到
    unique=False        #是否唯一
    blank=False
    null=False          #是否允许为空
    db_index=False
    rel=None
    default=NOT_PROVIDED
    editable=True       #是否可编辑
    serialize=True
    unique_for_date=None
    unique_for_month=None
    unique_for_year=None
    choices=None
    help_text=''
    db_column=None
    db_tablespace=None
    auto_created=False
    validators=[]
    error_messages=None

    models.ForeignKey
    ~~~~~~~~~~~~~~~~~
    可以用models.ForeignKey()指定外键,如在models.py中:
    _______________________________________________
    class Author(models.Model):
        name = models.CharField(max_length=100)

    class Book(models.Model):
        title = models.CharField(max_length=100)
        author = models.ForeignKey(Author) #定义外键
    -----------------------------------------------
    注:Author必须在Book之前定义。如果不想有这样的限制,那么在ForeignKey()中以
    "Author"字符串对象作为参数传入。
    _______________________________________________
    class Book(models.Model):
        title = models.CharField(max_length=100)
        author = models.ForeignKey('Author') # 注意,这里用的是类名称,而不是类
                                             # 本身
    class Author(models.Model):
        name = models.CharField(max_length=100)
    -----------------------------------------------

    在外键的支持下,可以实现数据库中多表查询的功能。比如查到与该书作者的所有书:
    ________________________________________________
    book_title = "C++程序设计"
    this_book = Book.objects.get(title=book_title)  # 找到title为"C++程序设计"
                                                    # 的book对象this_book
    author = this_book.author   # 由this_book获得作者对象author
    books = author.book_set.all()   # 根据author获得所有的书,得到books数组
                   ^^^^^^^^
    for book in books: # 打印每一本书
        print(book.title)
    ------------------------------------------------
    在Book中加入了ForeignKey('Author')之后,Django会在Author对象中添加一个属性
    叫:book_set。
    但是,如果用的是ForeignKey('Author', related_name="books"),也就是告诉django
    在Author端对应的属性名叫"books",而不再是django默认的"book_set"了。

    models.ManyToManyField
    ~~~~~~~~~~~~~~~~~~~~~~
    顾名思意,就是多对多域。当两个表存在多对多的关系时,这就很有用。
    比如:一名作者可能写了多本书,一本书也可能由多名作者共同编写。
    _______________________________________________
    class Author(models.Model):
        name = models.CharField(max_length=100)

    class Book(models.Model):
        title = models.CharField(max_length=100)
        author = models.ManyToManyField(Author)
    -----------------------------------------------
    其实,Django为我们建了另一个book_book_author的表。

    如下为book_book_author的创建明细:
    __________________________________________________________________________
    sqlite> .schema book_book_author
    CREATE TABLE "book_book_author" (
        "id" integer NOT NULL PRIMARY KEY,
        "book_id" varchar(50) NOT NULL,
        "author_id" integer NOT NULL REFERENCES "book_author" ("id"),
        UNIQUE ("book_id", "author_id")
        );
    CREATE INDEX "book_book_author_36c249d7" ON "book_book_author" ("book_id");
    CREATE INDEX "book_book_author_e969df21" ON "book_book_author" ("author_id");
    --------------------------------------------------------------------------

    那么,这种多对多的关系在view中怎么使用呢?

    models.OneToOneField一对一关系
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    模型继承关系
    ~~~~~~~~~~~~
    在模型类中定义Meta内部类,并指定Meta.abstract = True时,表示该模型为抽象模型
    ,即只用来被子模型类派生而不生成实际的模型。
    这时,Django在./manage.py syncdb时就不会为该模型创建表。比如:Person为人的模
    型,里面定义了人的基本属性。Student与Teacher继承于它。在同步数据库时,我们不
    能为Person创建一张表吧。如下:
    ________________________________________________
    class Person(models.Model):
        name = models.CharField(max_length=50)
        gender = models.PositiveSmallIntegerField()
        birthday = models.DateField()

        def __unicode__(self):
            return self.name

        class Meta:
            abstract = True

    class Teacher(Person):
        pass

    class Student(Person):
        pass
    ------------------------------------------------
    对了,记得给模型定义__unicode__方法。这用利于让admin知道模型对象该怎么显示。

    Meta嵌套类
    ~~~~~~~~~~

    在前面有两处提到了Meta类,一处是在blog排序时,另一处就是上面的虚继承。
    Meta的用法是嵌套在Model类里面,用于说明附加的信息。

    数据查询
    ~~~~~~~~
    每个Model都有一个objects属性,而这个objects属性具有以下方法:
    Model.objects.all()       # 获取所有对象的QuerySet
    Model.objects.filter()    # 获取满足条件的对象的QuerySet
    Model.objects.exclude()   # 获取不满足条件的对象的QuerySet
    Model.objects.get()       # 获取单个符合条件的对象的QuerySet

    QuerySet会将查询条件转换成SQL语句,并获得执行结果。
    示例:
    ____________________________________________________________
    # 找出John Doe
    Person.objects.filter(last="Doe").filter(first="John")

    # 找出逾期不还的书
    today = datetime.now()
    overdue_books = book_queryset.filter(due_date__lt = today)
                                                 ^^^^
                                     意恩是:due_date < today
    # 注:除了__lt,还有:__gt

    # 查询结果排序,并提取前5个
    all_sorted_first = Person.objects.all().order_by('first')[:5]

    # 使用select_related执行简单的join操作
    Person.objects.all().select_related('address', depth=1)
    -------------------------------------------------------------

    用Q()让条件灵活组合
    ~~~~~~~~~~~~~~~~~~~
    使用Q()来封装查询条件,与 & | ~ 配合,形成组合条件。
    _______________________________________________________________________
    Person.objects.filter(
        Q(last="Doe") |
        (Q(last="Smith") & Q(first="John") & ~Q(middle__startswith="W"))
    )

    first_names = ['John', 'Jane', 'Jeremy']
    first_name_keywords = Q()
    for name in first_names:
        first_name_keywords = first_name_keywords | Q(first=name)
    specific_does = Person.objects.filter(last="Doe").filter(first_name_keywords)
    ----------------------------------------------------------------------

    用extra()提供其它的功能
    ~~~~~~~~~~~~~~~~~~~~~~~

    ## select提供简单数据
    # SELECT age, (age > 18) as is_adult FROM myapp_person;
    Person.objects.all().extra(select={'is_adult': "age > 18"})

    ## where提供查询条件
    # SELECT * FROM myapp_person WHERE first||last ILIKE 'jeffrey%';
    Person.objects.all().extra(where=["first||last ILIKE 'jeffrey%'"])

    ## table连接其它表
    # SELECT * FROM myapp_book, myapp_person WHERE last = author_last
    Book.objects.all().extra(table=['myapp_person'], where=['last = author_last'])

    ## params添参数
    # !! 错误的方式 !!
    first_name = 'Joe'  # 如果first_name中有SQL特定字符就会出现漏洞
    Person.objects.all().extra(where=["first = '%s'" % first_name])
    # 正确方式
    Person.objects.all().extra(where=["first = '%s'"], params=[first_name])
    #                                                ^^^^^^^^^^^^^^^^^^^^^

    数据库导入导出
    ~~~~~~~~~~~~~~
    # 将book应用的数据导出到book.json文件中去
    ./manage.py dumpdata --indent=4 book > book.json

    自定义SQL查询
    ~~~~~~~~~~~~~
    如果前面的QuerySet无法满足特殊的查询要求,那就让我们自己来指定select语句吧。
    如下:
    _______________________________________________________________________
    from django.db import connection
    cursor = connection.cursor()
    cursor.execute("SELECT first, last FROM myapp_person WHERE last='Doe'")
    doe_rows = cursor.fetchall()
    for row in doe_rows:
        print("%s %s" % (row[0], row[1]))
    -----------------------------------------------------------------------

    转载,侵删

  • 相关阅读:
    AT SELECTIONSCREEN的用法
    ADD的用法
    ~的用法
    DIV+CSS布局
    CSS 列表
    CSS 文本
    VC include 路径解析
    CRITICAL_SECTION临界区学习
    UI设计时要注意的几个方面
    使用和扩展marshal_as库
  • 原文地址:https://www.cnblogs.com/yinsjun/p/7228072.html
Copyright © 2011-2022 走看看