Выбор модели Django в отдельном файле константы

#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