Ali Ismayilov
Ali Ismayilov

Reputation: 5837

Django flatpages default site

mostly I use flatpages for one site (from sites framework). How can I mark existing site default for all created flatpages? It is waste of time every time to choose same site for every page created. Is there any way to override this in models or save method?

Upvotes: 8

Views: 2197

Answers (4)

ke1g
ke1g

Reputation: 11

I took a different approach, monkey patching the FlatpageForm Meta to use a custom widget for sites.

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

You must call flatpages() from somewhere before the admin might be used. I put the code above in a module admin.py in a package monkey_patches, then in my root urls.py, which gets imported the first time a request comes in, I put:

from monkey_patches.admin import flatpages
flatpages()

This is under Django 1.4 with python 2.7.3, but should work for older versions too.

Oh, and note that if you really want an empty sites association, you can deselect it intentionally, since this is just widget initialization. Subsequent edits will pass an empty list to render as value, which isn't None.

Bill, KE1G

Upvotes: 1

seler
seler

Reputation: 9193

allow for blank in sites field (models.py -> FlatPage.sites) and put this in your model Form (admin.py -> FlatPageForm)

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

edit: I've come up with a better solution. This makes current site already focused in ManyToMany sites field. Edit flatpages/admin.py. Add :from django.contrib.sites.models import Site in the beggining of file and put following code into 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)

There is no need to allow for blank in sites field in FlatPage model

Upvotes: 9

ygneo
ygneo

Reputation: 412

Here is a completely working piece of code solving the original problem (to mark existing site default for all created flatpages):

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()

Also this solution:

  • Only runs one INSERT or one UPDATE in the DB. The previous one was hitting the DB with one INSERT and one UPDATE, or two UPDATES.
  • By using proxy = True is not necessary to run syncbd in order to create an extra table for CustomFlatPage model.

Upvotes: 1

Ali Ismayilov
Ali Ismayilov

Reputation: 5837

Here is my code, it works:

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

Upvotes: 2

Related Questions