一步步完整搭建一個圖紙管理系統(Django+Vue3)

来源:https://www.cnblogs.com/lightwower/archive/2023/05/24/17428880.html
-Advertisement-
Play Games

# 圖紙管理系統 ## 一、初步構建後端項目 ### 1、打開已經創建好的虛擬環境:激活activate(推薦使用虛擬環境)並創建項目 ![](https://img2023.cnblogs.com/blog/2240937/202305/2240937-20230524164953360-1300 ...


圖紙管理系統

一、初步構建後端項目

1、打開已經創建好的虛擬環境:激活activate(推薦使用虛擬環境)並創建項目

2、導入vs code中,項目環境大致如下:

需要將終端改成虛擬環境的解釋器後,簡單試運行:

3、創建子app(圖紙管理系統模塊)

由於我們把子項目都放在apps裡面了(方便統一管理)所以註冊要加入一段配置

4、創建資料庫

一定要註意格式

5、設置Django連接資料庫

(1)安裝pymysql

pip install pymysql

(2)gveInformationSystem/settings中進行相關配置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'StudentDB',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}

(3)需要在init.py導入pymysql

6、創建資料庫表內容

(在:apps/DrawingManagementSystem/models.py)

from django.db import models


# Create your models here.
# === 圖紙管理系統 models
# 感測器分類--sensor, 項目--project, 資料-data, 圖紙信息-drawing

# 公有創建時間和修改時間
class TimestampMode(models.Model):
    """
    An abstract base class model that provides selfupdating ``created`` and ``modified`` fields.
    """
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True  # it's very important to add this line


# === 感測器類 --- Sensor:Id,name,created,modified
class Sensor(TimestampMode):
    sensor_name = models.CharField(verbose_name="感測器名稱", max_length=50, unique=True, null=False, blank=False)

    # create_time = models.DateTimeField(default=timezone.now().replace(microsecond=0))

    class Meta:
        db_table = "Draw_Sensor"
        managed = True
        app_label = "DrawingManagementSystem"

    def __str__(self):
        return "%s" % (self.sensor_name)


# === 項目類 --- project:Id,name,created,modified
class Project(TimestampMode):
    project_name = models.CharField(verbose_name="項目名稱", max_length=50, unique=True, null=False, blank=False)
    sensor = models.ForeignKey(verbose_name="所屬感測器", to=Sensor, on_delete=models.PROTECT)

    class Meta:
        db_table = "Draw_Project"
        managed = True
        app_label = "DrawingManagementSystem"

    def __str__(self):
        return "%s" % (self.project_name)


# === 資料類 --- data:ID,name,created,modified
class Data(TimestampMode):
    data_name = models.CharField(verbose_name="資料名稱", max_length=50, unique=True, null=False, blank=False)
    sensor = models.ForeignKey(verbose_name="所屬感測器", to=Sensor, on_delete=models.PROTECT)
    project = models.ForeignKey(verbose_name="所屬項目", to=Project, on_delete=models.PROTECT)

    class Meta:
        db_table = "Draw_Data"
        managed = True
        app_label = "DrawingManagementSystem"

    def __str__(self):
        return "%s" % (self.data_name)


# === 圖紙信息 --- drawing:ID(Material_code),drawing_name,created,modified,drawing_spec,drawing_page,drawing_client_id,drawing_remark,drawing_version
class Drawing(TimestampMode):
    material_code = models.CharField(verbose_name="物料編號", max_length=50, blank=False)
    sensor = models.ForeignKey(verbose_name="所屬感測器", to=Sensor, on_delete=models.PROTECT)
    project = models.ForeignKey(verbose_name="所屬項目", to=Project, on_delete=models.PROTECT)
    data = models.ForeignKey(verbose_name="所屬資料", to=Data, on_delete=models.PROTECT)
    drawing_name = models.CharField(verbose_name="材料名稱", max_length=50, blank=False)
    drawing_spec = models.CharField(verbose_name="規格/圖紙號", max_length=50, blank=False)
    drawing_page = models.CharField(verbose_name="圖紙頁數", max_length=50, blank=False)
    drawing_client_id = models.CharField(verbose_name="客戶編號", max_length=50)
    drawing_version = models.CharField(verbose_name="版本號", max_length=50, blank=False)
    drawing_remark = models.CharField(verbose_name="備註", max_length=100)
    drawing_url = models.CharField(verbose_name="地址", max_length=100)
    is_deleted = models.IntegerField(verbose_name="邏輯刪除0否1是", max_length=10, blank=False, default=0)

    class Meta:
        db_table = "Draw_Drawing"
        managed = True
        app_label = "DrawingManagementSystem"

    def __str__(self):
        return "%s" % (self.drawing_name)


(1)用指令生成資料庫

python manage.py makemigrations
python manage.py migrate

完成後代碼如下:

7、DRF介面(初步)

(1)DRF的安裝和快速實現

安裝DjangoRestFramework包

pip install djangorestframework==3.13.0

在settings中導入

序列化:負責對象和json格式的相互轉換

​ a獲取數據:對象-->Json返回給前端

​ b添加、修改:json-->對象 存儲在資料庫中

視圖:實現後臺功能的核心

​ 早期:視圖是基於函數--FBV

​ DRF:視圖基於類--CBV

路由:路由的匹配

(2)序列化

創建DrawingManagementSystem\serializer.py文件

from rest_framework import serializers
from DrawingManagementSystem.models import Sensor, Project, Data, Drawing


# ----Sensor序列化類----
class SensorSerialzer(serializers.ModelSerializer):
    class Meta:
        model = Sensor
        fields = "__all__"

# ____Project序列化類____
class ProjectSerialzer(serializers.ModelSerializer):
    class Meta:
        model = Project
        fields = "__all__"

# ____Data序列化類____
class DataSerialzer(serializers.ModelSerializer):
    class Meta:
        model = Data
        fields = "__all__"

# ____Drawing序列化類____
class DrawingSerialzer(serializers.ModelSerializer):
    class Meta:
        model = Drawing
        fields = "__all__"

(3)編寫view.py代碼(apps\DrawingManagementSystem\views.py)

# ====== 導入模塊 ======
from rest_framework.viewsets import ModelViewSet  # 封裝完成的ModelViewset視圖集
from DrawingManagementSystem.models import Sensor, Project, Data, Drawing  # 具體的類
from DrawingManagementSystem.serializer import SensorSerialzer, ProjectSerialzer, DataSerialzer, DrawingSerialzer # 序列化類

# ---Sensor視圖---
class SensorViewSet(ModelViewSet):
    queryset = Sensor.objects.all()
    serializer_class = SensorSerialzer

# ---Project---
class ProjectViewSet(ModelViewSet):
    queryset = Project.objects.all()
    serializer_class = ProjectSerialzer

# ---Data視圖---
class DataViewSet(ModelViewSet):
    queryset = Data.objects.all()
    serializer_class = DataSerialzer

# ---Sensor視圖---
class DrawingViewSet(ModelViewSet):
    queryset = Drawing.objects.all()
    serializer_class = DrawingSerialzer

(4)編寫urls.py代碼(apps\DrawingManagementSystem\urls.py)

# ======導入模塊======
from django.urls import path
from rest_framework.routers import DefaultRouter
from DrawingManagementSystem.views import SensorViewSet, ProjectViewSet, DataViewSet, DrawingViewSet

# ====1.實例化一個 DefaultRouter====
router = DefaultRouter()

# ====2.註冊相應的url====
# 註冊Sensor對象
router.register('Sensors', SensorViewSet, basename='Sensors') # http://127.0.0.1:8080/DrawingApi/v1/Sensors/
# 註冊Sensor對象
router.register('Projects', ProjectViewSet, basename='Projects') # http://127.0.0.1:8080/DrawingApi/v1/Projects/
# 註冊Sensor對象
router.register('Datas', DataViewSet, basename='Datas') # http://127.0.0.1:8080/DrawingApi/v1/Datas/
# 註冊Sensor對象
router.register('Drawings', DrawingViewSet, basename='Drawings') # http://127.0.0.1:8080/DrawingApi/v1/Drawings/

urlpatterns = [

]

# ====3.附加到urlpatterns集合中====
urlpatterns += router.urls

編寫總urls.py代碼(gveInformationSystemBE\urls.py)

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('DrawingApi/v1/',include('DrawingManagementSystem.urls')),
]

編寫後運行django項目

python manage.py runserver

瀏覽器輸入:http://127.0.0.1:8000/DrawingApi/v1/

可以看到界面如下:

說明簡單後端介面已經完成,可以簡單測試下:

發現存入的時間是北美市區,將gveInformationSystemBE\settings.py中的USE_TZ = True改為:USE_TZ = False

發現存入的時間是帶毫秒:參考解決方法為

或者直接在資料庫軟體中

可以避免存入毫秒的問題

8、DRF進階(增刪改介面、篩選、搜索、分頁)

其實在網址後面加上id,就可以進行數據的刪除修改

(1)DRF的篩選

步驟為:

安裝:pip install django-filter

pip install django-filter==21.1

註冊到installed_apps中

完成filter的篩選類

在apps\DrawingManagementSystem新建filter.py

# =====導入模塊=====
from django_filters import FilterSet
from DrawingManagementSystem.models import Sensor, Project, Data, Drawing


# ---Sensor的Filter類---
class SensorFilter(FilterSet):
    class Meta:
        model = Sensor
        fields = ('sensor_name',) # 感測器名稱


# ---Project的Filter類---
class ProjectFilter(FilterSet):
    class Meta:
        model = Project
        fields = ('project_name', 'sensor') # 項目名稱 所屬感測器


# ---Data的Filter類---
class DataFilter(FilterSet):
    class Meta:
        model = Data
        fields = ('data_name', 'sensor', 'project') # 資料名稱 所屬感測器 所屬項目


# ---Drawing的Filter類---
class DrawingFilter(FilterSet):
    class Meta:
        model = Drawing
        fields = ('drawing_name', 'material_code', 'drawing_spec', 'drawing_client_id')  # 材料名稱、物料編號、規格/圖紙號、客戶編號

在viewset中添加篩選類

# ====== 導入模塊 ======
from rest_framework.viewsets import ModelViewSet  # 封裝完成的ModelViewset視圖集
from DrawingManagementSystem.models import Sensor, Project, Data, Drawing  # 具體的類
from DrawingManagementSystem.serializer import SensorSerialzer, ProjectSerialzer, DataSerialzer, \
    DrawingSerialzer  # 序列化類
from django_filters.rest_framework import DjangoFilterBackend  # 實現篩選的後臺模塊
from DrawingManagementSystem.filter import SensorFilter, ProjectFilter, DataFilter, DrawingFilter


# ---Sensor視圖---
class SensorViewSet(ModelViewSet):
    queryset = Sensor.objects.all()
    serializer_class = SensorSerialzer
    # 設定篩選的後臺
    filter_backends = (DjangoFilterBackend,)
    # 指定篩選的類
    filter_class = SensorFilter

# ---Project---
class ProjectViewSet(ModelViewSet):
    queryset = Project.objects.all()
    serializer_class = ProjectSerialzer
    # 設定篩選的後臺
    filter_backends = (DjangoFilterBackend,)
    # 指定篩選的類
    filter_class = ProjectFilter


# ---Data視圖---
class DataViewSet(ModelViewSet):
    queryset = Data.objects.all()
    serializer_class = DataSerialzer
    # 設定篩選的後臺
    filter_backends = (DjangoFilterBackend,)
    # 指定篩選的類
    filter_class = DataFilter


# ---Sensor視圖---
class DrawingViewSet(ModelViewSet):
    queryset = Drawing.objects.all()
    serializer_class = DrawingSerialzer
    # 設定篩選的後臺
    filter_backends = (DjangoFilterBackend,)
    # 指定篩選的類
    filter_class = DrawingFilter

效果如下:

(2)篩選優化——模糊匹配

# =====導入模塊=====
from django_filters import FilterSet,filters
from DrawingManagementSystem.models import Sensor, Project, Data, Drawing


# ---Sensor的Filter類---
class SensorFilter(FilterSet):
    # 重新需要支持模糊匹配的欄位
    sensor_name = filters.CharFilter(field_name='sensor_name',lookup_expr="icontains")
    class Meta:
        model = Sensor
        fields = ('sensor_name',) # 感測器名稱


# ---Project的Filter類---
class ProjectFilter(FilterSet):
    # 重新需要支持模糊匹配的欄位
    project_name = filters.CharFilter(field_name='project_name', lookup_expr="icontains")
    class Meta:
        model = Project
        fields = ('project_name', 'sensor') # 項目名稱 所屬感測器


# ---Data的Filter類---
class DataFilter(FilterSet):
    # 重新需要支持模糊匹配的欄位
    data_name = filters.CharFilter(field_name='data_name', lookup_expr="icontains")
    class Meta:
        model = Data
        fields = ('data_name', 'sensor', 'project') # 資料名稱 所屬感測器 所屬項目


# ---Drawing的Filter類---
class DrawingFilter(FilterSet):
    # 重新需要支持模糊匹配的欄位
    drawing_name = filters.CharFilter(field_name='drawing_name', lookup_expr="icontains")
    material_code = filters.CharFilter(field_name='material_code', lookup_expr="icontains")
    drawing_spec = filters.CharFilter(field_name='drawing_spec', lookup_expr="icontains")
    drawing_client_id = filters.CharFilter(field_name='drawing_client_id', lookup_expr="icontains")
    class Meta:
        model = Drawing
        fields = ('drawing_name', 'material_code', 'drawing_spec', 'drawing_client_id')  # 材料名稱、物料編號、規格/圖紙號、客戶編號

(3)全局加入篩選後臺

在gveInformationSystemBE\settings.py中加入

# ======= REST Framework全局設置 ===========
REST_FRAMEWORK = {

    # ==== 設置全局的Filter_Backends ====
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
    ],


}

這樣views.py中就不需要加入

# 設定篩選的後臺
    filter_backends = (DjangoFilterBackend,)

修改後代碼如下:

# ====== 導入模塊 ======
from rest_framework.viewsets import ModelViewSet  # 封裝完成的ModelViewset視圖集
from DrawingManagementSystem.models import Sensor, Project, Data, Drawing  # 具體的類
from DrawingManagementSystem.serializer import SensorSerialzer, ProjectSerialzer, DataSerialzer, \
    DrawingSerialzer  # 序列化類
from DrawingManagementSystem.filter import SensorFilter, ProjectFilter, DataFilter, DrawingFilter


# ---Sensor視圖---
class SensorViewSet(ModelViewSet):
    queryset = Sensor.objects.all()
    serializer_class = SensorSerialzer

    # 指定篩選的類
    filter_class = SensorFilter

# ---Project---
class ProjectViewSet(ModelViewSet):
    queryset = Project.objects.all()
    serializer_class = ProjectSerialzer

    # 指定篩選的類
    filter_class = ProjectFilter


# ---Data視圖---
class DataViewSet(ModelViewSet):
    queryset = Data.objects.all()
    serializer_class = DataSerialzer

    # 指定篩選的類
    filter_class = DataFilter


# ---Sensor視圖---
class DrawingViewSet(ModelViewSet):
    queryset = Drawing.objects.all()
    serializer_class = DrawingSerialzer

    # 指定篩選的類
    filter_class = DrawingFilter

(4)加入搜索

篩選【filter】:一個值只能對應一個欄位,需要django-filter

搜索【search】;一個值能對應多個欄位,DRF自帶

在gveInformationSystemBE\settings.py中加入'rest_framework.filters.SearchFilter',

# ======= REST Framework全局設置 ===========
REST_FRAMEWORK = {

    # ==== 設置全局的Filter_Backends ====
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.SearchFilter',

    ],


}

在apps\DrawingManagementSystem\views.py中加入需要搜索匹配的欄位

# ---Sensor視圖---
class DrawingViewSet(ModelViewSet):
    queryset = Drawing.objects.all()
    serializer_class = DrawingSerialzer

    # 指定篩選的類
    filter_class = DrawingFilter
    # 指定查找匹配的欄位
    search_fields = ('drawing_name', 'material_code', 'drawing_spec', 'drawing_client_id')

結果如下:

(5)加入分頁

有2種,一種為全局

即在在gveInformationSystemBE\settings.py中加入

# ======= REST Framework全局設置 ===========
REST_FRAMEWORK = {

    # ==== 設置全局的Filter_Backends ====
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.SearchFilter',

    ],
    # ===== 設置分頁 ===============
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10


}

還有一種為:按需分頁

apps\DrawingManagementSystem下新建paginations.py

代碼如下:

# ========== 導入 ===========
from rest_framework.pagination import PageNumberPagination


class MyPageNumberPagination(PageNumberPagination):
    page_size = 5
    page_query_param = "page"
    page_size_query_param = 'size'
    max_page_size = 50

在apps\DrawingManagementSystem\views.py中加入:

from DrawingManagementSystem.paginations import MyPageNumberPagination
###
###
###
# ---Sensor視圖---
class DrawingViewSet(ModelViewSet):
    queryset = Drawing.objects.all()
    serializer_class = DrawingSerialzer
    pagination_class = MyPageNumberPagination

    # 指定篩選的類
    filter_class = DrawingFilter
    # 指定查找匹配的欄位
    search_fields = ('drawing_name', 'material_code', 'drawing_spec', 'drawing_client_id')

效果如下:

9、添加Swagger文檔

記得在setting中註冊

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'DrawingManagementSystem',
    'rest_framework',
    'django_filters',
    'drf_yasg',
]

效果如下:

想要中文註釋

效果如下:


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在 HTML 中,屬性(Attribute)和屬性(Property)是用於描述 HTML 元素的相關特性的術語。 屬性(Attribute)是指在 HTML 標簽中聲明的附加信息。它們以鍵值對的形式出現,用於提供元素的初始狀態或配置選項。屬性的名稱是不區分大小寫的,並且值可以是字元串或布爾值。 例 ...
  • ### GC 優化 #### 1.防止大對象Buffer到記憶體中 **現象**:當大包請求時,YGC 耗時嚴重 **原因**:預設情況下 Zuul2 並不會緩存請求體(DirectByteBuffer),也就意味著它會先發送接收到的請求 Headers 到後端服務,之後接收到請求體再繼續發送到後端服 ...
  • 一、什麼是微服務 微服務是一種技術架構,通常我們可以把它理解為一組可以相互之間協同工作的應用程式或服務,這些應用程式或服務能夠被單獨部署到不同的伺服器中,並且能夠自主運行和維護。 微服務技術只是一個名稱而已,或許我們在日常工作中已經或多或少在使用其中的一種或幾種技術和架構,但我們並沒有將其稱之為微服 ...
  • 汽車之家電商系統誕生在2014年,成長於2016~2019年,並經歷多年雙11、818晚會的洪峰考驗,沉澱了穩定可靠、性能卓越的線上交易能力。隨著業務中台的建設浪潮興起,2019年進入中台化建設階段,輸出其在汽車電商領域五年沉澱的能力,助力汽車電商行業發展,加速企業數字化轉型! ...
  • ## 初步瞭解 ### 總體架構設計 Mybatis 整體框架如下: ![img](https://zhangjiahao-blog.oss-cn-beijing.aliyuncs.com/picgo/202305161021323.png) ##### 介面層 MyBatis 和資料庫的交互有兩種 ...
  • # Java語法基礎 ## 註釋 註釋是對代碼的解釋和說明文字,可以提高程式的可讀性,因此在程式中添加必要的註釋文字十分重要。Java中的註釋分為三種: 單行註釋。單行註釋的格式是使用//,從//開始至本行結尾的文字將作為註釋文字。 ~~~java // 這是單行註釋文字 ~~~ 多行註釋。多行註釋 ...
  • ## 教程簡介 Apache Kafka由Scala寫成。Kafka最初是由LinkedIn開發,並於2011年初開源。2012年10月從Apache Incubator畢業。該項目的目標是為處理實時數據提供一個統一、高通量、低等待的平臺。 Kafka是一個分散式的、分區的、多複本的日誌提交服務。它 ...
  • 最近在壓測一批介面,發現介面處理速度慢的有點超出預期,感覺很奇怪,後面定位發現是資料庫批量保存這塊很慢。 這個項目用的是 mybatis-plus,批量保存直接用的是 mybatis-plus 提供的 saveBatch。 我點進去看了下源碼,感覺有點不太對勁: 繼續追蹤了下,從這個代碼來看,確實是 ...
一周排行
    -Advertisement-
    Play Games
  • 在C#中使用SQL Server實現事務的ACID(原子性、一致性、隔離性、持久性)屬性和使用資料庫鎖(悲觀鎖和樂觀鎖)時,你可以通過ADO.NET的SqlConnection和SqlTransaction類來實現。下麵是一些示例和概念說明。 實現ACID事務 ACID屬性是事務處理的四個基本特征, ...
  • 我們在《SqlSugar開發框架》中,Winform界面開發部分往往也用到了自定義的用戶控制項,對應一些特殊的界面或者常用到的一些局部界面內容,我們可以使用自定義的用戶控制項來提高界面的統一性,同時也增強了使用的便利性。如我們Winform界面中用到的分頁控制項、附件顯示內容、以及一些公司、部門、菜單的下... ...
  • 在本篇教程中,我們學習瞭如何在 Taurus.MVC WebMVC 中進行數據綁定操作。我們還學習瞭如何使用 ${屬性名稱} CMS 語法來綁定頁面上的元素與 Model 中的屬性。通過這些步驟,我們成功實現了一個簡單的數據綁定示例。 ...
  • 是在MVVM中用來傳遞消息的一種方式。它是在MVVMLight框架中提供的一個實現了IMessenger介面的類,可以用來在ViewModel之間、ViewModel和View之間傳遞消息。 Send 接受一個泛型參數,表示要發送的消息內容。 Register 方法用於註冊某個對象接收消息。 pub ...
  • 概述:在WPF中,通過EventHandler可實現基礎和高級的UI更新方式。基礎用法涉及在類中定義事件,併在UI中訂閱以執行更新操作。高級用法藉助Dispatcher類,確保在非UI線程上執行操作後,通過UI線程更新界面。這兩種方法提供了靈活而可靠的UI更新機制。 在WPF(Windows Pre ...
  • 概述:本文介紹了在C#程式開發中如何利用自定義擴展方法測量代碼執行時間。通過使用簡單的Action委托,開發者可以輕鬆獲取代碼塊的執行時間,幫助優化性能、驗證演算法效率以及監控系統性能。這種通用方法提供了一種便捷而有效的方式,有助於提高開發效率和代碼質量。 在軟體開發中,瞭解代碼執行時間是優化程式性能 ...
  • 概述:Cron表達式是一種強大的定時任務調度工具,通過配置不同欄位實現靈活的時間規定。在.NET中,Quartz庫提供了簡便的方式配置Cron表達式,實現精準的定時任務調度。這種靈活性和可擴展性使得開發者能夠根據需求輕鬆地制定和管理定時任務,例如每天備份系統日誌或其他重要操作。 Cron表達式詳解 ...
  • 概述:.NET提供多種定時器,如System.Windows.Forms.Timer適用於UI,System.Web.UI.Timer用於Web,System.Diagnostics.Timer用於性能監控,System.Threading.Timer和System.Timers.Timer用於一般 ...
  • 問題背景 有同事聯繫我說,在生產環境上,訪問不了我負責的common服務,然後我去檢查common服務的health endpoint, 沒問題,然後我問了下異常,timeout導致的System.OperationCanceledException。那大概率是客戶端的問題,會不會是埠耗盡,用ne ...
  • 前言: 在本篇 Taurus.MVC WebMVC 入門開發教程的第四篇文章中, 我們將學習如何實現數據列表的綁定,通過使用 List<Model> 來展示多個數據項。 我們將繼續使用 Taurus.Mvc 命名空間,同時探討如何在視圖中綁定並顯示一個 Model 列表。 步驟1:創建 Model ...