【问题标题】:Django flatpages default siteDjango flatpages 默认站点
【发布时间】:2011-01-24 20:26:23
【问题描述】:

我主要为一个站点使用平面页面(来自站点框架)。如何为所有创建的平面页面标记现有站点默认值? 每次为创建的每个页面选择相同的站点都是浪费时间。有没有办法在模型或保存方法中覆盖它?

【问题讨论】:

  • 您的意思是在 Django 管理员中?还是在一般模型上?

标签: django django-flatpages


【解决方案1】:

允许在站点字段中留空 (models.py -> FlatPage.sites) 并将其放入您的模型表单 (admin.py -> FlatPageForm)

def clean_sites(self):
    sites = self.cleaned_data.get('sites')
    print sites
    return [Site.objects.get(id=settings.SITE_ID)]

编辑: 我想出了一个更好的解决方案。 这使得当前站点已经专注于多对多站点领域。编辑 flatpages/admin.py。在文件开头添加:from django.contrib.sites.models import Site,并将以下代码放入class FlatPageAdmin

    def formfield_for_manytomany(self, db_field, request=None, **kwargs):
    if db_field.name == "sites":
        kwargs["initial"] = [Site.objects.get_current()]
    return super(FlatPageAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

FlatPage 模型中的站点字段中不需要允许空白

【讨论】:

  • 明确地说,您不应该在 Django 核心中编辑 flatpages/admin.py。您应该在自己的应用程序中继承 Flatpages Admin 类并覆盖 formfield_for_manytomany() 方法并添加这些行。
  • @JeremyBlanchard,我确实是这么说的 :)
【解决方案2】:

这是我的代码,它可以工作:

class CustomFlatPage(FlatPage):
    def save(self):
        super(CustomFlatPage, self).save()
        self.sites = [Site.objects.get(pk=1)]
        super(CustomFlatPage, self).save()

【讨论】:

  • 完全错了!这样,您将始终选择相同的站点,即使您在管理页面中将其更改为 pk==2 的站点。
【解决方案3】:

这是解决原始问题的完整代码(标记所有创建的平面页面的现有站点默认值):

from django.conf import settings
from django.contrib.flatpages.models import FlatPage
from django.contrib.sites.models import Site

class CustomFlatPage(FlatPage):
    class Meta:
        proxy = True

    def save(self):
        self.sites = [Site.objects.get(pk=settings.SITE_ID)]
        super(CustomFlatPage, self).save()

还有这个解决方案:

  • 在数据库中只运行一次 INSERT 或一次 UPDATE。前一个是通过一个 INSERT 和一个 UPDATE 或两个 UPDATE 访问数据库。
  • 使用proxy = True 不需要运行syncbd 来为CustomFlatPage 模型创建额外的表。

【讨论】:

  • 纠正我自己,这段代码不起作用,因为 django 抱怨在实例有主键之前创建多对多关系。所以,这个super(CustomFlatPage, self).save()需要加在self.sites = [Site.objects.get(pk=settings.SITE_ID)]之前
  • 为什么不能在超过 1 个站点上工作? Site.objects.get(pk=settings.SITE_ID) 将返回您需要的一个站点,无论您创建了多少个站点,不是吗?
  • @ygneo,如果我想在两个站点上拥有一个平面页面怎么办?
  • @seler,如果您想在所有站点中拥有平面页面,您可以这样做:self.sites = Site.objects.all() 如果您想在某些特定站点中拥有它,那么只需使用 filter 而不是 @ 987654329@
  • @ygneo,你真的不明白我的意思。用户必须能够选择是否希望在一个平面页面(例如默认)、两个、三个或全部上提供特定的襟翼。
【解决方案4】:

我采取了不同的方法,猴子修补 FlatpageForm Meta 以使用网站的自定义小部件。

from django.forms import SelectMultiple
from django.conf import settings
from django.contrib.flatpages.forms import FlatpageForm

class PreSelectDefaultSiteOnCreateSelectMultiple(SelectMultiple):
    def render(self, name, value, attrs=None, choices=()):
        if value is None:
            # None in the add form, a list, possibly empty, in
            # the edit form.  So we're adding a new instance here.
            value = [settings.SITE_ID]
        return super(PreSelectDefaultSiteOnCreateSelectMultiple, self
                     ).render(name, value, attrs, choices)

def flatpages():
    """Hack the sites field widget.
    """
    fpafm = FlatpageForm.Meta
    if getattr(fpafm, 'widgets', None) is None:
        fpafm.widgets = {}
    fpafm.widgets['sites'] = PreSelectDefaultSiteOnCreateSelectMultiple

在使用管理员之前,您必须从某个地方调用 flatpages()。我将上面的代码放在monkey_patches包中的模块admin.py中,然后在我的根urls.py中,它在第一次请求进入时被导入,我输入:

from monkey_patches.admin import flatpages
flatpages()

这是在 Django 1.4 和 python 2.7.3 下,但也应该适用于旧版本。

哦,请注意,如果您真的想要一个空的站点关联,您可以有意取消选择它,因为这只是小部件初始化。随后的编辑将传递一个空列表以呈现为值,而不是 None。

比尔,KE1G

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-20
    • 2013-03-01
    • 2011-05-10
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 2019-07-07
    • 1970-01-01
    相关资源
    最近更新 更多