#django #django-models #python-import
#django #django-модели #python-импорт
Вопрос:
Согласно документам 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
Я бы хотел максимально избегать импорта моделей в другой файл, потому что это вызывает множество проблем с циклическим импортом, и в целом я чувствую, что это не самый чистый способ. Я быстро проверил и не нашел никого, кто представлял бы решение о том, как экстернализировать эти константы модели, такие как:
book/constants.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,
)
и тогда, если мне нужны только константы, мне не нужно импортировать модель книги, а только constants.py
Есть ли причина не делать так?
Комментарии:
1.я думаю, что единственная причина в том, что вы можете использовать общие слова,
AVAILABLE
ARCHIVED
которые уже используются в ваших других моделях, я думаю, вам следует подумать о том, чтобы сделать имена более уникальными, напримерBOOK_STATUS_AVAILABLE
BOOK_STATUS_ARCHIVED
, чтобы вас не путали с повторяющимися именами2. Да, это сделало бы константы уникальными
Ответ №1:
Я работаю над проектом, где мы рассматриваем что-то вроде этого. Он подключен к другому API-сервису, у которого есть метрики и определения, которые мы извлекаем. Итак, мы рассматривали возможность обычного извлечения этих файлов и сохранения их во что-то вроде файла metrics.json, а не использования их в моделях.
Это довольно плавно и приятно, но я думаю, что вы теряете видимость изменений в моделях, которые приводят к необходимости создания, отслеживания и запуска миграций.
В вашем случае кажется, что константы на самом деле не будут меняться, и намерение состоит в том, чтобы просто быть СУХИМ. Похоже, вы могли бы создать этот файл констант, а затем добавить метод, который возвращает статусы с префиксом для вашей модели, если вы хотите, чтобы они были более четкими для каждой модели.
Чем вы жертвуете в этом случае, так это простой ссылкой на эти значения непосредственно из модели. В примере из документов вы могли бы ссылаться на статус с помощью Book.STATUS_BORROWED
. Но в вашем примере вам пришлось бы фактически импортировать эти константы отдельно.
Я думаю, что лучшее решение — просто создать микс, который охватывает это, и чтобы все ваши модели, которым нужны эти статусы, наследовали от этого.
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