When I use this code to customize my form's widget, it will not validate. If I comment out def __init__(..) it works fine.
class CommentForm(forms.Form):
def __init__(self, *args, **kwargs):
self.wysiwyg = kwargs.pop('wysiwyg', False)
super(CommentForm, self).__init__()
if self.wysiwyg:
self.fields['comment_text'].widget = SummernoteWidget()
else:
self.fields['comment_text'].widget = forms.Textarea(attrs={'rows':2})
comment_text = forms.CharField()
I've been able to troubleshoot this far, and the difference between the working form (no init) and the invalid form, is this:
not valid form with init:
CommentForm bound=False, valid=Unknown, fields=(comment_text)
valid form:
CommentForm bound=True, valid=Unknown, fields=(comment_text)
Is bound the problem and how do I fix it?
Thanks!
Try this .. might work
class CommentForm(forms.Form):
def __init__(self, *args, **kwargs):
try:
self.wysiwyg = kwargs['wysiwyg']
except KeyError:
self.wysiwyg = None
super(CommentForm, self).__init__(*args, **kwargs)
if self.wysiwyg:
self.fields['comment_text'].widget = SummernoteWidget()
else:
self.fields['comment_text'].widget = forms.Textarea(attrs={'rows':2})
comment_text = forms.CharField()
Related
So as the title states, I'm trying to pass a parameter from views to forms. I've seen several Stack Overflow posts regarding this issue, but none of them solved my problem :(
So what I'm trying to build is basically a question-and-answer application. Each user answers to pre-provided questions. I want to make an answering template for each corresponding question. So here's my code:
forms.py
class AnswerForm(forms.ModelForm):
main_answer = formsCharField(required=True)
# Some other fields
def __init__(self, *args, **kwargs):
self.q = kwargs.pop('q')
super(AnswerForm, self).__init__(*args, **kwargs)
self.fields['main_answer'].label = q.main_question
views.py
def createAnswer(request, pk):
thisQuestion = Question.objects.get(question_number=pk)
AnswerFormSet = modelformset_factory(Answer, form=AnswerForm(q = thisQuestion), extra=1)
formset = AnswerFormSet(queryset=Answer.objects.filter(authuser=request.user.id, question_number=pk))
# And some other codes
I'm supposed to show this formset in my template using {% crispy_formset%}. However I keep getting this error: "name 'q' is not defined". What is the problem here?
You pass these when you construct the FormSet with the form_kwargs=… parameter [Django-doc]:
def createAnswer(request, pk):
thisQuestion = Question.objects.get(question_number=pk)
AnswerFormSet = modelformset_factory(Aswer, form=AnswerForm, extra=1)
formset = AnswerFormSet(
form_kwargs={'q': thisQuestion},
queryset=Answer.objects.filter(authuser=request.user.id, question_number=pk)
)
You also will get a name error, because you use q in the __init__ method, but q is not defined:
class AnswerForm(forms.ModelForm):
main_answer = formsCharField(required=True)
# Some other fields
def __init__(self, *args, **kwargs):
# ↓ assign to a local variable q
q = self.q = kwargs.pop('q')
super(AnswerForm, self).__init__(*args, **kwargs)
self.fields['main_answer'].label = q.main_question
I am using a django (3.0) ModelMultipleChoice field for a form. I am trying to modify the queryset to make some restrictions on it.
here is the views :
def nouvelle_tache(request,id_livrable):
livrable=Livrable.objects.get(pk=id_livrable)
projet = livrable.projet
if request.method == "POST":
form = NouvelleTache(request.POST,projet=projet)
tache = form.save(commit=False)
tache.livrable = livrable
tache.id_tache = livrable.id_derniere_tache() + Decimal(0.01)
tache.save()
form.save_m2m()
etat = Temps_etat_tache(etat=form.cleaned_data['etat_initial'],tache=tache)
etat.save()
return redirect('tache',tache.pk)
else:
form = NouvelleTache(projet=projet)
return render(request, 'application_gestion_projets_AMVALOR/nouvelle_tache.html', locals())
And the forms :
class NouvelleTache(forms.ModelForm):
def __init__(self, *args, **kwargs):
projet = kwargs.pop('projet', None)
queryset = Utilisateur.objects.all()
for utilisateur in projet.utilisateurs:
queryset = queryset.exclude(pk=utilisateur.pk)
self.fields['ressources'].queryset = queryset
super(NouvelleTache, self).__init__(*args, **kwargs)
ressources= forms.ModelMultipleChoiceField(queryset=Utilisateur.objects.all() ,widget =forms.CheckboxSelectMultiple )
etat_initial = forms.ModelChoiceField(queryset=Etat_tache.objects.none())
class Meta:
model = Tache
fields = ['libelle']
I have the followig error : 'NouvelleTache' object has no attribute 'fields'
I don't understand why because many other users seems to have similar code and it works.
Any help would be appreciate.
super(NouvelleTache, self).__init__(*args, **kwargs)
needs to be executed first, as the fields are set in the super class:
def __init__(self, *args, **kwargs):
projet = kwargs.pop('projet', None)
queryset = Utilisateur.objects.all()
for utilisateur in projet.utilisateurs:
queryset = queryset.exclude(pk=utilisateur.pk)
super(NouvelleTache, self).__init__(*args, **kwargs)
self.fields['ressources'].queryset = queryset
I have a form:
class ConfigNotifyForm(forms.Form):
sensor_name = forms.ChoiceField(widget=forms.Select(),
label="Sensor",
choices=[],
required=True)
value_min = forms.FloatField(label="Value Min", required=True)
value_max = forms.FloatField(label="Value Max", required=True)
def __init__(self, *args, **kwargs):
super(ConfigNotifyForm, self).__init__(*args, **kwargs)
# Get 'initial' argument if any
initial_arguments = kwargs.get('initial', None)
sensor_choices = ''
if initial_arguments != None:
#for choice in initial_arguments.get('src_choices'):
sensor_choices = tuple(initial_arguments.get('src_choices'))
self.fields['sensor_name'].choices = sensor_choices
It's work ok with template. But when submit, sensor_name not in cleandata except value_min, and value_max. So, it not pass form.is_valid.
But, if I code init like this:
def __init__(self, *args, **kwargs):
super(ConfigNotifyForm, self).__init__(*args, **kwargs)
sensor_choices = (
('', 'Select'),
('a0', 'Ndo'),
('a1', 'pH'),
('a2', 'DO'))
self.fields['sensor_name'].choices = sensor_choices
It's OK. Form is valid. I don't know why. Can anyone help me explain and resolve this issue ? Thanks
The issue is that in your form ConfigNotifyForm you have mentioned sensor_name as required=True. This means that this field cannot be nothing. You HAVE TO pass a value to it in order for your form to be valid. When in your __init__ you hardcode the choices, the field is no more nothing/empty and hence it becomes valid.
I have the following form:
class PlayerAchievementForm(forms.ModelForm):
class Meta:
model = PlayerAchievement
fields = ('achievement',)
def __init__(self, *args, **kwargs):
super(PlayerAchievementForm, self).__init__(**kwargs)
self.fields['achievement'].queryset = Achievement.objects.filter(input_type=0)
I have the following implementation in a view:
def points(request, action, target=None):
if request.method == 'POST':
if target == 'player':
form = PlayerAchievementForm(request.POST)
print form.errors
if form.is_valid():
print 'valid'
elif:
print 'invalid'
On submit, this prints invalid.
If I take out this line in the form:
def __init__(self, *args, **kwargs):
super(PlayerAchievementForm, self).__init__(**kwargs)
self.fields['achievement'].queryset = Achievement.objects.filter(input_type=0)
Then it saves without issue. What is wrong with the init?
I found the answer here: DJango form with custom __init__ not validating
I was missing:
super(PlayerAchievementForm, self).__init__(*args, **kwargs)
I had the same problem and after a lot of tries, the code that work for me is something like that:
(Notice the first instantiation of the the field at class level.)
class PlayerAchievementForm(forms.ModelForm):
achievement = Achievement.objects.filter(input_type=0)
class Meta:
model = PlayerAchievement
fields = ('achievement',)
def __init__(self, *args, **kwargs):
super(PlayerAchievementForm, self).__init__(**kwargs)
self.fields['achievement'].queryset = Achievement.objects.filter(input_type=0)
So, I have the following form:
class DesignItemForm (forms.ModelForm):
def __init__(self, *args, **kwargs):
super(DesignItemForm, self).__init__(*args, **kwargs)
CHOICES=[(i,i) for i in range(MAX_DESIGN_ITEM_QUANTITY)]
self.fields['quantity'] = forms.ChoiceField(choices=CHOICES)
class Meta:
model = DesignItem
fields = ('quantity','trackable',)
My view:
d = Design.object.get(slug=fromInput)
....
DesignItemInlineFormSet = inlineformset_factory(Design, DesignItem, fk_name="design", form=DesignItemForm,)
if request.method == "POST":
formset = DesignItemInlineFormSet(request.POST, request.FILES, instance=d)
if formset.is_valid():
formset.save()
DesignItemInlineFormSet(instance=d)
As you can tell, in my form, I overwrote the quantity field to be a drop down instead of an integer field.
For some reason, when I submit the form, the data is not updated in the database. However, if I change the form to the following, it works (of course, it doesn't have the dropdowns I want, but it posts to the db). Why is this, and how do I fix it?
class DesignItemForm (forms.ModelForm):
def __init__(self, *args, **kwargs):
super(DesignItemForm, self).__init__(*args, **kwargs)
# CHOICES=[(i,i) for i in range(MAX_DESIGN_ITEM_QUANTITY)]
# self.fields['quantity'] = forms.ChoiceField(choices=CHOICES)
class Meta:
model = DesignItem
fields = ('quantity','trackable',)
EDIT: Here is the DesignItem model:
class DesignItem(models.Model):
"""Specifies how many of an item are in a design."""
design = models.ForeignKey(Design, related_name="items")
quantity = models.PositiveIntegerField(default=1)
trackable = models.ForeignKey(Trackable, related_name="used")
have you tried just overriding the widget instead of the whole field?
i guess you want a select widget
def __init__(self, *args, **kwargs):
super(DesignItemForm, self).__init__(*args, **kwargs)
CHOICES=[(i,i) for i in range(MAX_DESIGN_ITEM_QUANTITY)]
self.fields['quantity'].widget = forms.Select(choices=CHOICES)