我面临以下情况:我有一个名为Contact
的Django模型类,它看起来像:
class Contact(models.Model):
first_name = models.CharField(max_length=70)
last_name = models.CharField(max_length=70)
company = models.ForeignKey(Company) // should be disabled in user-facing forms
organizations = models.ManyToManyField(Organization) // should be disabled and hidden in user-facing forms
// some other fields not relevant to this question
应用程序的用户和管理员都应该能够创建类型Contact
的对象并将其存储在数据库中。但是,对于用户而言,应以无法自由选择Contact
对象的公司字段的方式对此进行限制。为此,我创建了一个名为ModelForm
的基础ContactForm
(供管理员使用)和一个受限制的面向用户的子类RestrictedContactForm
。代码如下:
class ContactForm(forms.modelForm):
class Meta:
model = Contact
fields = ['first_name', 'last_name', 'company', 'organizations']
class RestrictedContactForm(ContactForm):
class Meta(ContactForm.Meta):
widgets = {'organizations': forms.HiddenInput()}
def __init__(self, *args, **kwargs):
super(RestrictedContactForm, self).__init__(*args, **kwargs)
// Maybe populate company and organization here somehow?
self.fields['company'].disabled = True
self.fields['organization'].disabled = True
RestrictedContactForm
会在用户决定创建新联系人后呈现给用户。显然,由于company
和organization
字段都是必填字段,因此需要以某种方式手动注入它们。我的问题恰恰在这里:我没有设法手动填充这些字段。
在下面,您可以找到实现用户发起的创建逻辑的视图功能的概述。
def create_contact(request, company_pk):
company = Company.objects.get(pk=company_pk)
organization = Organization.objects.get(...)
if request.method == 'POST':
// Add company.pk and organization.pk to POST here?
// Pass data dictionary manually populated from POST and
// with company.pl and organization.pk to constructor?
contact_form = RestrictedContactForm(request.POST, request.FILES)
// Add company.pk and organization.pk to contact_form.data
// here (after making it mutable)?
if contact_form.is_valid():
contact_form.save()
return redirect(...)
return render(...)
contact_form = ContactForm(initial={'company': company, 'organizations': organization})
我已经尝试了上面评论中出现的所有建议。该表格根本无法验证。因此,我的问题是,这样做的正确方法是什么?此外,该方法至少在概念上是否正确?
该项目使用Django 1.9。
答案 0 :(得分:0)
我一直使用form_valid方法完成此操作。在这种情况下,请使用子表单的form_valid方法:
def form_valid(self, form):
form.instance.company = foo
form.instance.organisation = bar
return super().form_valid(form)
这将填充缺少的字段,然后保存表单。
答案 1 :(得分:0)
如果用户无法更改company
和organization
字段,则不应将它们完全包含在RestrictedContactForm
中的字段 中。
您可以做的是将organization
和company
的已知值传递到表单的构造函数中,然后将它们分配给对象,然后再在数据库中实际创建它。
class RestrictedContactForm(ContactForm):
class Meta(ContactForm.Meta):
fields = ['first_name', 'last_name', ]
def __init__(self, company, organization, *args, **kwargs):
super(RestrictedContactForm, self).__init__(*args, **kwargs)
self.company = company
self.organization = organization
def save(self, commit=True):
instance = super(RestrictedContactForm, self).save(commit=False)
if not instance.pk:
instance.company = self.company
instance.organization = self.organization
if commit:
instance.save()
return instance
def create_contact(request, company_pk):
# ...
if request.method == 'POST':
company = Company.objects.get(pk=company_pk)
organization = company.organization
contact_form = RestrictedContactForm(company, organization, request.POST, request.FILES)
# ...
# ...