在不更改原始Django App的情况下向Django FlatPages添加功能

时间:2009-06-20 11:54:00

标签: django django-models monkeypatching

我想在Django FlatPage数据库模型中添加一个字段,但我真的不知道如何在不编辑原始应用程序的情况下扩展它。

我想要做的是将以下字段添加到模型中:


from django.db import models
from django.contrib.flatpages.models import FlatPage as FlatPageOld

class FlatPage(FlatPageOld):
    order = models.PositiveIntegerField(unique=True)

如何将其添加到FlatPage模型中?

提前致谢

3 个答案:

答案 0 :(得分:21)

您的方法很好 - 您只是看不到结果,因为旧的平面模型已在管理员中注册而新的平面模型未注册。以下是您在新应用程序的admin.py中可能会执行的操作(使用的命名方式比上面提到的更少):

from django.contrib import admin
from django.contrib.flatpages.admin import FlatPageAdmin
from django.contrib.flatpages.forms import FlatpageForm
from django.contrib.flatpages.models import FlatPage

from models import ExtendedFlatPage

class ExtendedFlatPageForm(FlatpageForm):
    class Meta:
        model = ExtendedFlatPage

class ExtendedFlatPageAdmin(FlatPageAdmin):
    form = ExtendedFlatPageForm
    fieldsets = (
        (None, {'fields': ('url', 'title', 'content', 'sites', 'order')}),
    )     

admin.site.unregister(FlatPage)
admin.site.register(ExtendedFlatPage, ExtendedFlatPageAdmin)

显然这里有一些事情,但最重要的是FlatPage模型正在取消注册,而ExtendedFlatPage模型正在其位置注册。

答案 1 :(得分:7)

你帖子中的方法不起作用,因为......?

如果由于某种原因你真的需要摆弄内置的FlatPage类并动态编辑它,你可以挂钩到class_prepared信号:

http://docs.djangoproject.com/en/dev/ref/signals/#class-prepared

修改

以下是使用class_prepared执行此操作的方法:

from django.db.models.signals import class_prepared
from django.db import models

def alter_flatpages(sender, **kwargs):
    if sender.__module__ == 'django.contrib.flatpages.models' and sender.__name__ == 'FlatPage':
        order = models.IntegerField()
        order.contribute_to_class(sender, 'order')

class_prepared.connect(alter_flatpages)

将此信息放入与settings.py位于同一目录中的'signals.py'中,并将“信号”添加到顶部(这一点非常重要,以确保信号处理程序安装时间安装在INSTALLED_APPS列表中。

但是,仍然无法在Admin中显示该字段,因为FlatPages有一个自定义的ModelAdmin类,它明确地列出了字段。因此,在flatpages应用程序中注册后,您需要在某处取消注册(admin.site.unregister)并注册您自己的ModelAdmin。

答案 2 :(得分:0)

  1. settings.py应用程序的django.contrib.flatpages change the location of the migrations folder中将应用程序移到默认文件夹以外的其他文件夹。例如:

settings.py

MIGRATION_MODULES = {'flatpages': 'yourproject.flatpages.migrations'}

请记住,您必须在文件夹__init__.pyyourprojectflatpages中创建空的migrations文件,以使Python对待那些文件字典作为包。

  1. 执行makemigrations管理命令以将初始迁移填充到MIGRATION_MODULES文件夹中。它的外观应类似于default one

  2. 在您的一个应用程序(最好是使用平板功能的应用程序)的apps.py中,添加oggy的class_prepared解决方案:

apps.py

from django.apps import AppConfig
from django.db.models.signals import class_prepared
from django.db import models


def alter_flatpages(sender, **kwargs):
    if sender.__module__ == 'django.contrib.flatpages.models' and sender.__name__ == 'FlatPage':
        meta_description = models.CharField(max_length=255, blank=True, null=True)
        meta_description.contribute_to_class(sender, 'meta_description')


class TexteConfig(AppConfig):
    name = 'marlene.texte'

    def __init__(self, app_name, app_module):
        super().__init__(app_name, app_module)
        class_prepared.connect(alter_flatpages)
  1. 通过再次执行makemigrations添加另一个迁移。这次您已将CharField meta_description添加到模型中。 migrate将更改应用到数据库。

  2. 修改FlatPageAdmin

admin.py

from django.contrib.flatpages.admin import FlatPageAdmin
from django.contrib.flatpages.models import FlatPage

class MarleneFlatPageAdmin(FlatPageAdmin):
    fieldsets = (
        (None, {'fields': ('url', 'title', 'content', 'meta_description', 'sites')}),
        (_('Advanced options'), {
            'classes': ('collapse',),
            'fields': ('registration_required', 'template_name'),
        }),
    )


admin.site.unregister(FlatPage)
admin.site.register(FlatPage, MarleneFlatPageAdmin)

该解决方案的最大缺点是,如果Django将来将新的迁移添加到平板应用程序,则您要负责管理它们。我建议大家,无论是否适合您当前的情况,都不要使用平板应用程序。