I have this form:
class addMeal(forms.Form):
name = forms.CharField(
max_length=40,
widget=forms.TextInput(attrs={'class':'form-control','placeholder':'نام وعده'})
)
foods = forms.ModelMultipleChoiceField(
queryset=Food.objects.none(),
widget=forms.SelectMultiple(attrs={'class':'form-control'})
)
def save(self,request):
data = self.cleaned_data
meal = Meals(name=data['name'],user=request.user,foods=data['foods'])
meal.save()
def __init__(self, user=None,*args, **kwargs, ):
super().__init__(*args, **kwargs)
if user is not None:
self.fields['foods'].queryset = Food.objects.filter(user=user)
class Meta:
model = Meals
and this view:
#login_required
def addmeal(request):
if request.method == 'POST':
form = addMeal(request.POST)
if form.is_valid():
form.save(request)
return redirect('food:index')
else:
form = addMeal(user=request.user)
return render(request,'addmeal.html',{'form':form})
when i fill out form and press submit django give me error(Field 'id' expected a number but got <QueryDict: {'csrfmiddlewaretoken': ['C2B8y3kLCa5IQ0S5Mvk7Tw0NTU4pNlYicppWlsIL1LCrcc8AuCQzjJkqWNUot4z6'], 'name': ['شام'], 'foods': ['1']}>.).
what should i do to fix it?
Since user is the first parameter, you pass the data as second, so:
#login_required
def addmeal(request):
if request.method == 'POST':
form = addMeal(user=request.user, data=request.POST)
if form.is_valid():
form.save(request)
return redirect('food:index')
else:
form = addMeal(user=request.user)
return render(request,'addmeal.html',{'form':form})
Related
Want to have Django From dropdown filtered by logged-in User (Customer), using __init__ method. But when submit the form, keep having this Field id expected a number but got <QueryDict: { error:
class OrderForm(ModelForm):
class Meta:
model = Order
fields = ['contract', 'quantity', 'status']
def __init__(self, customer, *args, **kwargs):
super(OrderForm, self).__init__(*args, **kwargs)
self.fields['contract'].queryset = Contract.objects.filter(customer=customer)
#login_required(login_url='login')
def createOrder(request):
customer = request.user.customer.id
form = OrderForm(customer)
if request.method == 'POST':
form = OrderForm(request.POST)
if form.is_valid():
form = form.save(commit=False)
form.customer = request.user.customer
form.save()
messages.success(request, 'Ticket submitted successfully .')
return redirect('customer_table')
context = {'form':form}
return render(request, 'create-order.html', context)
you can pass any attribute in form like this
in view:
form = OrderForm(request.POST, customer=request.user)
in form:
def __init__(self, *args, **kwargs):
customer = kwargs.pop('user') # allway before super()
# and call .pop() not .get() on kwargs, for upper class not evaluate user keyword
super(OrderForm, self).__init__(*args, **kwargs)
self.fields['contract'].queryset = Contract.objects.filter(customer=customer)
I summarize the working solutions as below:
View.py
def createOrder(request):
form = OrderForm(request.POST, customer=request.user.customer.id)
if request.method == 'POST':
form = OrderForm(request.POST, customer=request.user.customer.id)
if form.is_valid():
form = form.save(commit=False)
form.customer = request.user.customer
form.save()
messages.success(request, 'Ticket submitted successfully .')
return redirect('customer_table')
context = {'form':form}
return render(request, 'create-order.html', context)
class OrderForm(ModelForm):
class Meta:
model = Order
fields = ['contract', 'quantity', 'status']
def __init__(self, *args, **kwargs):
customer = kwargs.pop('customer')
super(OrderForm, self).__init__(*args, **kwargs)
self.fields['contract'].queryset = Contract.objects.filter(customer__id=customer)
I'm using Django Model Form. Can anyone help me validate those fields to get field error using clean()?
The Name field cannot be repeated in the same office, only in a different one.
form.py
class CreateSalesRepForm(forms.ModelForm):
class Meta:
model = CreateSalesRep
fields = ['name', 'office']
widgets = {
'office': forms.Select(attrs={'class': 'form-control', 'placeholder': 'Enter Office'}),
'name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter Name'})
}
UPDATED (form.py) --- Here is the solution, you can use this codes to validate both insert and update form.
def clean(self):
cleaned_data = super().clean()
office = cleaned_data.get("office")
name = cleaned_data.get("name")
duplicates = CreateSalesRep.objects.filter(office=office, name=name)
if (self.instance.pk and None):
duplicates = duplicates.filter(pk=self.instance.pk)
if duplicates.exists():
msg = "Name already exist in office selected"
self.add_error('name', msg)
self.add_error('office', msg)
view.py
def create_salesrep(request):
if request.method == "POST":
form = CreateSalesRepForm(request.POST or None)
if form.is_valid():
form.save()
messages.success(request, 'Successfully Saved!', 'alert-success')
return redirect('sales_rep')
else:
return render(request, 'salesrep/create_salesrep.html', {'form':form})
else:
form = CreateSalesRepForm()
context = {'form':form}
return render(request, 'salesrep/create_salesrep.html', context)
def update_salesrep(request, pk):
srep = CreateSalesRep.objects.get(id=pk)
form = CreateSalesRepForm(instance=srep)
if request.method == "POST":
form = CreateSalesRepForm(request.POST or None, instance=srep)
if form.is_valid():
form.save()
messages.success(request, 'Successfully Updated!', 'alert-success')
return redirect('sales_rep')
else:
return render(request, 'salesrep/update_salesrep.html', {'form':form})
else:
form = CreateSalesRepForm(instance=srep)
return render(request, 'salesrep/update_salesrep.html', {'form':form})
You can validate in the forms:
class CreateSalesRepForm(forms.ModelForm):
class Meta:
model = CreateSalesRep
fields = ['name', 'office']
def clean(self):
cleaned_data = super().clean()
office= cleaned_data.get("office")
name = cleaned_data.get("name")
duplicates = CreateSalesRep.objects.filter(office=office, name=name)
if self.instance.pk:
duplicates = duplicates.filter(pk=self.instance.pk)
if duplicates.exists():
raise forms.ValidationError('Name already in office')
That being said, you could enforce this in the model/db level as well by adding the following to your CreateSalesRep model:
class CreateSalesRep(models.Model):
...
class Meta:
unique_together = ['office', 'name']
You can try following inside your model class
class Meta:
unique_together = [('office', 'name')]
I am trying to replicate
if form.is_valid():
With the django form wizard. (this question shouldn't have anything to do with the wizard)
I have this code:
class ContactWizard(SessionWizardView):
def get_template_names(self):
return [TEMPLATES[self.steps.current]]
def done(self, form_list, **kwargs):
if self.request.method == 'POST':
print(form_list)
process_form_data(form_list)
return HttpResponseRedirect('../home')
def process_form_data(form_list):
if form.is_valid():
form_data = [form.cleaned_data for form in form_list]
first_name = form_data[0]['first_name']
last_name = form_data[0]['last_name']
email = form_data[0]['email']
fav_food = form_data[0]['fav_food']
fav_drink = form_data[0]['fav_drink']
user = User.objects.create_user(email)
user.first_name = first_name
user.last_name = last_name
user.email = email
user.save()
user_addon = UserAddon.objects.create(user=user,fav_food=fav_food,fav_drink=fav_drink)
user_addon.save()
return form_data
If i print out form_list i get this
odict_values([<UserAddonForm bound=True, valid=True, fields=(fav_food;fav_drink;first_name,last_name;email)>,ContactForm3 bound=True, valid=True, fields=(info1;info2;message)>])
and if i try running it with just
form.is_valid()
i get
Exception Value: name 'form' is not defined
how can i get an equivalent of the form.is_valid() working?
Thanks
You're passing a form_list to the function process_form_data, but checking against name form (by form.is_valid()) which does not exist at that point.
Assuming form_list is an iterable, you can iterate over it and deal with the forms sequentially:
def process_form_data(form_list):
for form in form_list:
if form.is_valid():
form_data = form.cleaned_data
first_name = form_data[0]['first_name']
last_name = form_data[0]['last_name']
I want to store a POST request to a database, so I a had model form MessageForm and called it from views to validate the data and save it.
models.py
class phoneNumber(models.Model):
address = models.CharField(max_length=15)
def __str__(self):
return self.address
class Message(models.Model):
to = models.ForeignKey(phoneNumber, null=True)
sentfrom = models.CharField(max_length=15, null=True)
content = models.TextField(null=True)
def __str__(self):
return '%s' % (self.content)
forms.py
class MessageForm(forms.ModelForm):
class Meta:
model = Message
fields = '__all__'
def __init__(self, *args, **kwargs):
to = kwargs.pop('to', '')
super(MessageForm, self).__init__(*args, **kwargs)
self.fields['to']=forms.ModelChoiceField(queryset=phoneNumber.objects.filter(address=to))
views.py
#csrf_exempt
def incoming(request):
if request.method == "POST":
form = MessageForm(request.POST)
if form.is_valid():
twiml = '<Response><Message>Yes</Message></Response>'
else:
twiml = '<Response><Message>No</Message></Response>'
else:
twiml = '<Response><Message></Message></Response>'
return HttpResponse(twiml, content_type='text/xml')
Nothing is saved and I get No response when I test it.
You can access your errors in views.py
#csrf_exempt
def incoming(request):
if request.method == "POST":
form = MessageForm(request.POST)
if form.is_valid():
twiml = '<Response><Message>Yes</Message></Response>'
else:
print(form.errors)
print(form.non_field_errors)
twiml = '<Response><Message>No</Message></Response>'
else:
twiml = '<Response><Message></Message></Response>'
return HttpResponse(twiml, content_type='text/xml')
Have you tried:
def __init__(self, *args, **kwargs):
to = kwargs.pop('to', '')
super(MessageForm, self).__init__(*args, **kwargs)
self.fields['to'].queryset = phoneNumber.objects.filter(address=to)
Also I'm not sure if you want to pass anything to the form in views method, because right now your to in form is empty string, so your queryset is querying on phoneNumber.objects.filter(address=''), which may or may not be what you want.
Edit:
The reason that to is empty string because kwargs.pop('to', '') means "pop argument to out from kwargs, if to is not there the default is ''". In your views you do:
form = MessageForm(request.POST)
but you didn't feed the constructor with any to argument, so kwargs.pop('to', '') would get '' as default value. You might need something like:
form = MessageForm(request.POST, to="white house")
I have a from created which is generated by a model. I can save the form, but the form data is not inserted into the table. The insert occurs, but with blank data. Any help would be greatly appreciated.
models.py
class HelpDefinition(models.Model):
org = models.IntegerField(default=0)
help_type = models.CharField(max_length=255)
help_content = models.TextField(blank=True)
def __unicode__(self):
return self.name
views.py
def index(request, org_id=None):
help_def = HelpDefinition()
if org_id:
help_def = HelpDefinition.objects.get(org=org_id)
if request.method == 'POST':
form = FormHelp(request.POST)
if form.is_valid():
help_def.save()
messages.success(request, 'Saved!')
else:
messages.error(request, 'Ugh')
else:
form = FormHelp(request=request, initial=initial_data)
return {
'form': form,
}
forms.py
class FormHelp(forms.Form):
org = forms.CharField(widget=forms.HiddenInput, required=True)
help_type = forms.ChoiceField(abel='Text', required=True)
help_content = forms.CharField(label='Description', required=True, widget=forms.Textarea)
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(FormHelp, self).__init__(*args, **kwargs)
Due that you dont use ModelForm, you need to set your attributes one by one.
if request.method == 'POST':
form = FormHelp(request.POST)
if form.is_valid():
help_def.org = form.cleaned_data.get("org")
help_def.help_type = form.cleaned_data.get("help_type")
help_def.help_type = form.cleaned_data.get("help_content")
help_def.save()