I'm trying to create a simple page versioning system for a website. I want to be able to pass a page into a form, which points to all of the versions related to the page, and have the form dropdown contain all of the versions for that page, and make the initial page version the ideal version when it is initialized in the view. So far, the form will fill with all of the versions for the page, but not select the ideal version as the initial item.
How do I set the initial item of a field in a form if the field gets populated while the form is initialized in the view?
Research:
I have tried the answers in the following questions, but none of them had the solution:
- Setting initial value of Django ModelChoiceField
- Django: How to set initial values for a field in an inline model formset?
- Setting initial value of Django ModelChoiceField
Example code:
models.py
from django.db import models
from autoslug import AutoSlugField
from django_enumfield import enum
from ..users.models import User
def write_page(name, submitter, content=''):
page = Page.objects.get_or_create(name=name)[0]
page_version = PageVersion.create(page, submitter, content)
return page_version
class Status(enum.Enum):
DISABLED = 0
ACTIVE = 1
class Page(models.Model):
name = models.CharField(max_length=100)
slug = AutoSlugField(populate_from='name', unique=True)
status = enum.EnumField(Status, default=Status.ACTIVE)
current_version = models.IntegerField(default=0)
def __unicode__(self):
name_str = "(name='{}', slug='{}')"
return name_str.format(self.name, self.slug)
@property
def versions(self):
status = ("status = {}".format(Status.ACTIVE),)
order_by = ("-version",)
return self.pageversion_set.extra(where=status, order_by=order_by)
@property
def all_versions(self):
order_by = ("-version",)
return self.pageversion_set.extra(order_by=order_by)
@property
def ideal(self):
try:
return PageVersion.objects.get(id=self.current_version)
except self.DoesNotExist:
return None
@property
def version(self):
if self.ideal:
return self.ideal.version
return 0
@property
def content(self):
if self.ideal:
return self.ideal.content
return ''
@property
def submitter(self):
if self.ideal:
return self.ideal.submitter
return None
@classmethod
def create(cls, name):
page_object = cls.objects.create(name=name)
return page_object
class PageVersion(models.Model):
parent = models.ForeignKey(Page)
version = models.IntegerField(default=0)
content = models.TextField()
date = models.DateTimeField(auto_now_add=True)
status = enum.EnumField(Status, default=Status.ACTIVE)
submitter = models.ForeignKey(User)
def __unicode__(self):
name_str = "(name='{}', slug='{}', version={})"
return name_str.format(self.name, self.slug, self.version)
@property
def name(self):
return self.parent.name
@property
def slug(self):
return self.parent.slug
@classmethod
def create(cls, page, submitter, content='', make_current=True):
if page.all_versions:
current_max_version = max([i.version for i in page.all_versions])
else:
current_max_version = 0
page_version_object = cls(parent=page, submitter=submitter, content=content)
page_version_object.version = current_max_version + 1
page_version_object.save()
if make_current:
page.current_version = page_version_object.id
page.save()
return page_version_object
forms.py
from django import forms
from .models import PageVersion
class PageVersionForm(forms.Form):
version = forms.ModelChoiceField(queryset=None)
def __init__(self, *args, **kwargs):
page = kwargs.pop("page")
super(PageVersionForm, self).__init__(*args, **kwargs)
self.fields["version"].queryset = page.versions
views.py
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponseForbidden
from django.core.urlresolvers import reverse
from .models import Page, write_page
from .forms import PageForm, PageVersionForm
from ..helpers import get_pages
def update_page(request, slug):
if not request.user.has_perm("can_edit_page"):
return HttpResponseForbidden()
page = get_object_or_404(Page, slug=slug)
if request.method == "POST":
form = PageForm(request.POST)
if form.is_valid():
content = form.cleaned_data["content"]
user = request.user
write_page(name=page.name, submitter=user, content=content)
kwargs = {}
kwargs["slug"] = slug
return HttpResponseRedirect(reverse("pages:detail", kwargs=kwargs))
else:
data = {}
data["content"] = page.content
form = PageForm(data)
context = {}
page_version_form = PageVersionForm(page=page)
context["form"] = form
context["page_version_form"] = page_version_form
context["page"] = page
context["user"] = request.user
context.update(get_pages())
return render(request, "pages/page_update.html", context)