8

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?

Ali Ismayilov
  • 5,727
  • 2
  • 22
  • 24

4 Answers4

9

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

seler
  • 8,803
  • 4
  • 41
  • 54
  • To be clear, you shouldn't edit flatpages/admin.py inside Django core. You should subclass the Flatpages Admin class in your own app and the override the formfield_for_manytomany() method and add these lines. – Jeremy Blanchard Feb 20 '13 at 23:31
  • @JeremyBlanchard, sure that's what I ment :) – seler Feb 21 '13 at 07:48
2

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()
Ali Ismayilov
  • 5,727
  • 2
  • 22
  • 24
  • 1
    it's totally wrong! this way you will always have the same site selected, even if you change it in admin page to site where pk==2. – seler May 06 '11 at 22:26
1

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

ke1g
  • 11
  • 1
1

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.
ygneo
  • 416
  • 3
  • 10
  • Correcting myself, this code don't works, cause django complains about creating many-to-many relationships before the instance has a primary key. So, this `super(CustomFlatPage, self).save()` need to be added before `self.sites = [Site.objects.get(pk=settings.SITE_ID)]` – ygneo Apr 24 '11 at 22:45
  • Why that won't work on more than 1 site? `Site.objects.get(pk=settings.SITE_ID)` will return the one site you need, no matter how many sites did you created, didn't it? – ygneo May 08 '11 at 18:01
  • @ygneo, what if i want to have one flatpage on two sites? – seler May 08 '11 at 18:09
  • @seler, if you want to have the flatpage in all sites, you can do: `self.sites = Site.objects.all()` And if you want to have it in some specific sites, then just use `filter` instead of `all()` – ygneo May 08 '11 at 18:31
  • @ygneo, you really dont understand my point. users must be able to choose if they want to have certain flapage available on one flatpage (default for example), or on two, or three or all. – seler May 08 '11 at 18:39