django 模型


一、project 與app之間的關系

  1個project中可包含多個app

  eg:包含兩個app的project的結構

  

  project:存放對各個app的配置

  app:真正的業務代碼,包含models和views,以package的形式存在,

     容易完整移植到其他project,從而被多個project復用    

二、用python代碼定義表結構

  1、python通過models實現create table的操作:

from django.db import models

class Book(models.Model):
    name = models.CharField(max_length=50)
    pub_date = models.DateField()

  2、python代碼定義表結構的好處

    1)無需考慮不同數據庫平台的兼容性問題,無論是mysql,mongodb,redis

       從python代碼create table的方式都是一樣的

    2)開發者專注於python代碼,不用再去寫sql,減輕大腦負擔

    3)django框架中有特定的數據類型, eg:email類型,url類型

    4)性能考慮:不用每次系統啟動或者發起請求都要先檢查一下數據庫結構,而是

        可以根據python代碼就知道了目標數據庫的結構。

  3、缺點

    每次修改了python數據庫結構后,需要手動修改數據庫中的表結構

 三、測試models在django中的使用

  1、基本准備

    1)創建django project和app

      

    2)修改settings.py中的基本設置

      模板位置:

TEMPLATE_DIRS = (
    os.path.join(BASE_DIR, 'templates'),
)

      數據庫連接:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_db',
        'USER': 'root',
        'PASSWORD': 'feng',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

      僅安裝當前使用的app:

INSTALLED_APPS = (
#    'django.contrib.admin',
#    'django.contrib.auth',
#    'django.contrib.contenttypes',
#    'django.contrib.sessions',
#    'django.contrib.messages',
#    'django.contrib.staticfiles',
    'model_test_app',
)

MIDDLEWARE_CLASSES = (
#    'django.contrib.sessions.middleware.SessionMiddleware',
#    'django.middleware.common.CommonMiddleware',
#    'django.middleware.csrf.CsrfViewMiddleware',
#    'django.contrib.auth.middleware.AuthenticationMiddleware',
#    'django.contrib.messages.middleware.MessageMiddleware',
#   'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

    執行ctrl+r+syndbc時,只會根據INSTALLED_APPS設置的app來檢查

    對應的數據庫表是否存在,其他沒有設置的app不會被檢查。

    3)此時數據庫中的狀態(之前有過其他project的測試數據)

      

    2、通過models.py定義表結構

     1)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()

    以上python定義表結構涉及到的知識點:

    a)字段類型:

        字符串類型,URL類型,Email類型,Date類型 

    b)多對多關系:

         authors = models.ManyToManyField(Author)

    c)外鍵:

         publisher = models.ForeignKey(Publisher)

    d)關於主鍵:

         無需顯式指明主鍵,django會自動為每個模型生成一個自增的整數id作為主鍵

    2)通過python在數據庫中創建表

    a)檢查model的語法和邏輯是否正確:ctrl+r+validate

        

    b)生成建表的sql語句:ctrl+r+sql

"D:\DevPlatform\PyCharm 3.1.3\bin\runnerw.exe" C:\Python27\python.exe "D:\DevPlatform\PyCharm 3.1.3\helpers\pycharm\django_manage.py" sql model_test_app D:/ProgramData/python/model_test
BEGIN;
CREATE TABLE `model_test_app_publisher` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `name` varchar(30) NOT NULL,
    `address` varchar(50) NOT NULL,
    `city` varchar(60) NOT NULL,
    `state_province` varchar(30) NOT NULL,
    `country` varchar(50) NOT NULL,
    `website` varchar(200) NOT NULL
)
;
CREATE TABLE `model_test_app_author` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `first_name` varchar(30) NOT NULL,
    `last_name` varchar(40) NOT NULL,
    `email` varchar(75) NOT NULL
)
;
CREATE TABLE `model_test_app_book_authors` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `book_id` integer NOT NULL,
    `author_id` integer NOT NULL,
    UNIQUE (`book_id`, `author_id`)
)
;
ALTER TABLE `model_test_app_book_authors` ADD CONSTRAINT `author_id_refs_id_206f10ad` FOREIGN KEY (`author_id`) REFERENCES `model_test_app_author` (`id`);
CREATE TABLE `model_test_app_book` (
    `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
    `title` varchar(100) NOT NULL,
    `publisher_id` integer NOT NULL,
    `publication_date` date NOT NULL
)
;
ALTER TABLE `model_test_app_book` ADD CONSTRAINT `publisher_id_refs_id_f51d29ce` FOREIGN KEY (`publisher_id`) REFERENCES `model_test_app_publisher` (`id`);
ALTER TABLE `model_test_app_book_authors` ADD CONSTRAINT `book_id_refs_id_6f49ea9b` FOREIGN KEY (`book_id`) REFERENCES `model_test_app_book` (`id`);

COMMIT;

Process finished with exit code 0

    此處多生成了一張表:model_test_app_book_authors用於描述多對多關系

    c)同步sql語句到數據庫: ctrl+r+syncdb

    

    運行之后數據庫中的情況:

    

    說明:1、實際上可以修改自動生成表名的規則

       2、重復執行ctrl+r+syndbc是安全的,不會生成重復的表也不會沖掉舊數據

       3、只會根據INSTALLED_APPS設置的app來檢查對應的數據庫表是否存在

   3、基本數據訪問

      views.py

#coding:utf-8
from django.shortcuts import render
from django.shortcuts import render_to_response
from model_test_app.models import Publisher

# Create your views here.
def db_op(request):
    #刪除
    #Publisher.objects.filter(name='Apress').delete()
    Publisher.objects.all().delete()
    #新增
    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.objects.create(name="O'Reilly",
    address='10 Fawcett St.', city='Cambridge',
    state_province='MA', country='U.S.A.',
    website='http://www.oreilly.com/')

    #更新
    pub=Publisher.objects.get(name='Apress')
    pub.country='China'
    pub.save()
    #查詢
    publisher_list = Publisher.objects.all()
    for publisher in publisher_list:
        print publisher.name,publisher.country

    return render_to_response('db_op.html', locals())

    db_op.html:

<!DOCTYPE html>
<html>
<head>
    <title>數據庫操作</title>
</head>
<body>
    <p>操作結果:</p>
    <p>
        <ul>
            {% for publisher in publisher_list %}
            <li>{{ publisher.name }}, {{publisher.country}}</li>
            {% endfor %}
        </ul>
    </p>
</body>
</html>

      執行結果:

      頁面:

     

      后台輸出:

     

    4、模型中的__unicode__()方法:

     用於自定義輸出“模型”的字符串內容,類似於java中的toString方法

     views.py中的輸出操作:

def db_op(request):
    #查詢
    publisher_list = Publisher.objects.all()
    print publisher_list

    return render_to_response('db_op.html', locals())

    未添加__unicode__()方法時:

    

    增加了__unicode__()方法時:

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()

    #def __unicode__(self):
        #return self.name
    def __unicode__(self):
        return u'%s, %s'%(self.name,self.country)

    

   5、關於update操作中的p.save()

    並不是只更新修改過的那個字段,所有的字段都會被更新

   6、django中實現where條件

    1)查詢中對字段進行過濾

def db_op(request):
    #查詢
    publisher_list = Publisher.objects.filter(name='Apress',country='China')

    print publisher_list

    return render_to_response('db_op.html', locals())

     執行結果:

     

    2)like關鍵詞在django中的實現

def db_op(request):
    #查詢
    publisher_list = Publisher.objects.filter(name__contains='eil')

    #publisher_list = Publisher.objects.all()
    print publisher_list

    return render_to_response('db_op.html', locals())

    相當於:where name like '%eil%'

    執行結果:

    

    3)get方法獲取單條記錄:

       a)恰好返回1條記錄時

def db_op(request):

    try:
        pub=Publisher.objects.get(name__contains='eil')
    except:
        print '獲取單條記錄發生異常'
    else:
        print pub.name

    return render_to_response('db_op.html', locals())

      

       b)返回兩條記錄時

def db_op(request):

    try:
        pub=Publisher.objects.get(name__contains='e')
    except:
        print '獲取單條記錄發生異常'
    else:
        print pub.name

    return render_to_response('db_op.html', locals())

      

      c)沒有記錄返回時

def db_op(request):

    try:
        pub=Publisher.objects.get(name__contains='eeeeeee')
    except:
        print '獲取單條記錄發生異常'
    else:
        print pub.name

    return render_to_response('db_op.html', locals())

      

     4)排序     

def db_op(request):
    #升序
    publisher_list=Publisher.objects.order_by("name","country")
    print publisher_list
    #降序
    publisher_list2=Publisher.objects.order_by("-name","country")
    print publisher_list2

    return render_to_response('db_op.html', locals())

      執行結果:

      

      模型中指定默認排序規則:

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 u'%s, %s'%(self.name,self.country)

    class Meta:
        ordering = ['-name']
def db_op(request):

    publisher_list=Publisher.objects.all()
    print publisher_list

    return render_to_response('db_op.html', locals())

    執行結果:

    

      5)where和order by同時使用

def db_op(request):

    publisher_list=Publisher.objects.filter(name="Apress").order_by("name")
    print publisher_list

    return render_to_response('db_op.html', locals())

     

    6)limit的實現

def db_op(request):
    #返回單個記錄
    pub=Publisher.objects.order_by("name")[0]
    print pub

    #返回記錄列表
    publisher_list=Publisher.objects.order_by("name")[0:100]
    print publisher_list

    return render_to_response('db_op.html', locals())

     執行結果:

     

    7)更新記錄中的某些字段,而不是所有字段

       使用結果集QuerySet的update()方法,而不是p.save()

def db_op(request):
    #返回記錄列表
    affectRowCount=Publisher.objects.filter(name__contains='e').update(country='Japan')
    print affectRowCount

    publisher_list=Publisher.objects.all()
    print publisher_list

    return render_to_response('db_op.html', locals())

      執行結果:

      

    8)刪除一些記錄,而不是單條記錄

       使用 使用結果集QuerySet的delete()方法,而不是先get單條p,再p.delete()

def db_op(request):
    #返回記錄列表
    affectRowCount=Publisher.objects.filter(name='Apress').delete()
    print affectRowCount

    publisher_list=Publisher.objects.all()
    print publisher_list

    return render_to_response('db_op.html', locals())

      執行結果:

      

     ps:不會返回被刪除的行數

   參考:http://djangobook.py3k.cn/2.0/chapter05/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM