【问题标题】:Django API architectureDjango API 架构
【发布时间】:2021-09-11 19:46:59
【问题描述】:

我有一个 API,我将 DRF 与基于类的视图一起使用。

我的 API 有这些模型:

""" 系统模型"""

import uuid

from django.db import models
from django.utils.translation import ugettext as _
from simple_history.models import HistoricalRecords

from common_config import custom_model_fields as version_model
from systems.models.manager.manager import SystemManager


class System(models.Model):
    """ Define fields for system model.
    machine(1-1): machine/models/machine.py
    owner(N-N): user/models/user.py
    support(N-N): user/models/user.py
    dealer(1-N): user/models/company.py
    console(1-1): console/models/console.py
    vision(1-N): vision/models/vision.py
    """

    class MarketChoice(models.TextChoices):
        """ Enum for market location """
        AUSTRALIA = 'Australia', _('Australia')
        EUROPE = 'Europe', _('Europe')

    class ProductChoice(models.TextChoices):
        """ Enum for Product """

        SPRAYER = 'Sprayer', _('Sprayer')
        OPTICAL_SORTER = 'Optical sorter', _('Optical sorter')

    uuid = models.UUIDField(
        default=uuid.uuid4,
        editable=False,
        unique=True)
    name = version_model.VersionCharField(
        verbose_name=_('Commercial name of the system'),
        max_length=30,
        default='1',
        null=False,
        blank=False,
        unique=True,
        version=1)
    code = models.CharField(verbose_name=_('code'), max_length=30, default='')
    description = models.TextField(verbose_name=_('Description'), blank=True)
    machine = models.OneToOneField('machine.Machine', on_delete=models.PROTECT)
    owner = models.ManyToManyField('users.User', related_name='own')
    support = models.ManyToManyField('users.User', related_name='support')
    dealer = models.ForeignKey('users.Company', on_delete=models.PROTECT)
    console = models.OneToOneField('console.Console', on_delete=models.PROTECT, related_name='console')
    market_location = models.CharField(max_length=25, choices=MarketChoice.choices, default=MarketChoice.EUROPE)
    is_telemetry_available = models.BooleanField(default=True,
                                                 verbose_name=_('Is the telemetry activated for this system ?'))
    product = models.CharField(verbose_name=_('Product type'), max_length=25, choices=ProductChoice.choices,
                               default=ProductChoice.SPRAYER)
    application = models.CharField(verbose_name=_('Application'), max_length=30, default='')
    history = HistoricalRecords()
    objects = SystemManager()

    class Meta:  # pylint: disable=too-few-public-methods
        """ Meta class for System """
        verbose_name = _('System')
        verbose_name_plural = _('Systems')

    def __str__(self):
        return f'System {self.name}'


""" Model for Calculation module """
import uuid

from django.db import models
from django.utils.translation import ugettext_lazy as _


class Vision(models.Model):
    """ Define fields for vision model.
    Represent a physical calculation module.
    device(1-1): device/models/device.py
    we_version(1-N): version/models/version.py
    setting(1-N): setting/models/setting.py
    camera(N-N): camera/models/camera.py
    """
    uuid = models.UUIDField(
        default=uuid.uuid4,
        editable=False,
        unique=True)
    device = models.OneToOneField(
        'device.Device',
        on_delete=models.PROTECT
    )
    we_version = models.ForeignKey('version.Version', on_delete=models.PROTECT, verbose_name=_('Weed Engine Version'))
    we_up_to_date = models.BooleanField(default=True, verbose_name=_('Is Weed Engine up to date'))
    we_last_update = models.DateTimeField(verbose_name=_('Weed Engine last update date'))
    setting = models.ForeignKey('setting.Setting', on_delete=models.PROTECT,
                                verbose_name=_('Settings associate to the vision module'), blank=True, null=True)
    system_id = models.PositiveSmallIntegerField(verbose_name=_('Id of the vision module on the system'))
    camera = models.ManyToManyField('camera.Camera', verbose_name=_('Cameras associated to vision module'))
    installation_date = models.DateTimeField(verbose_name=_('Vision installation date on the system'), null=True,
                                             blank=True)
    system_parent = models.ForeignKey('systems.System', on_delete=models.SET_NULL, null=True, related_name='vision')

    class Meta:  # pylint: disable=too-few-public-methods
        """ Meta class for Vision """
        verbose_name = _('Vision')
        verbose_name_plural = _("Visions")


""" Model for Camera """
import uuid
from django.db import models
from django.utils.translation import ugettext_lazy as _


class Camera(models.Model):
    """ Define fields for camera model.
    Represent a physical camera.
    1-1: device/models/device.py
    1-N: setting/models/setting.py
    """
    uuid = models.UUIDField(
        default=uuid.uuid4,
        editable=False,
        unique=True)
    system_id = models.PositiveSmallIntegerField(verbose_name=_('Id of the vision module on the system'))
    installation_date = models.DateTimeField(verbose_name=_('Camera installation date on the system'), null=True,
                                             blank=True)
    hardware = models.OneToOneField(
        'device.Hardware',
        on_delete=models.PROTECT
    )
    setting = models.ForeignKey('setting.Setting', on_delete=models.PROTECT,
                                verbose_name=_('Settings associate to the vision module'), null=True, blank=True)

    class Meta:  # pylint: disable=too-few-public-methods
        """ Meta class for Camera """
        verbose_name = _('Camera')
        verbose_name_plural = _("Cameras")

系统、视觉和相机是 3 个不同的应用程序。

我的 API 正在与 SPA 通信。

对于特定的已知系统,SPA 需要获取数据:

const cameras = [
    {name:"206", module:"206"},
    {name:"204", module:"204"},
    {name:"202", module:"202"},
    {name:"201", module:"201"},
    {name:"203", module:"203"},
    {name:"205", module:"203"},

];

该常量是出于某种测试原因创建的,“name”键对应于相机的名称,“module”对应于模块的名称。

我想知道我是否应该在系统、视觉或相机上创建我的视图?无论如何,我考虑过过滤系统名称/uuid。

另外,无论我将视图放在哪个应用程序中,我应该如何重新创建 SPA 需要的结构?我应该创建一个自定义序列化程序并使用它有一个特定的视图吗?我应该直接从我的数据库中返回正确的结构(我最喜欢的选项)吗?我应该在 '/visions-configuration' 这样的 url 上调用我的观点吗?它看起来不是很干净,我不确定它是否会遵守 REST 约定...

任何帮助都会很棒!

谢谢! :D

【问题讨论】:

    标签: django api rest django-rest-framework architecture


    【解决方案1】:

    我从未使用过 Django,但我不认为您正在寻找的答案太特定于 Django...

    我应该直接从我的数据库返回正确的结构

    没有。你熟悉层的架构概念吗?如果没有,请看一下。基本上,您的代码具有不同的职责——UI、“业务逻辑”和数据访问。混合它们通常是不好的,一方面它会使您的代码随着系统的增长、需求的变化等而变得非常困难或非常耗时。

    关于您的主要问题:据我了解,您有 3 种不同的数据模型要使用。我假设您有一个 UI(和其他系统组件)需要一致地处理这些问题。一个好的方法是提出您的系统(UI 等)处理的模型/数据结构(也称为“系统模型”)。我不确定“模型”是否在这里是正确的术语 - 我的意思是某种数据结构,它不特定于您系统外部的任何东西。

    这样,是的,您已经将三个输入模型修改为您的系统模型,但您只需执行一次,系统的其余部分仅取决于您控制的系统模型。这意味着您的其余开发更加可控和稳定。

    我应该创建一个自定义序列化程序并使用它有一个特定的视图

    听起来不错。要考虑的一件重要事情是,您的视图是否直接与序列化程序的输出一起使用,或者关闭了介于两者之间的某些东西。请注意,在这两种情况下,视图使用的数据结构与我在上面称为“系统模型”的一致。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多