Sensor Data Collector後端資料模型實作建議
by ChatGPT
---
Q:
我要規劃一個IoT感測器資料搜集平台,本系統的參與角色有以下:
1. 雲端系統:後端API使用Django搭配Rest-framework實作,包含資料輸入與匯出功能。前端使用Vue.js實作,包含管理介面、資料展示Dashboard、帳號權限設定等。資料庫使用PostgreSQL16.3,系統架構使用docker進行架設。每個平台使用者皆隸屬於某客戶公司,使用者可加入不同角色(Groups)。
2. Device:地端蒐集器,負責集中處理所有地端Sensor Data,並上傳給雲端系統。每個設備皆會隸屬於某間公司,一個設備可以連接管理多個感測器。
3. Sensor:感測器,有多種感測器包含但不限於溫度、濕度、PM2.5、PM10、照度等。Sensor種類可以直接在後台進行管理,包含該Sensor回傳的資料型態、最大最小值等。
請先幫我撰寫適合後端用的models。
帳號權限我想用Django原生的User(使用onetoone擴充)與Group實作。
程式架構請用以下應用分類:
accounts
devices
sensors
---
A:
根據您的需求,我將根據 Django 的最佳實踐,將模型分別放在 `accounts`、`devices` 和 `sensors` 三個應用中。以下是每個應用的 `models.py` 文件內容,包括相關的模型定義和關聯設定。
### 1. `accounts` 應用
此應用主要負責用戶帳號管理,包括公司資訊和用戶擴充資料。
```python
# accounts/models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class Company(models.Model):
"""
公司模型,每個用戶隸屬於某個公司。
"""
name = models.CharField(max_length=255, unique=True)
address = models.TextField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Profile(models.Model):
"""
用戶擴充模型,透過 OneToOneField 擴充 Django 原生 User 模型。
"""
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='users')
# 其他擴充欄位可以在此添加,例如電話、地址等
phone = models.CharField(max_length=20, blank=True, null=True)
def __str__(self):
return f"{self.user.username} Profile"
# Signal 來自動建立或更新 Profile
@receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
```
**說明:**
- **Company 模型**:儲存公司相關資訊,每個用戶和設備都會關聯到一個公司。
- **Profile 模型**:擴充 Django 的 `User` 模型,透過 `OneToOneField` 與 `User` 相關聯,並新增 `company` 欄位來表示用戶所屬的公司。您可以根據需要在此模型中添加更多擴充欄位。
- **Signal**:當 `User` 創建或更新時,自動創建或更新對應的 `Profile`。
### 2. `devices` 應用
此應用負責管理設備(Device),每個設備隸屬於一個公司,並可管理多個感測器。
```python
# devices/models.py
from django.db import models
from accounts.models import Company
from django.contrib.auth.models import User
class Device(models.Model):
"""
設備模型,每個設備隸屬於某個公司,並可以管理多個感測器。
"""
name = models.CharField(max_length=255)
device_id = models.CharField(max_length=100, unique=True)
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='devices')
description = models.TextField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.name} ({self.device_id})"
```
**說明:**
- **Device 模型**:包含設備名稱、唯一的 `device_id`、所屬公司以及其他描述性欄位。
- **關聯**:每個設備透過 `ForeignKey` 關聯到 `Company`,確保設備屬於特定公司。
### 3. `sensors` 應用
此應用負責管理感測器類型和具體的感測器實例。
```python
# sensors/models.py
from django.db import models
from devices.models import Device
class SensorType(models.Model):
"""
感測器類型模型,用於管理不同種類的感測器。
"""
DATA_TYPE_CHOICES = [
('float', 'Float'),
('integer', 'Integer'),
('string', 'String'),
('boolean', 'Boolean'),
# 根據需要添加更多資料型態
]
name = models.CharField(max_length=100, unique=True)
data_type = models.CharField(max_length=50, choices=DATA_TYPE_CHOICES)
min_value = models.FloatField(blank=True, null=True)
max_value = models.FloatField(blank=True, null=True)
description = models.TextField(blank=True, null=True)
def __str__(self):
return self.name
class Sensor(models.Model):
"""
感測器模型,每個感測器隸屬於某個設備,並有特定的感測器類型。
"""
name = models.CharField(max_length=255)
sensor_id = models.CharField(max_length=100, unique=True)
device = models.ForeignKey(Device, on_delete=models.CASCADE, related_name='sensors')
sensor_type = models.ForeignKey(SensorType, on_delete=models.PROTECT, related_name='sensors')
description = models.TextField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f"{self.name} ({self.sensor_id})"
class Meta:
unique_together = ('device', 'sensor_id')
```
**說明:**
- **SensorType 模型**:管理不同類型的感測器,包括名稱、資料型態、最小值和最大值等。`DATA_TYPE_CHOICES` 定義了感測器資料的可能型態。
- **Sensor 模型**:代表具體的感測器實例,包含感測器名稱、唯一的 `sensor_id`、所屬設備以及感測器類型。`unique_together` 確保同一設備下的 `sensor_id` 唯一。
- **關聯**:
- 每個感測器透過 `ForeignKey` 關聯到 `Device`,確保感測器屬於特定設備。
- 每個感測器透過 `ForeignKey` 關聯到 `SensorType`,確保感測器具有特定的類型定義。
### 4. 其他建議
**使用 Docker 部署:**
確保在 `Dockerfile` 和 `docker-compose.yml` 中正確配置這些應用的相依性和服務。例如,確保 PostgreSQL 服務正確設定,並且每個應用的資料庫遷移能夠順利進行。
**權限管理:**
利用 Django 的 `Group` 模型來管理不同角色的權限。在 `accounts` 應用中,您可以根據需求創建不同的群組(例如:管理員、一般使用者等),並分配適當的權限。
**資料驗證與約束:**
根據需求,您可以在模型中添加更多的驗證邏輯,例如在 `Sensor` 模型中確保 `sensor_id` 的格式,或在 `SensorType` 模型中根據 `data_type` 限制 `min_value` 和 `max_value` 的適用性。
**範例管理命令:**
在每個應用中創建相應的 `admin.py` 文件,讓您能夠透過 Django 管理介面管理這些模型。
```python
# accounts/admin.py
from django.contrib import admin
from .models import Company, Profile
admin.site.register(Company)
admin.site.register(Profile)
```
```python
# devices/admin.py
from django.contrib import admin
from .models import Device
admin.site.register(Device)
```
```python
# sensors/admin.py
from django.contrib import admin
from .models import SensorType, Sensor
admin.site.register(SensorType)
admin.site.register(Sensor)
```