Django開發:(3.1)ORM:單表操做

MVC或者MVC框架中包括一個重要的部分,就是ORM,它實現了數據模型與數據庫的解耦,即數據模型的設計不須要依賴於特定的數據庫,經過簡單的配置就能夠輕鬆更換數據庫,這極大的減輕了開發人員的工做量,不須要面對因數據庫變動而致使的無效勞動css

ORM是「對象-關係-映射」的簡稱。html

Mysql中的表對應python中的類,表的字段對應類的屬性,表的記錄對應類的實例化的對象python

 

單表操做

建立表

1. 建立模型mysql

 

建立名爲app01的app,在app01下的models.py中建立模型:linux

from django.db import models

# Create your models here.

class Book(models.Model):  # 類名能夠隨便起,但必定得繼承 models.Model
    id = models.AutoField(primary_key=True)  # AutoField表示自增字段; primary_key=True 表示是主鍵
    title = models.CharField(max_length=32)
    # state = models.BooleanField()
    pub_date = models.DateField()
    price = models.DecimalField(max_digits=8,decimal_places=2)
    publish = models.CharField(max_length=32)

2. 更多字段和參數git

每一個字段有一些特有的參數,例如,CharField須要max_length參數來指定VARCHAR數據庫字段的大小。還有一些適用於全部字段的通用參數。sql

3. settings配置數據庫

若想將模型轉爲mysql數據庫中的表,須要在settings中配置:django

DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.mysql',
        'NAME':'orm', # 要鏈接的數據庫,鏈接前須要先建立好
        'USER':'root',  # 鏈接數據庫的用戶名
        'PASSWORD':'tj037778',  # 鏈接數據庫的密碼
        'HOST':'127.0.0.1',  # 鏈接主機
        'PORT':3306  # 端口
    }
}

注意1:NAME即數據庫的名字,在mysql鏈接前該數據庫必須已經建立(ORM只能處理到表這一層,數據庫操做不了),而上面的sqlite數據庫下的db.sqlite3則是項目自動建立 USER和PASSWORD分別是數據庫的用戶名和密碼。設置完後,再啓動咱們的Django項目前,咱們須要激活咱們的mysql。而後,啓動項目,會報錯:no module named MySQLdb 。這是由於django默認你導入的驅動是MySQLdb,但是MySQLdb 對於py3有很大問題,因此咱們須要的驅動是PyMySQL 因此,咱們只須要找到項目名(project)文件下的__init__(ORM/ORM/__init__.py),在裏面寫入:bootstrap

import pymysql

pymysql.install_as_MySQLdb()

最後經過兩條數據庫遷移命令便可在指定的數據庫中建立表 :

python manage.py makemigrations
python manage.py migrate
# makemigrations 後並無在數據庫生成表,而是在對應的 migrationsns 文件夾下生成了 py 文件
# migrate 時會執行 migrations文件夾下的 py文件(至於執行哪一個py文件,程序會先去 django自帶的 django_migrations 這張表中去查,若是migrationsns 文件夾下人某個py文件在 django_migrations 這張表已經存在,則 migrate時則會跳過這個py文件不執行,即已經執行過的py文件會存放在 django_migrations表中)
# 修改數據庫的時候,儘可能用 makemigrations 和 migrate,不要直接在Navicat 中修改

注意2:確保配置文件中的INSTALLED_APPS中寫入咱們建立的app名稱

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
]

注意3:若是報錯以下:

django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.3 or newer is required; you have 0.7.11.None

MySQLclient目前只支持到python3.4,所以若是使用的更高版本的python,須要修改以下:

經過查找路徑:D:\python\Lib\site-packages\django\db\backends\mysql\base.py

把裏面的

if version < (1, 3, 3):
    raise ImproperlyConfigured("mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)

註釋掉 就OK了。

注意4: 若是想打印orm轉換過程當中的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',
        },
    }
}

添加表記錄

urls.py

from django.contrib import admin
from django.urls import path

from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path(r'index/',views.index)
]

app01/models.py

from django.db import models

# Create your models here.

class Book(models.Model):  # 類名能夠隨便起,但必定得繼承 models.Model
    id = models.AutoField(primary_key=True)  # AutoField表示自增字段; primary_key=True 表示是主鍵
    title = models.CharField(max_length=32)
    # state = models.BooleanField()
    pub_date = models.DateField()
    price = models.DecimalField(max_digits=8,decimal_places=2)
    publish = models.CharField(max_length=32)

 

app01/views.py

from django.shortcuts import render,HttpResponse

# Create your views here.

# 先把模型導入進來
from app01.models import Book

def index(request):
    # 添加表記錄

    # 方式一:實例化Book對象
    book_obj = Book(id=1,title="python全棧開發",pub_date="2018-6-7",price=100,publish="IT出版社")   # pub_date是一個日期類型,必定得按照"年-月-日"的格式
    book_obj.save()  # save()以後記錄纔會生成 # 表裏面的一條記錄就是類的一個對象

    # 方式二:用 objects去調用create; create方法有返回值,返回值就是生成的記錄對象
    book_obj2 = Book.objects.create(title="linux運維",pub_date="2015-6-7",price=100,publish="IT出版社")  # id是自增的,因此無需再寫
    # 這種方式不須要 save();.objects.create(kwargs) 直接就在數據庫中生成了一條記錄(對象),並把這個對象返回給 book_obj2(咱們也就能夠打印book_obj2中的屬性)
    print(book_obj2.pub_date)


    return HttpResponse("ok")

 

單表查詢:

models.py

from django.db import models

# Create your models here.

class Book(models.Model):  # 類名能夠隨便起,但必定得繼承 models.Model
    id = models.AutoField(primary_key=True)  # AutoField表示自增字段; primary_key=True 表示是主鍵
    title = models.CharField(max_length=32)
    # state = models.BooleanField()
    pub_date = models.DateField()
    price = models.DecimalField(max_digits=8,decimal_places=2)
    publish = models.CharField(max_length=32)

    def __str__(self):  # 只是控制了對象的打印形式
        return self.title

views.py

from django.shortcuts import render,HttpResponse

# Create your views here.

# 先把模型導入進來
from app01.models import Book

def index(request):

    # #######################查詢表結構API#######################
    # 注意:要知道每一個方法的返回值是什麼、以及每一個方法是誰來調用的

    # 1. all() :查詢全部結果;返回值是一個QuerySet數據類型(Django自定義的數據類型),調用者是 objects
    all_books = Book.objects.all()
    print(all_books)
    # Book類沒有 __str()__方法時的打印結果:
    # <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]>
    # Book有 __str()__ 方法時的打印結果:
    # <QuerySet [<Book: python全棧開發>, <Book: linux運維>]>
    # QuerySet數據類型:至關於 [obj1,obj2,...],可用列表的方式去處理它

    for obj in all_books:  # 支持遍歷
        print(obj.title,obj.pub_date)

    print(all_books[1].publish)  # 支持索引

    # 2. first(),last()方法;返回值是一個model(模型)對象,調用者是 QuerySet對象
    book1 = Book.objects.all().first()  # 至關於 Book.objects.all()[0]
    book2 = Book.objects.all().last()

    print(book1,book2)

    # 3. filter()方法:返回值:QuerySet對象,調用者:管理器(objects)
    books = Book.objects.filter(title="python全棧開發",price=100)  # filter()的做用至關於sql語句的where;# 返回值:[obj1,obj2,....];多個過濾條件用逗號分隔
    print(books)
    # filter()方法也能夠調用 first(),last()方法
    print(books.first())

    # 4. get()方法:有且只有一個查詢結果時纔有意義;若是有多個查詢結果或者沒有查詢結果,報錯;因此,返回值:model對象
    book_get = Book.objects.get(title="python全棧開發")
    print(book_get.price)

    # 5. exclude():排除條件的過濾,對應filter();返回QuerySet
    ret = Book.objects.exclude(title="python全棧開發")
    print(ret)

    # 6. order_by():按照某種條件排序(默認是按照id);返回值:QuerySet,調用者:QuerySet
    book_order_asc = Book.objects.all().order_by("id")
    print(book_order_asc)
    book_order_desc = Book.objects.all().order_by("-id")  # 按照降序排列
    print(book_order_desc)
    book_price_desc = Book.objects.all().order_by("-price")  # 按照價格降序排列
    print(book_price_desc)
    # Book.objects.all().order_by("-price","id") # 先按照價格降序排列,再按照id升序
    # 要熟悉orm的鏈式操做

    # 7. reverse() :對查詢結果反向排序

    # 8. count():計數;返回值:int,調用者:QuerySet
    Book.objects.all().count()  # 計數裏面有多少個元素

    # 9. exists():若是QuerySet包含數據,就返回True,不然返回False
    ret_exists = Book.objects.all().exists()  # 判斷 Book.objects.all() 裏面是否有數據

    # 10. values(*field):field表明字段;values()具備遍歷做用,返回一個QuerySet --- 一個特殊的QuerySet,運行後獲得的並非一系列model的實例化對象,而是一個可迭代的字典序列;返回值:QuerySet(列表裏面放字典),調用者:QuerySet
    # values()方法很重要
    ret_values = Book.objects.all().values("price","title")
    print(ret_values)
    # <QuerySet [{'price': Decimal('100.00'), 'title': 'python全棧開發'}, {'price': Decimal('100.00'), 'title': 'linux運維'}]>
    print(ret_values[0].get("price"))
    # 100.00

    # 11. values_list(*field):它與values()很是類似,它返回的QuerySet裏面是一個元組序列,values返回的是一個字典序列
    ret_values_list = Book.objects.all().values_list("price", "title")
    print(ret_values_list)
    # <QuerySet [(Decimal('100.00'), 'python全棧開發'), (Decimal('100.00'), 'linux運維')]>

    # 12. distinct():從返回結果中剔除重複紀錄(一般配合values,values_list一塊兒使用)
    ret_distinct = Book.objects.all().values("price").distinct()
    print(ret_distinct)
    # <QuerySet [{'price': Decimal('100.00')}]>
    # 注: Book.objects.all().distinct() 這種寫法沒有任何意義

    # #######################查詢表結構之模糊查詢(都是雙下劃線)#######################
    # 1. __gt :大於;__lt:小於;返回值:QuerySet
    price__gt = Book.objects.filter(price__gt=50,price__lt=200)
    print("__gt",price__gt)

    # 2. __startswith:以什麼開頭;返回值:QuerySet
    obj_start = Book.objects.filter(title__startswith="py")
    print(obj_start)

    # 3. __contains:包含什麼;返回值:QuerySet
    # 4. __icontains:包含某些元素(不區分大小寫)
    obj_contains = Book.objects.filter(title__contains="x")
    print(obj_contains)

    # 5. __in = [] :是列表中的一個;返回值:QuerySet
    obj_in = Book.objects.filter(price__in=[100,150,200])
    print(obj_in)

    # 6. __year : 某一年的(只有date類型有);返回值:QuerySet
    obj_year = Book.objects.filter(pub_date__year=2018)
    print(obj_year)

    # 7. __range = [] : 在某個區間(包含兩端)
    obj_range = Book.objects.filter(price__range=[50,100])
    print("range",obj_range)

    return HttpResponse("ok")

補充:例如上面的4.get() 方法,若是值不存在,能夠捕獲到這個異常

from django.core.exceptions import ObjectDoesNotExist  # ObjectDoesNotExist 值不存在的異常類型

 

單表之刪除和編輯

views.py

from django.shortcuts import render,HttpResponse

# Create your views here.

# 先把模型導入進來
from app01.models import Book

def index(request):
    # #######################刪除、修改表記錄#######################
    # delete() : 刪除;調用者:QuerySet對象 或者 model對象;返回值是刪除元素的一些信息
    # Book.objects.filter(pub_date__year=2018).delete()  # 須要都把記錄查詢出來才能刪除;調用者:QuerySet對象
    # Book.objects.filter(pub_date__year=2015).first().delete()  # 調用者:model對象

    # update():編輯記錄; 調用者:QuerySet;返回值:更新的條數
    Book.objects.filter(title__contains="linux").update(title="linux運營維護")


    return HttpResponse("ok")

 

圖書管理系統

settings.py

"""
Django settings for bookms project.

Generated by 'django-admin startproject' using Django 2.0.1.

For more information on this file, see
https://docs.djangoproject.com/en/2.0/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.0/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'm6=&s25aszxks#m(5f57mdpi)hc%v7#&e0$kmak48@80xr7t0h'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    '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',
]

ROOT_URLCONF = 'bookms.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'bookms.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.0/ref/settings/#databases

# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }
DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.mysql',
        'NAME':'bookms', # 要鏈接的數據庫,鏈接前須要先建立好
        'USER':'root',  # 鏈接數據庫的用戶名
        'PASSWORD':'tj037778',  # 鏈接數據庫的密碼
        'HOST':'127.0.0.1',  # 鏈接主機
        'PORT':3306  # 端口
    }
}

# Password validation
# https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/

STATIC_URL = '/static/'  # 若存放靜態文件的static目錄在app目錄下,則該句生效,無需定義下面的
# STATICFILES_DIRS = [
#     os.path.join(BASE_DIR,"static"),
# ]    # 若存放靜態文件的static目錄在project目錄下,則用該定義


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

 

urls.py

"""bookms URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path,re_path

from app01 import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path(r"addbook/",views.addbook),
    path(r"books/",views.books),

    # (\d+)用於匹配獲取表記錄的主鍵(書的id)
    re_path(r"books/(\d+)/delete",views.bookdel),
    re_path(r"books/(\d+)/edit",views.bookedit)
]

 

views.py

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

# 把模型表引入
from app01.models import Book

def addbook(request):
    # 因爲templates/addbook.html 中 form標籤的 action沒寫,因此仍是提交到了當前頁面index.html
    if request.method == "POST":
        title = request.POST.get("title")
        price = request.POST.get("price")
        date = request.POST.get("date")
        press = request.POST.get("press")

        # 添加記錄
        book_obj = Book.objects.create(title=title,price=price,pub_date=date,publish=press)

        return redirect("/books/")

    return render(request,"addbook.html")

def books(request):
    books_list = Book.objects.all()

    return render(request,"books.html",locals())

def bookdel(request,pk):
    # 把對應ID的書刪除
    Book.objects.filter(id=pk).delete()

    # redirect()的做用就是讓瀏覽器往重定向的路徑再發一次請求
    return redirect("/books/")

def bookedit(request,id):
    # 編輯對應ID的書

    # 先獲取對應書對象
    book_obj = Book.objects.filter(id=id).first()

    # 因爲編輯後的內容仍是提交到當前頁面,因此在這個函數裏面要判斷請求是否就POST
    if request.method == "POST":
        # 獲取編輯後的內容
        title = request.POST.get("title")
        price = request.POST.get("price")
        date = request.POST.get("date")
        press = request.POST.get("press")

        # 把編輯後的內容更新到表中
        Book.objects.filter(id=id).update(title=title,price=price,pub_date=date,publish=press)
        # 更新完後重定向到 books.html 頁面
        return redirect("/books/")

    return render(request,"editbook.html",{"book_obj":book_obj})

 

models.py

from django.db import models

# Create your models here.

class Book(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    pub_date = models.DateField()
    price = models.DecimalField(max_digits=8, decimal_places=2)
    publish = models.CharField(max_length=32)

 

books.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>addbook</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">

    <style>
        .container{
            margin-top: 70px;
        }
        .btn{
            margin-bottom: 10px;
        }
    </style>

</head>
<body>
<h3>查看書籍</h3>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <a href="/addbook/" class="btn btn-primary">添加書籍</a>
            {# .table-striped 類能夠給 <tbody> 以內的每一行增長斑馬條紋樣式;.table-bordered 類爲表格和其中的每一個單元格增長邊框。#}
            <table class="table table-striped table-bordered">
                <thead>
                    <tr>
                        <th>書籍名稱</th>
                        <th>價格</th>
                        <th>出版日期</th>
                        <th>出版社</th>
                        <th>編輯</th>
                        <th>刪除</th>
                    </tr>
                </thead>
                <tbody>
                    {# 遍歷 books_list是的每個對象(表記錄),把每條表記錄添加到 table的一行中 #}
                    {% for book in books_list %}
                        <tr>
                            <td>{{ book.title }}</td>
                            <td>{{ book.price }}</td>
                            {# 利用date過濾器格式化時間樣式 #}
                            <td>{{ book.pub_date|date:"Y-m-d" }}</td>
                            <td>{{ book.publish }}</td>
                            {# 動態的爲每一個a標籤添加索引 #}
                            <td><a href="/books/{{ book.pk }}/edit" class="btn btn-info">編輯</a></td>
                            {# 把主鍵id添加到a標籤的路徑中;.pk表示model對象的主鍵 #}
                            <td><a href="/books/{{ book.pk }}/delete" class="btn btn-danger">刪除</a></td>
                        </tr>

                    {% endfor %}

                </tbody>
            </table>
        </div>
    </div>
</div>

</body>
</html>

 

addbook.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>addbook</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">

    <style>
        .container{
            margin-top: 70px;
        }
        .btn{
            margin-top: 10px;
        }
    </style>

</head>
<body>
<h3>添加書籍</h3>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <form action="" method="post">
                {% csrf_token %}
                <div>
                    <label for="">書籍名稱</label>
                    {# form-controlform-control控件,能夠爲input元素添加CSS定製樣式#}
                    <input type="text" class="form-control" name="title">
                </div>
                <div>
                    <label for="">價格</label>
                    <input type="text" class="form-control" name="price">
                </div>
                <div>
                    <label for="">出版日期</label>
                    {# date類型:可以下拉選擇日期 #}
                    <input type="date" class="form-control" name="date">
                </div>
                <div>
                    <label for="">出版社</label>
                    <input type="text" class="form-control" name="press">
                </div>
                {# btn btn-success:綠色按鈕;pull-right:右移 #}
                <input type="submit" class="btn btn-success pull-right">
            </form>
        </div>
    </div>
</div>

</body>
</html>

 

editbook.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>addbook</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">

    <style>
        .container{
            margin-top: 70px;
        }
        .btn{
            margin-top: 10px;
        }
    </style>

</head>
<body>
<h3>編輯書籍</h3>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            {# form標籤的action沒寫,因此默認仍是會提交到當前頁面 #}
            <form action="" method="post">
                {% csrf_token %}
                <div>
                    <label for="">書籍名稱</label>
                    {# 編輯時書名這一欄的內容是該對象原先的title;其它欄同理 #}
                    <input type="text" class="form-control" name="title" value="{{ book_obj.title }}">
                </div>
                <div>
                    <label for="">價格</label>
                    <input type="text" class="form-control" name="price" value="{{ book_obj.price }}">
                </div>
                <div>
                    <label for="">出版日期</label>
                    {# 此處的日期也須要用date過濾器格式化,要否則顯示不出來 #}
                    <input type="date" class="form-control" name="date" value="{{ book_obj.pub_date|date:'Y-m-d' }}">
                </div>
                <div>
                    <label for="">出版社</label>
                    <input type="text" class="form-control" name="press" value="{{ book_obj.publish }}">
                </div>
                {# btn btn-success:綠色按鈕;pull-right:右移 #}
                <input type="submit" class="btn btn-success pull-right">
            </form>
        </div>
    </div>
</div>

</body>
</html>
相關文章
相關標籤/搜索