根据 django 文档 处理模型中选择字段的最佳方法是这样做:
class Book(models.Model):
AVAILABLE = 'available'
BORROWED = 'borrowed'
ARCHIVED = 'archived'
STATUS = [
(AVAILABLE, 'Available to borrow'),
(BORROWED, 'Borrowed by someone'),
(ARCHIVED, 'Archived - not available anymore'),
]
# […]
status = models.CharField(
max_length=32,
choices=STATUS,
default=AVAILABLE,
)
但是,我的应用程序增长了很多,不同应用程序之间的模型互连也得到了扩展。在某些情况下,我需要导入模型类只是为了使用常量值
例如:
# some other file
from book.models import Book
def do_stuff_if_borrowed(book):
if (book.status == Book.BORROWED):
# do stuff
pass
我想尽可能避免在其他文件中导入模型,因为它会导致很多循环导入问题,总的来说我觉得这不是最干净的方法。我快速检查了一下,没有发现任何人提出如何外部化这些模型常量的解决方案,例如:
书/常量.py
AVAILABLE = 'available'
BORROWED = 'borrowed'
ARCHIVED = 'archived'
STATUS = [
(AVAILABLE, 'Available to borrow'),
(BORROWED, 'Borrowed by someone'),
(ARCHIVED, 'Archived - not available anymore'),
]
book/models.py
from .constants import STATUS, AVAILABLE
class Book(models.Model):
status = models.CharField(
max_length=32,
choices=STATUS,
default=AVAILABLE,
)
然后,如果我只需要常量,我不需要导入 Book 模型,而只需导入 Constants.py
有理由不这样做吗?
我正在做一个项目,我们正在考虑这样的事情。它连接到另一个服务 API,该 API 具有我们提取的指标和定义。因此,我们考虑过定期提取这些文件并将它们存储在类似metrics.json 文件的文件中,而不是在模型中使用它们。
这非常流畅且不错,但我认为您失去的是模型更改的可见性,这些更改导致需要创建、跟踪和运行迁移。
在你的例子中,常数似乎不会真正改变,目的只是保持干燥。似乎您可以创建该常量文件,然后添加一个方法来返回模型的前缀状态(如果您确实希望每个模型的状态更加清晰)。
在这种情况下,您牺牲的是轻松地直接从模型引用这些值。在文档的示例中,您可以使用
Book.STATUS_BORROWED
引用状态。但在您的示例中,您实际上必须单独导入这些常量。
我认为最好的解决方案就是制作一个包含此内容的 mixin,并让所有需要这些状态的模型都从中继承。
class BorrowableBookMixin(models.Model):
STATUS_AVAILABLE = 'available'
STATUS_BORROWED = 'borrowed'
STATUS_ARCHIVED = 'archived'
STATUS_CHOICES = [
(STATUS_AVAILABLE, 'Available to borrow'),
(STATUS_BORROWED, 'Borrowed by someone'),
(STATUS_ARCHIVED, 'Archived - not available anymore'),
]
status = models.CharField(
max_length=32,
choices=STATUS_CHOICES,
default=STATUS_AVAILABLE,
)
class Meta:
abstract = True
实际上,将常量和模型分开是一个很好的做法。
我会将特定模型的常量包装在 Constant 类中,如下所示:
# constants.py
class BookStatusChoices(object):
AVAILABLE = 'available'
BORROWED = 'borrowed'
ARCHIVED = 'archived'
STATUS = [
(AVAILABLE, 'Available to borrow'),
(BORROWED, 'Borrowed by someone'),
(ARCHIVED, 'Archived - not available anymore'),
]
我可以在模型中使用这些常量,如下所示:
from .constants import BookStatusChoices
class Book(models.Model):
# […]
status = models.CharField(
max_length=32,
choices=BookStatusChoices.STATUS,
default=BookStatusChoices.AVAILABLE,
)