データベースとORM

17238 ワード

データベースとORM
一、データベースの構成
1 djangoのデフォルトでは、sqlite、mysql、oracle、postgresqlデータベースがサポートされています.
​ <1> sqlite
djangoのデフォルトではsqliteのデータベースが使用され、デフォルトではsqliteのデータベースドライバが付属しています.
エンジン名:django.db.backends.sqlite 3
​ <2> mysql
エンジン名:django.db.backends.mysql
2 mysqlドライバ
  • MySQLdb(mysql python)
  • mysqlclient
  • MySQL
  • PyMySQL(純pythonのmysqlドライバ)
  • 3 djangoのプロジェクトではsqliteデータベースがデフォルトで使用され、settingsでは次のような設定があります.
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3', 
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }
    

    データベースを変更するには、次のように変更する必要があります.
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql', 
            'NAME': 'books',    #       
            'USER': 'root',   #        
            'PASSWORD': '', #       
            'HOST': '', #       ,     localhost
            'PORT': '3306', #       
        }
    }
    

    注意:
    NAME       , mysql             ,    sqlite     db.sqlite3        
    
    USER PASSWORD             。
    
        ,      Django   ,         mysql。
    
      ,    ,   :no module named MySQLdb
    
        django         MySQLdb,  MySQLdb  py3     ,          PyMySQL
    
      ,              __init__,     :
    
    import pymysql
    pymysql.install_as_MySQLdb()
    
        !
    

    一、ORM表モデル
    テーブル(モデル)の作成:
    例:次の概念、フィールド、および関係を仮定します.
    作者モデル:作者に名前があります.
    著者詳細モデル:性別、emailアドレス、生年月日を含む詳細テーブルに著者詳細を配置し、著者詳細モデルと著者モデルの間には1対1の関係(one-to-one)(個人と彼の身分証明書の関係に似ている)があり、多くの場合、2つのテーブルに分割する必要はありません.ここでは一対一の概念を引き出すだけだ.
    出版社モデル:出版社には名前、住所、所在都市、省、国、ウェブサイトがあります.
    書籍モデル:書籍には本名と出版日があり、1冊の本には複数の著者がいる可能性があり、1人の著者も複数の本を書くことができるので、著者と書籍の関係は多対多の関連関係(many-to-many)であり、1冊の本は1つの出版社だけが出版すべきで、出版社と書籍は1対多の関連関係(one-to-many)であり、外部キーとも呼ばれている.
    from django.db import models
    class Publisher(models.Model): name = models.CharField(max_length=30, verbose_name=" ") 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 Meta: verbose_name = ' ' verbose_name_plural = verbose_name def __str__(self): return self.name class Author(models.Model): name = models.CharField(max_length=30) def __str__(self): return self.name class AuthorDetail(models.Model): sex = models.BooleanField(max_length=1, choices=((0, ' '),(1, ' '),)) email = models.EmailField() address = models.CharField(max_length=50) birthday = models.DateField() author = models.OneToOneField(Author) class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() price=models.DecimalField(max_digits=5,decimal_places=2,default=10) def __str__(self): return self.title

    分析コード:
    <1>各データモデルはdjango.db.models.Modelのサブクラスであり、親モデルには必要なすべてのデータベースとインタラクティブな方法が含まれています.データベースフィールドをきれいに定義する構文を提供します.
    <2>各モデルは、単一のデータベース・テーブル(複数対の複数の関係例外で、複数の関係テーブルが生成されます)に相当し、各プロパティもこのテーブルのフィールドです.属性名は、CharFieldなどのフィールド名で、データベースのフィールドタイプ(varcharなど)に相当します.他のタイプがデータベースのどのフィールドに対応しているかに注意してください.
    <3>モデル間の3つの関係:1対1、1対多、多対多.
    一対一:実質は主外部キー(author_idはforeign key)の関係に基づいて、外部キーにUNIQUE=Trueの属性を加えたものである.
    一対多:主外部キー関係です.(foreign key)
    多対多:(ManyToManyField)3番目のテーブルを自動的に作成します(もちろん、3番目のテーブルを自分で作成することもできます:2つのforeign key)
    1、ORMの増加(create,save)
    from app01.models import *
    
        #create   :   Author.objects.create(name='Alvin')
    
        #create   :   Author.objects.create(**{"name":"alex"})
    
        #save   :     author=Author(name="alvin")
                                author.save()
    
        #save   :     author=Author()
                                author.name="alvin"
                                author.save()
    

    **ポイントが来ました-------->**では、一対多または多対多の関係がある本の情報をどのように作成しますか?(1対多のpublisher 対多のauthorsのような外部キー関係のフィールドをどのように処理するか)
    #   (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
           Book.objects.create(title='php',
                                   publisher=pub_obj,   #             **_id 。
                                   publication_date='2017-7-7',
                                   price=99)
    
    #   (ManyToManyField()):
    
        #   :
        #            ,         .add        。
    
        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_set.add(*book)      。
        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)
        #-------------------
        #   :          ,       id.
    
        book.authors.add(1)       #book.authors.add(1,2)        id,    id      
        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()
    

    2、ORMの削除(delete)
    >>> Book.objects.filter(id=1).delete()
    (3, {'app01.Book_authors': 2, 'app01.Book': 1})
    

    私たちは表面的に1つの情報を削除しましたが、実際には3つ削除しました.私たちが削除したこの本はBook_にあるからです.authorsテーブルには、djangoのデフォルトのカスケード削除という2つの関連情報があります.
    3、ROMの変更(updateとsave)
    例:
    author=Author.objects.get(id=5)
    author.name='tenglan'
    author.save()
    
    #     get(id=2)
    Publister.objects.filter(id=2).update(name='American publisher')
    

    注意:
    <1>第2の方法ではgetを使用できない理由は、updateはQuerySetオブジェクトの方法であり、getはupdateメソッドがなくmodelオブジェクトを返し、filterは1つのQuerySetオブジェクトを返します(filterの中の条件は、name='alvin'、2つのname='alvin'の行データなど、複数の条件が一致する可能性があります).
    <2> “ ” , save() , 。 , 。
    #---------------- update          ----------------
        models.Book.objects.filter(id=3).update(title="PHP")
        ##sql:
        ##UPDATE "app01_book" SET "title" = 'PHP' WHERE "app01_book"."id" = 3; args=('PHP', 3)
    
    
    #--------------- save              ,   -----------
        obj=models.Book.objects.filter(id=3)[0]
        obj.title="Python"
        obj.save()
    # SELECT "app01_book"."id", "app01_book"."title", "app01_book"."price", 
    # "app01_book"."color", "app01_book"."page_num", 
    # "app01_book"."publisher_id" FROM "app01_book" WHERE "app01_book"."id" = 3 LIMIT 1; 
    # 
    # UPDATE "app01_book" SET "title" = 'Python', "price" = 3333, "color" = 'red', "page_num" = 556,
    # "publisher_id" = 1 WHERE "app01_book"."id" = 3;
    

    さらに、update()メソッドは、任意の結果セット(QuerySet)に対して有効であり、これは、影響を受けるレコードの数を表す複数のレコードupdate()メソッドを同時に更新できることを意味します.
    ここでupdateは整形を返すのでquery属性は使えません.オブジェクトを作成するたびに、対応するraw sqlを表示するには、settingsにログ・セクションを追加する必要があります.
    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console':{
                'level':'DEBUG',
                'class':'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level':'DEBUG',
            },
        }
    }
    

    4、ORMの調査(filterとvalue)
    4.1クエリーAPI
    #     API:
    
    #  <1>filter(**kwargs):                       
    
    #  <2>all():                       
    
    #  <3>get(**kwargs):                        ,          ,                         。
    
    #-----------                  :   objects.filter.values()--------
    
    #  <4>values(*field):            ValueQuerySet——     QuerySet,             model      ,            
                                         
    #  <5>exclude(**kwargs):                      
    
    #  <6>order_by(*field):             
    
    #  <7>reverse():                      
    
    #  <8>distinct():                        
    
    #  <9>values_list(*field):     values()    ,           ,values          
    
    #  <10>count():                        (QuerySet)     。
    
    #  <11>first():                      
    
    #  <12>last():                        
    
    #  <13>exists():               QuerySet    ,   True,    False
    
    ---------------        (__)       ----------------
    
    #    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")
    #    models.Tb1.objects.filter(name__icontains="ven") # icontains      
    #
    #    models.Tb1.objects.filter(id__range=[1, 2])   #   bettwen and
    #
    #    startswith,istartswith, endswith, iendswith,
    

    4.2 QuerySetと不活性機構
    不活性メカニズムとは、Publisher.objects.all()または.filter()などが、すぐにsqlを実行するのではなく、QuerySetを呼び出すときに実行される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])
    

    QuerySetの効率的な使用:
    <1>Django queryset    
    
         Django queryset           (row),          。  ,               ‘Dave’     :person_set = Person.objects.filter(first_name="Dave")
                           。     person_set,          ,          ,             。    ,            web         。
    
    <2>           ,     queryset    if queryset,            sql.      ,   settings    LOGGING(    )
            obj=models.Book.objects.filter(id=3)
            # for i in obj:
            #     print(i)
    
            # if obj:
            #     print("ok")
    
    <3>queryset   cache     queryset ,              ,     Django model。      (evaluation).  model    queryset   cache ,           queryset,             。
            obj=models.Book.objects.filter(id=3)
    
            # for i in obj:
            #     print(i)
                              ## models.Book.objects.filter(id=3).update(title="GO")
                              ## obj_new=models.Book.objects.filter(id=3)
            # for i in obj:
            #     print(i)   #LOGGING      
    
    <4>     if              queryset       cache,           !      ,   exists()          :
    
                obj = Book.objects.filter(id=4)
                #  exists()           queryset cache。
                if obj.exists():
                    print("hello world!")
    
    <5> queryset     ,cache               ,              。     ,   queryset         ,         。             queryset cache,    iterator()       ,          。
            objs = Book.objects.all().iterator()
            # iterator()               ,        
            for obj in objs:
                print(obj.name)
            #BUT,        ,             (next)      ,     
            for obj in objs:
                print(obj.name)
    
         #  ,  iterator()       cache,        queryset        。    iterator()      ,             queryset         。
    
      :
        queryset cache              ,                         。  exists() iterator()              。  ,         queryset cache,             。