zoukankan      html  css  js  c++  java
  • Django之models

    ORM映射关系

    class 表名(models.Model):
        """
         模型
        """
        字段名 = models.DateField() ----> 字段约束

    映射关系:

        表名  <-------> 类名
    
            字段  <-------> 属性
    
       表记录 <------->类实例对象
    验证模型语法是否正确的命令:
    python manage.py validate
    
    
    python manage.py check 

    check命令运行Django系统检查框架 - 一组用于验证Django项目的静态检查。如果一切正常,你会看到消息System check identified no issues (0 silenced)

    validate 命令检查你的模型的语法和逻辑是否正确。 如果一切正常,你会看到 errors found 消息。如果出错,请检查你输入的模型代码。 错误输出会给出非常有用的错误信息来帮助你修正你的模型。

    通过logging可以查看翻译成的sql语句:

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console':{
                'level':'DEBUG',
                'class':'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level':'DEBUG',
            },
        }
    }  
    settings文件里设置

    字段

    Django模型字段参考

     Django模型字段参考
    领域            默认的小部件                    描述
    AutoField            N / A                    一个IntegerField根据可用的ID自动递增。
    BigIntegerField        NumberInput                一个64位整数,很像一个IntegerField不同之处在于它是保证从适合数字-9223372036854775808到9223372036854775807
    BinaryField         N / A                    用于存储原始二进制数据的字段。它只支持bytes分配。请注意,此字段的功能有限。
    BooleanField    CheckboxInput                真实/虚假的领域。如果您需要接受null值,则改为使用NullBooleanField。
    CharField            TextInput                一个字符串字段,用于从小到大的字符串。对于大量的文本,使用TextField。CharField有一个额外的必要论证:max_length。字段的最大长度(以字符为单位)。
    DateField            DateInput                一个日期,用Python代表一个datetime.date实例。有两个额外的可选参数:auto_now,每次保存对象时auto_now_add自动将字段设置为现在,当对象第一次创建时自动将字段设置为now。
    DateTimeField    DateTimeInput                日期和时间,用Python表示的一个datetime.datetime实例。采取相同的额外论据DateField。
    DecimalField        TextInput                一个固定精度的十进制数,由Python在Decimal实例中表示。有两个必需的参数:max_digits和decimal_places。
    DurationField        TextInput                一个存储时间的字段 - 用Python在Python中建模timedelta。
    EmailField            TextInput                甲CharField使用EmailValidator验证输入。max_length默认为254。
    FileField            ClearableFileInput         一个文件上传字段。有关更多信息FileField,请参阅下一节。
    FilePathField            Select                 A CharField的选择仅限于文件系统上某个目录中的文件名。
    FloatField            NumberInput                一个由Python float实例表示的浮点数。注意当field.localize是False,默认的小部件TextInput
    ImageField            ClearableFileInput        继承所有的属性和方法FileField,但也验证上传的对象是一个有效的图像。其他height和width属性。需要枕头[70]库。
    IntegerField            NumberInput             一个整数。在-2147483648之间的值2147483647在Django支持的所有数据库中都是安全的。
    GenericIPAddressField    TextInput            字符串格式的IPv4或IPv6地址(如192.0.2.302a02:42fe :: 4)。
    NullBooleanField        NullBooleanSelect    像一个BooleanField,但允许NULL作为其中一个选项。
    PositiveIntegerField    NumberInput            一个整数。2147483647在Django支持的所有数据库中,从0到数值是安全的。
    SlugField                TextInput            S is是一个报纸术语。一个slu is是一个短的标签的东西,只包含字母,数字,下划线或连字符。
    SmallIntegerField        NumberInput            像一个IntegerField,但只允许某个点下的值。32767在Django支持的所有数据库中,-32768的值是安全的。
    TextField                Textarea            一个大的文本字段。如果您指定了一个max_length属性,它将反映在自动生成的表单字段的Textarea小部件中。
    TimeField                TextInput            一段时间,用Python表示一个datetime.time实例。
    URLField                URLInput            A CharField为URL。可选max_length参数。
    UUIDField                TextInput            用于存储通用唯一标识符的字段。使用Python的UUID类。
    
    关系字段: 
    
    ForeignKey              多对一的关系。需要一个位置参数:与模型相关的类。要创建一个递归关系 - 一个与自身有多对一关系的对象 - 使用models.ForeignKey('self')。
    ManyToManyField         多对多的关系。需要一个位置参数:与模型相关的类,其工作原理与ForeignKey递归和惰性关系完全相同。相关的对象可以添加,删除,或与字段的创建RelatedManager。
    OneToOneField           一对一的关系。概念上,这类似于ForeignKey用unique=True,但关系的相反侧将直接返回单个对象。作为以某种方式扩展另一个模型的模型的主键, 需要一个位置参数:与模型相关的

     Django通用字段选项

    选项                    描述
    null                如果True,Django将存储NULL数据库中的空值。默认是False。避免使用null诸如CharField和TextField之类的基于字符串的字段,因为空字符串值将始终以空字符串形式存储,而不是以字符串形式存储NULL。对于基于字符串的字段和基于非字符串的字段,如果您希望允许表单中的空值,则还需要设置blank = True。如果您想null使用BooleanField 接受值,请改为使用NullBooleanField。
    blank                如果True,该字段被允许为空白。默认是False。请注意,这是不同于null。null纯粹与数据库相关,而空白则与验证相关。
    choices                一个可迭代的(例如,一个列表或元组),其自身包含两个项目(例如[(A,B),(A,B)...])的可迭代项目,以用作该字段的选项。如果这是给定的,默认的表单小部件将是一个选择框与这些选择,而不是标准的文本字段。每个元组中的第一个元素是要在模型上设置的实际值,第二个元素是人类可读的名称。
    db_column            用于此字段的数据库列的名称。如果没有给出,Django将使用该字段的名称。
    db_index            如果True,将为此字段创建一个数据库索引。
    db_tablespace        如果此字段已编入索引,则用于此字段索引的数据库表空间的名称。默认值是项目的DEFAULT_INDEX_TABLESPACE设置(如果已设置)或db_tablespace模型(如果有)。如果后端不支持索引的表空间,则忽略此选项。
    default                字段的默认值。这可以是一个值或一个可调用的对象。如果可调用,则每次创建新对象时都会调用它。缺省值不能是可变对象(模型实例,列表,集合等),因为对该对象的同一实例的引用将用作所有新模型实例中的默认值。
    editable            如果False,该字段将不会显示在管理员或任何其他ModelForm中。在模型验证期间,它们也被跳过。默认值是True。
    error_messages        该error_messages参数让您覆盖该字段将引发的默认消息。传入一个与您要覆盖的错误消息匹配的密钥的字典。错误消息键包括null,blank,invalid,invalid_choice,unique和unique_for_date。
    help_text            额外的帮助文本与窗体小部件一起显示。即使您的字段没有在表单上使用,对于文档也是有用的。请注意,此值在自动生成的表单中不是 HTML转义的。如果您愿意,可以在help_text中包含HTML。
    primary_key            如果True这个字段是模型的主键。如果你没有为模型中的任何字段指定primary_key = True,Django会自动添加一个AutoField来保存主键,所以你不需要在任何字段上设置primary_key = True,除非你想覆盖默认的主键行为。主键字段是只读的。
    unique                如果True,这个字段在整个表中必须是唯一的。这是在数据库级和模型验证实施的。此选项在所有字段类型ManyToManyField(OneToOneField和除外)均有效FileField。
    unique_for_date        将其设置为DateField的名称或DateTimeField要求此字段对于日期字段的值是唯一的。举例来说,如果你有一个字段title有unique_for_date =” PUB_DATE”,那么Django的不允许的两个记录具有相同的入口title和pub_date。这是Model.validate_unique()在模型验证期间强制执行的,而不是在数据库级。
    unique_for_month    喜欢unique_for_date,但要求该领域是相对于本月独一无二的。
    unique_for_year        喜欢unique_for_date,但要求该领域是唯一的一年。
    verbose_name        该字段的人类可读名称。如果没有给出详细名称,Django将使用字段的属性名称自动创建它,将下划线转换为空格。
    validators            要为此字段运行的验证程序列表。

    建立模型

    作者模型:一个作者有姓名和年龄。

    作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对一的关系(one-to-one)

    出版商模型:出版商有名称,所在城市以及email。

    书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)。

    # models.py
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name=models.CharField( max_length=32)
        age=models.IntegerField()
     
        # 与AuthorDetail建立一对一的关系
        authorDetail=models.OneToOneField(to="AuthorDetail")
     
    class AuthorDetail(models.Model):
     
        nid = models.AutoField(primary_key=True)
        birthday=models.DateField()
        telephone=models.BigIntegerField()
        addr=models.CharField( max_length=64)
        
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name=models.CharField( max_length=32)
        city=models.CharField( max_length=32)
        email=models.EmailField()
     
     
    class Book(models.Model):
     
        nid = models.AutoField(primary_key=True)
        title = models.CharField( max_length=32)
        publishDate=models.DateField()
        price=models.DecimalField(max_digits=5,decimal_places=2)
        keepNum=models.IntegerField()
      commentNum=models.IntegerField() # 与Publish建立一对多的关系,外键字段建立在多的一方 publish=models.ForeignKey(to="Publish",to_field="nid") # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表 authors=models.ManyToManyField(to='Author')  

    注意事项:

    1、 表的名称myapp_modelName,是根据 模型中的元数据自动生成的,也可以覆写为别的名称  

    2、id 字段是自动添加的

    3、对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名

    4、这个例子中的CREATE TABLE SQL 语句使用PostgreSQL 语法格式,要注意的是Django 会根据settings 中指定的数据库类型来使用相应的SQL 语句。

    5、定义好模型之后,你需要告诉Django _使用_这些模型。你要做的就是修改配置文件中的INSTALL_APPSZ中设置,在其中添加models.py所在应用的名称。

    6、外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。

    数据化迁移

    注意: 上面的命令告诉Django你已经对你的模型进行了一些改变(在这种情况下,你创建了一个新模型)

    python manage.py sqlmigrate books 0001
    G:myObjectlog>python3 manage.py sqlmigrate app01 0001
    BEGIN;
    --
    -- Create model Author
    --
    CREATE TABLE "app01_author" ("nid" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(32) NOT NULL, "age" integer NOT NULL);
    --
    -- Create model AuthorDetail
    --
    CREATE TABLE "app01_authordetail" ("nid" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "birthday" date NOT NULL, "telephone" bigint NOT NULL, "addr" varchar(64
    ) NOT NULL);
    --
    -- Create model Book
    --
    CREATE TABLE "app01_book" ("nid" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(32) NOT NULL, "publishDate" date NOT NULL, "price" decimal NOT N
    ULL, "keepNum" integer NOT NULL);
    CREATE TABLE "app01_book_authors" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "book_id" integer NOT NULL REFERENCES "app01_book" ("nid"), "author_id" i
    nteger NOT NULL REFERENCES "app01_author" ("nid"));
    --
    -- Create model Publish
    --
    CREATE TABLE "app01_publish" ("nid" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(32) NOT NULL, "city" varchar(32) NOT NULL, "email" varchar(254)
    NOT NULL);
    --
    -- Add field publish to book
    --
    ALTER TABLE "app01_book" RENAME TO "app01_book__old";
    CREATE TABLE "app01_book" ("nid" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(32) NOT NULL, "publishDate" date NOT NULL, "price" decimal NOT NUL
    L, "keepNum" integer NOT NULL, "publish_id" integer NOT NULL REFERENCES "app01_publish" ("nid"));
    INSERT INTO "app01_book" ("nid", "title", "publishDate", "price", "keepNum", "publish_id") SELECT "nid", "title", "publishDate", "price", "keepNum", NULL FROM
    "app01_book__old";
    DROP TABLE "app01_book__old";
    CREATE INDEX "app01_book_publish_id_d96d3535" ON "app01_book" ("publish_id");
    --
    -- Add field authorDetail to author
    --
    ALTER TABLE "app01_author" RENAME TO "app01_author__old";
    CREATE TABLE "app01_author" ("nid" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" varchar(32) NOT NULL, "age" integer NOT NULL, "authorDetail_id" integer N
    OT NULL UNIQUE REFERENCES "app01_authordetail" ("nid"));
    INSERT INTO "app01_author" ("nid", "name", "age", "authorDetail_id") SELECT "nid", "name", "age", NULL FROM "app01_author__old";
    DROP TABLE "app01_author__old";
    COMMIT;
    View Code

    qlmigrate命令实际上只会显示要进行操作的语句。不会创建表或以其他方式触摸数据库 - 它只是将输出显示在屏幕上,以便您可以查看SQL Django在执行时会执行哪些操作 。

    提交数据库

    迁移是Django将您对模型进行的更改(添加字段,删除模型等)传播到数据库模式的方式

    增删改

     添加表记录

     普通字段
    方式1
    publish_obj=Publish(name="人民出版社",city="北京",email="renMin@163.com")
    publish_obj.save() # 将数据保存到数据库

     

    方式2 返回值publish_obj是添加的记录对象
    publish_obj=Publish.objects.create(name="人民出版社",city="北京",email="renMin@163.com")


    方式3 以字典传参的方式
    Publish.objects.create(**request.POST.dict())
     外键字段
    方式1: 传入对象
       publish_obj=Publish.objects.get(nid=1)
       Book.objects.create(title="金瓶眉",publishDate="2012-12-12",price=665,pageNum=334,publish=publish_obj)
     
    方式2: 传入对象下的属性
       Book.objects.create(title="金瓶眉",publishDate="2012-12-12",price=665,pageNum=334,publish_id=1)  
    >>> models.Book.objects.create(title="金瓶眉",publishDate="2012-12-12",price=665,keepNum=334, publish=publish_obj)
    <Book: Book object>
    >>> publish_obj=models.Publish.objects.get(nid=1)
    >>> publish_obj
    <Publish: Publish object>
    >>> models.Book.objects.create(title="金瓶mei",publishDate="2012-12-12",price=665,keepNum=334, publish=publish_obj)
    <Book: Book object>
    >>> models.Book.objects.filter(title='金瓶mei').values()
    <QuerySet [{'nid': 2, 'title': '金瓶mei', 'publishDate': datetime.date(2012, 12, 12), 'price': Decimal('665.00'), 'keepNum': 334, 'publish_id': 1}]>

     

    既然models模型是以python中的类来建立的。 那么类常用的逻辑,models都应该支持, 比如上面, pulish就是一个类实例化而来 ,那就能调用它的属性。

    多对多字段
    book_obj=Book.objects.create(title="追风筝的人",publishDate="2012-11-12",price=69,keepNum=314,publish_id=1)
     
    author_yuan=Author.objects.create(name="yuan",age=23,authorDetail_id=1)
    author_egon=Author.objects.create(name="egon",age=32,authorDetail_id=2)
     
    book_obj.authors.add(author_egon,author_yuan)    #  将某个特定的 model 对象添加到被关联对象集合中。   =======    book_obj.authors.add(*[])
     
    book_obj.authors.create()      #创建并保存一个新对象,然后将这个对象加被关联对象的集合中,然后返回这个新对象。

     解除关系:

    book_obj.authors.remove()     # 将某个特定的对象从被关联对象集合中去除。    ======   book_obj.authors.remove(*[])
    book_obj.authors.clear()       #清空被关联对象集合。

    add(obj1[, obj2, ...])

    把指定的模型对象添加到关联对象集中。
    
    例如:
    
    >>> b = Blog.objects.get(id=1)
    >>> e = Entry.objects.get(id=234)
    >>> b.entry_set.add(e) # Associates Entry e with Blog b.
    在上面的例子中,对于ForeignKey关系,e.save()由关联管理器调用,执行更新操作。然而,在多对多关系中使用add()并不会调用任何 save()方法,而是由QuerySet.bulk_create()创建关系。
    
    延伸:
    
    # 1 *[]的使用
    >>> book_obj = Book.objects.get(id=1)
    >>> author_list = Author.objects.filter(id__gt=2)
    >>> book_obj.authors.add(*author_list)
    
    
    # 2 直接绑定主键
    book_obj.authors.add(*[1,3])  # 将id=1和id=3的作者对象添加到这本书的作者集合中
                                  # 应用: 添加或者编辑时,提交作者信息时可以用到. 

    create(**kwargs)

    创建一个新的对象,保存对象,并将它添加到关联对象集之中。返回新创建的对象:
    
    >>> b = Blog.objects.get(id=1)
    >>> e = b.entry_set.create(
    ...     headline='Hello',
    ...     body_text='Hi',
    ...     pub_date=datetime.date(2005, 1, 1)
    ... )
    
    # No need to call e.save() at this point -- it's already been saved.
    这完全等价于(不过更加简洁于):
    
    >>> b = Blog.objects.get(id=1)
    >>> e = Entry(
    ...     blog=b,
    ...     headline='Hello',
    ...     body_text='Hi',
    ...     pub_date=datetime.date(2005, 1, 1)
    ... )
    >>> e.save(force_insert=True)
    要注意我们并不需要指定模型中用于定义关系的关键词参数。在上面的例子中,我们并没有传入blog参数给create()。Django会明白新的 Entry对象blog 应该添加到b中。

    remove(obj1[, obj2, ...])

    从关联对象集中移除执行的模型对象:
    
    >>> b = Blog.objects.get(id=1)
    >>> e = Entry.objects.get(id=234)
    >>> b.entry_set.remove(e) # Disassociates Entry e from Blog b.
    对于ForeignKey对象,这个方法仅在null=True时存在。

    clear()

    从关联对象集中移除一切对象。
    
    >>> b = Blog.objects.get(id=1)
    >>> b.entry_set.clear()
    注意这样不会删除对象 —— 只会删除他们之间的关联。
    
    就像 remove() 方法一样,clear()只能在 null=True的ForeignKey上被调用。

    set()方法

    先清空,在设置,编辑书籍时即可用到

    注意 : 对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法。

    直接赋值:

    通过赋值一个新的可迭代的对象,关联对象集可以被整体替换掉。

    >>> new_list = [obj1, obj2, obj3]
    >>> e.related_set = new_list

    如果外键关系满足null=True,关联管理器会在添加new_list中的内容之前,首先调用clear()方法来解除关联集中一切已存在对象的关联。否则, new_list中的对象会在已存在的关联的基础上被添加

    删除表记录

    删除方法就是 delete()。它运行时立即删除对象而不返回任何值。例如:

    e.delete()

    你也可以一次性删除多个对象。每个 QuerySet 都有一个 delete() 方法,它一次性删除 QuerySet 中所有的对象。

    例如,下面的代码将删除 pub_date 是2005年的 Entry 对象:

    Entry.objects.filter(pub_date__year=2005).delete()

    要牢记这一点:无论在什么情况下,QuerySet 中的 delete() 方法都只使用一条 SQL 语句一次性删除所有对象,而并不是分别删除每个对象。如果你想使用在 model 中自定义的 delete() 方法,就要自行调用每个对象的delete 方法。(例如,遍历 QuerySet,在每个对象上调用 delete()方法),而不是使用 QuerySet 中的 delete()方法。

    在 Django 删除对象时,会模仿 SQL 约束 ON DELETE CASCADE 的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象。例如:

    b = Blog.objects.get(pk=1)
    # This will delete the Blog and all of its Entry objects.
    b.delete()

    要注意的是: delete() 方法是 QuerySet 上的方法,但并不适用于 Manager 本身。这是一种保护机制,是为了避免意外地调用 Entry.objects.delete() 方法导致 所有的 记录被误删除。如果你确认要删除所有的对象,那么你必须显式地调用:

    Entry.objects.all().delete()  

    如果不想级联删除,可以设置为:

    pubHouse = models.ForeignKey(to='Publisher', on_delete=models.SET_NULL, blank=True, null=True)

    修改表记录

    注意:

    <1> 第二种方式修改不能用get的原因是:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象(filter里面的条件可能有多个条件符合,比如name='alvin',可能有两个name='alvin'的行数据)。

    <2>在“插入和更新数据”小节中,我们有提到模型的save()方法,这个方法会更新一行里的所有列。 而某些情况下,我们只需要更新行里的某几列。

    此外,update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录update()方法会返回一个整型数值,表示受影响的记录条数。

    注意,这里因为update返回的是一个整形,所以没法用query属性;对于每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分

  • 相关阅读:
    day23,xml 和面向对象
    day22,ConfigParser,subprocess,xlrd三个模块
    re的总结
    day20,日志和正则表达式
    day19,序列化与反序列化总结,和其它的有些模块
    字符串的内建函数
    字符串和编码
    python解释器分类
    git &github 快速入门
    do export method of oracle all database tables with dmp files.
  • 原文地址:https://www.cnblogs.com/wangyuanming/p/8001353.html
Copyright © 2011-2022 走看看