Миграции Django и настраиваемые многократно используемые приложения
Я начал писать свое первое приложение многоразового использования около 3 недель назад, и у меня возникли проблемы с миграцией.
Я хочу, чтобы некоторые пункты моего приложения были настраиваемыми. Таким образом, у меня есть conf
субмодуль, который определяет пользовательские настройки и назначает разумные значения по умолчанию, которые подходят для большинства случаев.
Это приводит к тому, что некоторые поля моей модели выглядят так:
attachment = models.FilePathField(
path=conf.ATTACHMENTS_DIR, recursive=True)
template_file = models.FileField(
upload_to=conf.TEMPLATES_UPLOAD_DIR, blank=True)
prefix_subject = models.BooleanField(
default=True, verbose_name=_("prefix subject"),
help_text=_(
"Whether to prefix the subject with \"{}\" or not."
).format(conf.SUBJECT_PREFIX))
К сожалению, на проектах, использующих это приложение, это вызывает django-admin makemigrations
создавать миграции для него каждый раз, когда изменяется настройка. Или даже, когда они в первый раз устанавливают приложение для настроек, значение которых по умолчанию зависит от хост-системы.
Я более чем сомневаюсь в легитимности проекта, создающего собственные миграции внутри своей копии приложения. Но если я ошибаюсь, скажи мне.
За prefix_subject
В приведенном выше примере я решил проблему с этим решением. Учитывая, что потеря help_text
информация в миграциях была не очень эффективной.
Однако я не уверен, что это подходящее решение для всех / большинства случаев. Это?
Я думал о другом решении, которое, кажется, работает. Это решение состоит в том, чтобы вручную редактировать миграции и заменять оцененные параметры самой переменной.
Например, я бы заменил это:
migrations.CreateModel(
name='MailStaticAttachment',
fields=[
('id', ...),
('filename', ...)
('mime_type', ...)
('attachment', models.FilePathField(path='/home/antoine/Workspace/django-mailing/static/mailing/attachments', recursive=True, verbose_name='file')),
],
options={...}
),
С:
from ..conf import ATTACHMENTS_DIR
migrations.CreateModel(
name='MailStaticAttachment',
fields=[
('id', ...),
('filename', ...)
('mime_type', ...)
('attachment', models.FilePathField(path=ATTACHMENTS_DIR, recursive=True, verbose_name='file')),
],
options={...}
),
Это похоже на хорошее решение для вас?
Что вы советуете делать в таких случаях?
Я думаю, что оба Field.help_text
, FilePathField.path
а также FileField.upload_to
атрибуты не используются для создания операторов SQL. Так что в этом случае не должно быть особых проблем из-за "игнорирования их при миграции". Но что, если я, гипотетически, хочу настраиваемый Field.default
, Field.db_column
или же CharField.max_length
например? Вероятно, это очень плохая идея, которая не имеет практического интереса, но это единственная гипотетическая ситуация, которую я могу найти.:P I, думаю, в этом случае было бы лучше предоставить абстрактную базовую модель, предназначенную для расширения хост-проектом.
1 ответ
Во время проектирования django.db.migration
было решено, что все атрибуты поля должны отслеживаться, даже если они не влияют на представление схемы.
Для upload_to
В этом случае я предлагаю вам просто передать функцию, определенную на уровне модуля, как описано в документации.
import os
def upload_to(instance, filename):
return os.path.join([conf.TEMPLATES_UPLOAD_DIR, filename])
Для path
а также help_text
Я предлагаю вам использовать подход, аналогичный тому, что я сделал с django-sundial
обеспечить настраиваемые значения по умолчанию. Вам просто нужно убедиться, что вы передаете экземпляр класса с deconstruct()
метод, возвращающий соответствующие параметры.
from django.utils.six import python_2_unicode_compatible
@python_2_unicode_compatible
class StringConfReference(object):
def __init__(self, name):
self.name = name
def __str__(self):
return getattr(conf, self.name)
def deconstruct(self):
return "%s.%s" % (__name__, self.__class__.__name__), (self.name,), {}
attachment = models.FilePathField(
path=StringConfReference('ATTACHMENT_DIR'), recursive=True
)