# 圖紙管理系統 ## 一、初步構建後端項目 ### 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',
]
效果如下:
想要中文註釋
效果如下: