我正在尝试为网站创建一个简单的页面版本控制系统。我希望能够将页面传递给表单,该表单指向与页面相关的所有版本,并使表单下拉列表包含该页面的所有版本,并使初始页面版本成为理想版本在视图中初始化。到目前为止,表单将填充页面的所有版本,但不会选择理想版本作为初始项目。
如果在视图中初始化表单时填充字段,如何设置表单中字段的初始项?
研究
我在以下问题中尝试了答案,但没有一个人有解决方案:
示例代码:
models.py
timezone
forms.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
views.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
答案 0 :(得分:1)
您需要重置choices
属性,因为一旦设置了queryset,它就会缓存在字段上,即使您更新queryset
属性,也不会重新验证。
def __init__(self, *args, **kwargs):
...
self.fields['version'].queryset = page.versions
self.fields['version'].widget.choices = self.fields['version'].choices
你能检查一下Django版本中的ModelChoiceField
是否有一个名为_set_queryset
的setter方法吗?它似乎是在github中修复的。