How to fix modelformset error: __init__() missing 1 required positional argument: 'user'
How to fix modelformset error: __init__() missing 1 required positional argument: 'user'
这是我第一次尝试使用表单集,但遇到了这个错误。我哪里错了?我还不完全明白这是如何工作的。我认为我的表单正在等待用户,但我不知道如何处理它。感谢您的帮助!
错误:
init() 缺少 1 个必需的位置参数:'user'
型号:
class PropertySubmission(models.Model):
BANNER_CHOICES = (
('NB', 'No Banner'),
('FL', 'For Lease'),
('FS', 'For Sale'),
('NL', 'New Listing'),
('SD', 'Sold'),
('LD', 'Leased'),
('RD', 'Reduced'),
('NP', 'New Price'),
('SC', 'Sold Conditionally'),
('CB', 'Custom Banner'),
)
image = models.ImageField(upload_to=user_directory_path, blank=True)
mls_number = models.CharField(max_length=8, blank=True)
headline = models.CharField(max_length=30)
details = RichTextField()
banner = models.CharField(max_length=2, choices=BANNER_CHOICES)
author = models.ForeignKey(User, on_delete=models.CASCADE)
date_posted = models.DateTimeField(default=timezone.now)
date_modified = models.DateTimeField(default=timezone.now)
program_code = models.ManyToManyField(Program)
product = models.ForeignKey('Product', on_delete=models.SET_NULL, null=True)
production_cycle = models.ManyToManyField('ProductionCycle')
shell = models.ForeignKey('Shell', on_delete=models.SET_NULL, null=True)
card_delivery_instructions = models.CharField(max_length=1000, blank=True)
card_delivery_instructions_image = models.ImageField(upload_to=card_delivery_instructions_image_path, blank=True)
形式:
class PropertyCreateKeepInTouchForm(forms.ModelForm):
class Meta:
model = PropertySubmission
fields = ['headline','details','banner','image','mls_number','program_code']
help_texts = {
'details': '110 characters maximum',
}
def clean(self):
cleaned_data = super().clean()
image = cleaned_data.get("image")
mls_number = cleaned_data.get("mls_number")
program_code = cleaned_data.get("program_code")
if mls_number == '' and image is None:
# Only do something if one field are valid so far.
self.add_error('image', 'Please provide an image or MLS number')
self.add_error('mls_number', 'Please provide an image or MLS number')
raise forms.ValidationError("Please provide a number")
if program_code is None:
self.add_error('program_code', 'Please select one or more programs')
raise forms.ValidationError("Please select one or more program")
def __init__(self, user, *args, **kwargs):
super(PropertyCreateKeepInTouchForm, self).__init__(*args, **kwargs)
#self.fields['details'].widget = forms.Textarea(attrs={'rows':4, 'cols':15, 'maxlength':110})
self.fields['details'].label = "Provide Feature Property Details:"
self.fields['program_code'].widget = forms.CheckboxSelectMultiple()
self.fields['program_code'].queryset = Program.objects.filter(client=user).filter(production_cycles__product_name__name='Keep In Touch').filter(production_cycles__submission_deadline__lt=timezone.now()+timedelta(days=30)).filter(production_cycles__submission_deadline__gt=timezone.now()).distinct()
self.fields['program_code'].label = "Select Programs"
self.fields['mls_number'].label = "number - to retrieve a photo of the property."
self.fields['image'].label = "Property Photo"
self.fields['banner'].label = "Select a banner"
self.fields['headline'].label = "Provide a headline"
查看:
from django.forms import modelformset_factory
@login_required
def create_properties_keepintouch(request, num_forms):
property_formset = modelformset_factory(PropertySubmission, form=PropertyCreateKeepInTouchForm, extra=1)
formset = property_formset(queryset=PropertySubmission.objects.none())
return render(request, 'programs/property_submission_create_formset.html', {'formset': formset, 'num_forms':num_forms})
模板:
<form class="form-horizontal" method="POST" action="">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<div class="row form-row spacer">
<div class="col-6">
<hr>
<div class="input-group">
{{ form.media }}
{{form.as_p}}
</div>
</div>
</div>
{% endfor %}
<div class="row spacer">
<div class="col-4 offset-2">
<button type="submit" class="btn btn-block btn-primary">Create</button>
</div>
</div>
</form>
我相信你会想要使用 form_kwargs
:
formset = property_formset(
queryset=PropertySubmission.objects.none(),
form_kwargs={'user': request.user}
)
您已重载 PropertyCreateKeepInTouchForm __init__
方法,因为您需要传递一个用户。但是据我了解,modelform_factory
和 modelformset_factory
函数不允许传递任意参数。
据我所知,您需要手动创建表单集,而不是使用工厂函数。
完成此操作的最简单方法是使用 functools.partial
:
from functools import partial
def create_properties_keepintouch(request, num_forms):
form = partial(PropertyCreateKeepInTouchForm, request.user)
property_formset = modelformset_factory(PropertySubmission, form=form, extra=1)
...
基本上,这会在您实际调用它之前将 user
参数传递给 __init__
函数,这允许 Django 初始化表单 class 本身。
这是我第一次尝试使用表单集,但遇到了这个错误。我哪里错了?我还不完全明白这是如何工作的。我认为我的表单正在等待用户,但我不知道如何处理它。感谢您的帮助!
错误:
init() 缺少 1 个必需的位置参数:'user'
型号:
class PropertySubmission(models.Model):
BANNER_CHOICES = (
('NB', 'No Banner'),
('FL', 'For Lease'),
('FS', 'For Sale'),
('NL', 'New Listing'),
('SD', 'Sold'),
('LD', 'Leased'),
('RD', 'Reduced'),
('NP', 'New Price'),
('SC', 'Sold Conditionally'),
('CB', 'Custom Banner'),
)
image = models.ImageField(upload_to=user_directory_path, blank=True)
mls_number = models.CharField(max_length=8, blank=True)
headline = models.CharField(max_length=30)
details = RichTextField()
banner = models.CharField(max_length=2, choices=BANNER_CHOICES)
author = models.ForeignKey(User, on_delete=models.CASCADE)
date_posted = models.DateTimeField(default=timezone.now)
date_modified = models.DateTimeField(default=timezone.now)
program_code = models.ManyToManyField(Program)
product = models.ForeignKey('Product', on_delete=models.SET_NULL, null=True)
production_cycle = models.ManyToManyField('ProductionCycle')
shell = models.ForeignKey('Shell', on_delete=models.SET_NULL, null=True)
card_delivery_instructions = models.CharField(max_length=1000, blank=True)
card_delivery_instructions_image = models.ImageField(upload_to=card_delivery_instructions_image_path, blank=True)
形式:
class PropertyCreateKeepInTouchForm(forms.ModelForm):
class Meta:
model = PropertySubmission
fields = ['headline','details','banner','image','mls_number','program_code']
help_texts = {
'details': '110 characters maximum',
}
def clean(self):
cleaned_data = super().clean()
image = cleaned_data.get("image")
mls_number = cleaned_data.get("mls_number")
program_code = cleaned_data.get("program_code")
if mls_number == '' and image is None:
# Only do something if one field are valid so far.
self.add_error('image', 'Please provide an image or MLS number')
self.add_error('mls_number', 'Please provide an image or MLS number')
raise forms.ValidationError("Please provide a number")
if program_code is None:
self.add_error('program_code', 'Please select one or more programs')
raise forms.ValidationError("Please select one or more program")
def __init__(self, user, *args, **kwargs):
super(PropertyCreateKeepInTouchForm, self).__init__(*args, **kwargs)
#self.fields['details'].widget = forms.Textarea(attrs={'rows':4, 'cols':15, 'maxlength':110})
self.fields['details'].label = "Provide Feature Property Details:"
self.fields['program_code'].widget = forms.CheckboxSelectMultiple()
self.fields['program_code'].queryset = Program.objects.filter(client=user).filter(production_cycles__product_name__name='Keep In Touch').filter(production_cycles__submission_deadline__lt=timezone.now()+timedelta(days=30)).filter(production_cycles__submission_deadline__gt=timezone.now()).distinct()
self.fields['program_code'].label = "Select Programs"
self.fields['mls_number'].label = "number - to retrieve a photo of the property."
self.fields['image'].label = "Property Photo"
self.fields['banner'].label = "Select a banner"
self.fields['headline'].label = "Provide a headline"
查看:
from django.forms import modelformset_factory
@login_required
def create_properties_keepintouch(request, num_forms):
property_formset = modelformset_factory(PropertySubmission, form=PropertyCreateKeepInTouchForm, extra=1)
formset = property_formset(queryset=PropertySubmission.objects.none())
return render(request, 'programs/property_submission_create_formset.html', {'formset': formset, 'num_forms':num_forms})
模板:
<form class="form-horizontal" method="POST" action="">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<div class="row form-row spacer">
<div class="col-6">
<hr>
<div class="input-group">
{{ form.media }}
{{form.as_p}}
</div>
</div>
</div>
{% endfor %}
<div class="row spacer">
<div class="col-4 offset-2">
<button type="submit" class="btn btn-block btn-primary">Create</button>
</div>
</div>
</form>
我相信你会想要使用 form_kwargs
:
formset = property_formset(
queryset=PropertySubmission.objects.none(),
form_kwargs={'user': request.user}
)
您已重载 PropertyCreateKeepInTouchForm __init__
方法,因为您需要传递一个用户。但是据我了解,modelform_factory
和 modelformset_factory
函数不允许传递任意参数。
据我所知,您需要手动创建表单集,而不是使用工厂函数。
完成此操作的最简单方法是使用 functools.partial
:
from functools import partial
def create_properties_keepintouch(request, num_forms):
form = partial(PropertyCreateKeepInTouchForm, request.user)
property_formset = modelformset_factory(PropertySubmission, form=form, extra=1)
...
基本上,这会在您实际调用它之前将 user
参数传递给 __init__
函数,这允许 Django 初始化表单 class 本身。