我有一个项目模型如下:
class Project(models.Model):
name = models.CharField(max_length=255, null=False)
launch_date = models.CharField(max_length=20, null=False)
possession_date = models.CharField(max_length=20, null=False)
每个项目都有权限表中的一组权限:
class Permissions(models.Model):
name = models.CharField(max_length=255)
现在权限表中可能有多个权限。对于权限表中的每个权限,都有相应的值,例如grant / applied等。所以有一个项目权限表如下:
class ProjectPermission(models.Model):
project = models.ForeignKey('Project')
permission = models.ForeignKey('Permissions')
value = models.CharField(max_length=255)
所以我做了以下表格:
class PermissionForm(forms.Form):
def __init__(self, *args, **kwargs):
super(PermissionForm, self).__init__(*args, **kwargs)
permissions = Permissions.objects.all()
for permission in permissions:
self.fields[permission.name] = forms.CharField(
widget=forms.Select(choices=(
('Approved', 'Approved'),
('In Process', 'In Process'),
('Not Applied', 'Not Applied'),
('Denied', 'Denied'),
)))
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.disable_csrf = True
self.helper.form_id = 'permission-form'
def save(self, *args, **kwargs):
project = kwargs.pop('project')
for field in self.fields:
permission = Permissions.objects.filter(name=field).first()
p = ProjectPermission(
project=project,
permission=permission,
value=self.cleaned_data[field]
)
p.save()
return project
但问题是一个数据被保存,我无法使用正确的数据重新呈现表单,也无法更新数据。如果我更改字段的值并保存表单,它会在ProjectPermission表中创建一个新条目。
这是因为我在初始化表单时没有指定实例吗?如果是这样,我该如何指定实例?
答案 0 :(得分:0)
Django有ModelForms
to save you repeating your model code in forms。我假设您使用了您发布的代码中的crispy forms。我将带您了解一个简单的ModelForms示例。
首先,我想创建一个自己的基本表单类来分解一些常见的布局,如下所示:
# core Django imports
from django.forms import ModelForm
# third-party imports
from crispy_forms.helper import FormHelper
class MyForm(ModelForm):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
self.helper.form_class = 'form-horizontal'
现在假设我们有一个这样的模型,我们想要创建/更新/等等:
class Event(models.Model):
"""
Represents an individual event.
"""
name = models.CharField(max_length=50)
topic = models.ForeignKey(Topic)
date = models.DateField(help_text='dd/mm/yyyy')
start_time = models.TimeField(help_text='HH:MM - 24hr clock')
finish_time = models.TimeField(help_text='HH:MM - 24hr clock')
location = models.CharField(max_length=50)
attendees_need_to_sign_up = models.BooleanField(
default=False,
help_text="Tick the box if you're giving an open invite to attend",
)
organiser = models.ForeignKey(
Person,
related_name = "organiser",
)
...
您现在可以拥有这样的ModelForm:
class EventForm(MyForm):
def __init__(self, *args, **kwargs):
super(EventForm, self).__init__(*args, **kwargs)
self.helper.form_id = 'event-form'
self.helper.layout = Layout(
Field(
'topic',
template='events/related_topic.html',
),
Field('name', css_class='input-xlarge'),
Field('agenda', css_class='input-xlarge'),
Field('date', css_class='input-xlarge'),
Field('start_time', css_class='input-xlarge'),
Field('finish_time', css_class='input-xlarge'),
Field('location', css_class = 'input-xlarge'),
Field('attendees_need_to_sign_up', css_class = 'input-xlarge'),
FormActions(
Submit(
'save_changes',
'Save changes',
css_class = "btn-primary",
),
Button(
'cancel',
'Cancel',
onclick = 'history.go(-1);'
),
),
)
self.fields['name'].label = 'Event name'
def clean(self):
# custom validation goes here
...
class Meta:
model = Event
fields = (
'topic',
'name',
'agenda',
'date',
'start_time',
'finish_time',
'location',
'attendees_need_to_sign_up',
)
现在你只需要你的观点和模板。观点很简单:
# core django imports
from django.core.urlresolvers import reverse
from django.http import HttpResponse, HttpResponseRedirect
from django.views.generic import (
CreateView,
DetailView,
ListView,
UpdateView,
)
# third party imports
from braces.views import LoginRequiredMixin
...
class EventCreateView(LoginRequiredMixin, CreateView):
model = Event
form_class = EventForm
login_url = "/login/"
def get_context_data(self, **kwargs):
context = super(EventCreateView, self).get_context_data(**kwargs)
context['topics'] = Topic.objects.all()
return context
class EventUpdateView(LoginRequiredMixin, UpdateView):
model = Event
form_class = EventUpdateForm
login_url = "/login/"
LoginRequiredMixin来自Django braces。
您的模板现在非常简单,因为您已经在Python代码中定义了所有表单。您需要在{% extends %}
声明之后放置以下内容来包含crispy表单模板标记:
{% load crispy_forms_tags %}
然后放置:
{% crispy form %}
您想要表格的任何地方。