Django Attribute Error - Form object has no attribute 'is_valid' - python

I am receiving an error, object has no attribute 'is_valid', when trying to insert form data into a form. Below is the structure of my code:
Views.py:
def add_user(request):
form = Car(request.POST)
if request.method == 'POST' and form.is_valid():
last_store = form.cleaned_data.get['value']
make = request.POST.get('make', '')
model = request.POST.get('model', '')
..
car_obj = Car(last_store = last_store, make = make, model = model, series = series, series_year = series_year, price_new = price_new, engine_size = engine_size, fuel_system = fuel_system, tank_capacity = tank_capacity, power = power, seating_capacity = seating_capacity, standard_transmission = standard_transmission, body_type = body_type, drive = drive, wheelbase = wheelbase, available = available)
car_obj.save()
return HttpResponseRedirect('/inventory/add/')
else:
form = Car()
return render(request, 'cars/inventory-add.html', {})
Class:
class Car(models.Model):
make = models.CharField(max_length=200, null=False)
model = models.CharField(max_length=200, null=False)
series = models.CharField(max_length=200, null=False)
series_year = models.IntegerField(null=False)
price_new = models.IntegerField(null=False)
..
last_store = models.ForeignKey(Store, on_delete=models.DO_NOTHING, related_name="last_store")
available = models.BooleanField(null=False, default=True)
def __str__(self):
return(self.make + " " + self.model)
CarForm (forms.py)
class CarForm(forms.ModelForm):
class Meta:
model = Car
fields = ['last_store', 'make', 'model', 'series', 'series_year', 'price_new', 'engine_size', 'fuel_system', 'tank_capacity', 'power', 'seating_capacity', 'standard_transmission', 'body_type', 'drive', 'wheelbase', 'available']
The error lies within the last_store as without form.is_valid(), apparently I cannot use form.cleaned_data, but form.is_valid() seems to not even exist? As seen in the class, last_store is of type a foreign key, therefore I am struggling to set the default value for it when the user enters input into the form. The last_store variable is attempting to fetch the value from the inputted form data which consists of a SELECT option..

You have a clash between your model and form, which are both named Car. Typically you would fix this by renaming the form CarForm.
Note that you shouldn't normally need to create the object with car_obj = Car(...). If you use a model form, you can simplify your code to car_obj = form.save(). You should also move CarForm(request.POST) inside the if request.method == 'POST' check, and include form in the template context. Putting that together, you get something like:
def add_user(request):
if request.method == 'POST':
form = CarForm(request.POST)
if form.is_valid():
car_obj = form.save()
return HttpResponseRedirect('/inventory/add/')
else:
form = CarForm()
return render(request, 'cars/inventory-add.html', {'form': form})

In your views.py file line 2
form = Car(request.POST):
change it to
form = CarForm(request.POST):
Hope it works!

Related

Show multi-selected itens when load a edit view

I'm doing a edit form for some data. I'm having problem to pass information to . As you can see in my view, I pass the data to form using "initial" dictionary.
VIEWS.PY
#login_required
def project_detail(request, project_id):
if request.method == 'POST':
project = get_object_or_404(Project, pk=project_id)
form = ProjectDetailForm(project_id, request.POST, instance = project)
if form.is_valid():
instance = form.save(commit=False)
instance.client = Project.objects.get(pk=project_id).client
form.save()
messages.success(request,'Projeto modificado')
return redirect('projects')
else:
messages.error(request,'Ocorreu um erro!')
else:
project = get_object_or_404(Project, pk=project_id)
form = ProjectDetailForm(project_id, initial={'modal':project.modal,
'culture':project.culture,
'owner':project.owner,
'value':project.value,
'final_date':project.final_date,
'text':project.text,
'status':project.status,
'farm':project.farm.values()})
return render(request,'project_detail.html',{'form':form})
But doing this, the data is not displaied in . Thinking here, ManyToManyField saves data in lists. I tried iterate this field but still not working and I guess thats not the best way to do this.
MODELS.PY
class Project(models.Model):
modal_types = [('CUSTEIO AGRÍCOLA','Custeio Agrícola'),('CUSTEIO PECUÁRIO','Custeio Pecuário'),('INVESTIMENTO AGRÍCOLA','Investimento Agrícola'),('INVESTIMENTO PECUÁRIO','Investimento Pecuário'),('FGPP','FGPP')]
status_opts = [('Análise','Análise'),('Desenvolvimento','Desenvolvimento'),('Processamento','Processamento'),('Liberação','Liberação'),('Finalizado','Finalizado'),('Cancelado','Cancelado'),('Suspenso','Suspenso')]
farm = models.ManyToManyField(Farm, related_name='farm_name',verbose_name='Propriedade beneficiada')
client = models.ForeignKey(Clients, on_delete=models.CASCADE, related_name='project_client',default=None,null=True, verbose_name='Cliente')
owner = models.ForeignKey(Owner, on_delete=models.CASCADE, related_name='project_bidder',default=None,null=True, verbose_name='Proponente')
warranty = models.ManyToManyField(Farm, related_name='project_warranty',default=None, verbose_name='Propriedade de garantia')
modal = models.CharField(max_length=100,default=None,choices=modal_types, null=True, verbose_name='Tipo')
culture = models.CharField(max_length=50,null=True, verbose_name='Cultura')
status = models.CharField(max_length=50,null=True, verbose_name='Status', choices=status_opts)
created_date = models.DateField(null=True, verbose_name='Data de criação')
value = models.FloatField(max_length=10,null=True, verbose_name='Valor financiado')
final_date = models.DateField(default=None,null=True, verbose_name='Fim do contrato')
text = models.TextField(default=None,null=True, verbose_name='Observações')
forms.py
class ProjectDetailForm(ModelForm):
class Meta:
model = Project
fields = ['status','owner', 'farm', 'warranty', 'modal', 'culture', 'value','final_date','text']
def __init__(self, project_id, *args, **kwargs):
client_id = Project.objects.get(pk=project_id).client
super(ProjectDetailForm,self).__init__(*args,**kwargs)
self.fields['value'].required = False
self.fields['final_date'].required = False
self.fields['text'].required = False
self.fields['farm'].queryset = Farm.objects.filter(client=client_id)
self.fields['warranty'].queryset = Farm.objects.filter(client=client_id)
for field_name, field in self.fields.items():
field.widget.attrs['class'] = 'form-control'
Here all the fields with information, but in "select" nothing is selected, despite having data in the database
Someone can help me?
Why are you passing 'project_id' into your form class instance? Try changing this:
form = ProjectDetailForm(project_id, request.POST, instance = project)
to this:
form = ProjectDetailForm(request.POST, instance = project)
and see if it helps. Also in your form initialization, I'm not sure you're using the "initial=" values dictionary correctly. Initial values are typically defaults applicable to the "create" view, not database records that it sounds like you want to see in an update view. I think you want to pass in the instance of your database record there, something like:
else:
project = get_object_or_404(Project, pk=project_id)
form = ProjectDetailForm(instance=project)
Also, you really don't need to write project object query twice in this view. You can do something like:
def project_detail(request, project_id):
project = get_object_or_404(Project, pk=project_id) # query this once here
if request.method == 'POST':
form = ProjectDetailForm(request.POST, instance=project)
if form.is_valid():
instance = form.save(commit=False)
instance.client = Project.objects.get(pk=project_id).client
form.save()
messages.success(request,'Projeto modificado')
return redirect('projects')
else:
messages.error(request,'Ocorreu um erro!')
# you probably want a redirect here as well
else:
form = ProjectDetailForm(instance=project)
return render(request,'project_detail.html',{'form':form})
Finally, if you're trying to limit the choices from your ManyToMany field in the user's form, you can do so with something like this:
class ProjectDetailForm(forms.ModelForm):
class Meta:
model = YourModelName
fields = ['farm']
farm = forms.ModelMultipleChoiceField(
queryset=Farm.objects.filter(some_field=some_criteria).order_by('some_field'),
widget=forms.CheckboxSelectMultiple)
More info about widgets on form classes here in Django docs.

How to update the one attribute of model once form is validated in Django?

I have a model
class Tutor(models.Model):
name = models.CharField(max_length=100)
qualification = models.CharField(max_length=100)
experience = models.CharField(max_length=200)
tution_fee = models.CharField(max_length=100)
about = models.CharField(max_length=1000)
demo_classes_link = models.CharField(max_length=1000)
contact_number = models.CharField(max_length=10)
email_id = models.EmailField(null=True, blank=True)
material = models.CharField(max_length=1000)
status = models.BooleanField(null=True, blank=True)
and a form
class GeeksForm(forms.ModelForm):
# specify the name of model to use
class Meta:
model = Tutor
fields = "__all__"
Now I have captured all the data using POST API form is validated.
def registration(request) :
form = GeeksForm(request.POST)
# Check if the form is valid:
if form.is_valid():
number = request.POST['contact_number']
print(number)
r = requests.get('http://apilayer.net/api/validate?access_key=***********&number=*******&country_code=+91&format=1', params=request.GET)
if r.status_code == 200:
form['status'] = 1 # I want to update this once is form is validated, django throws an error.
form.save()
return HttpResponse('Yay, it worked')
currentID = form.auto_id
print(currentID)
# form = GeeksForm()
else :
print("Invalid")
return render(request, 'Tutorform.html', {'form': form})
How do I update status parameter of model in django after form validation is successful ?
Change form['status'] = 1 to form.cleaned_data['status'] = True
When a form is validated, its data is also "cleaned" (i.e. consolidated into one uniform format), and stored in a dictionary called cleaned_data, which is used when saving the form. You should edit it there.
Though, I'm not entirely sure, a BooleanField will probably expect True instead of 1.
It's also possible to save the instance first, and edit status later:
instance = form.save()
instance.status = True
instance.save()
Retrieve the underlying model instance, change the field value and save the form.
if r.status_code == 200:
myform = form.save(commit=False) #returns model instance object
myform.status = True
myform.save()
return HttpResponse('Yay, it worked')

How to assign value of field of one model to field of another model?

Say, I have a view function that creates a Vacancy object on saving the form, and it has the field company that, if the form is valid, has to be assigned with value of field name, that is on the other model named EmployerProfile, how can I do that? I have company as a foreign key on my model.
My models
class EmployerProfile(models.Model):
name = models.CharField(max_length = 64)
description = models.TextField()
username = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete = models.CASCADE)
class Vacancy(models.Model):
name = models.CharField(max_length = 64)
competences = models.CharField(max_length = 32)
salary = models.DecimalField(decimal_places = 2, max_digits = 10)
description = models.TextField(null = True)
company = models.ForeignKey(EmployerProfile, on_delete = models.CASCADE)
featured = models.BooleanField(default = False)
My view
#login_required(login_url = 'login')
def vacancyAddView(request):
if request.method == 'POST':
form = VacancyAddForm(request.POST)
if form.is_valid():
form.save()
return redirect('profile')
else:
form = VacancyAddForm()
context = {
'form':form
}
return render(request, "addVacancy.html", context)
My form
class VacancyAddForm(forms.ModelForm):
class Meta:
model = Vacancy
fields = [
'name',
'competences',
'description',
'salary',
]
P.S. I have tried adding this piece of code to my view, rigth after form.is_valid():
obj = EmployerProfile.objects.get(username = request.user)
form.instance.company = obj.name
but it didn't work, it returned the ValueError with text "Vacancy.company" must be a "EmployerProfile" instance.
P.P.S. I also tried to override the save method in my model like this
def save(self, *args, **kwargs):
self.company = self.EmployerProfile.name
super(Vacancy, self).save(*args, **kwargs)
but it didn't work either.
You can't do what you want. Your Vacancy model defines company as a foreign key, but you're trying to set it as a string.
class Vacancy(models.Model):
company = models.ForeignKey(EmployerProfile, on_delete = models.CASCADE)
However, here's what your view should change to be to work with your models as you've defined them currently.
#login_required(login_url = 'login')
def vacancyAddView(request):
if request.method == 'POST':
form = VacancyAddForm(request.POST)
if form.is_valid():
# Set the company
form.instance.company = request.user.employerprofile
form.save()
return redirect('profile')
else:
form = VacancyAddForm()
context = {
'form':form
}
return render(request, "addVacancy.html", context)
The basic issue here is that you can't set a ForeignKey field to be a string. If you want the user to be able to set the Company from the form, you have a couple of choices. One is to take what you have now in the form and use it to filter, e.g. something like:
company = EmployerProfile.objects.filter(name__iexact=form.cleaned_data['company'])
form.instance.company = company
Another would be to change the form so that instead of a text input, company is a ModelChoiceField, or a regular ChoiceField populated with the company choices available to the user.
In either case the end goal will be to ensure that the company field contains a foreign key to an EmployerProfile object, rather than the string name of a company.

Django get error : id() takes exactly one argument (0 given) ,save with foreign key

So I have a problem about how to save model instance with foreign key relation,
models.py
class Connect(models.Model):
username = models.CharField(max_length=255)
password = models.CharField(max_length=255,null=True, blank=True)
conft = models.TextField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return unicode(self.username)
class Ip(models.Model):
class Meta:
db_table = 'autonet_ip'
connect_id = models.ForeignKey(Connect, on_delete=models.CASCADE)
ipaddr = models.CharField(max_length=255)
def __str__ (self):
return self.ipaddr
forms.py
class NacmForm(ModelForm):
password = forms.CharField(widget=forms.PasswordInput,required = False)
class Meta:
model = Connect
fields = ['username', 'password','conft']
labels = {'conft':_('Config'),}
class IpForm(ModelForm):
class Meta:
model = Ip
fields = ['ipaddr']
labels = {'ipaddr':_('IP address'),}
IpFormset = formset_factory(IpForm, extra=1)
views.py
def konfig(request):
ip_list = []
status = ''
value_bak = 1
if request.method == 'POST':
formm = NacmForm(request.POST or None)
ipform = IpFormset(request.POST)
upform = UploadForm(request.POST,request.FILES)
userValue = formm['username'].value()
passValue = formm['password'].value()
confValue = formm['conft'].value()
usernamef = get_object_or_404(Connect, pk=id)
if ipform.is_valid():
for form in ipform:
ipaddr = form.cleaned_data.get('ipaddr')
//.... some code ...//
simpanIp = form.save(commit=False)
simpanIp.connect_id = usernamef
simpanIp.save()
simpanForm.save()
return HttpResponseRedirect('/konfig')
else:
formm = NacmForm()
ipform = IpFormset()
return render(request, 'konfig.html', {'form': formm, 'logins': Connect.objects.all(), 'ipform': ipform, 'status': status })
Then, when I input all data and click submit to collect form data and on simpanIp.save(), I've got an error: id() takes exactly one argument (0 given).
I just want to know how to save the instance of Connect model to database with foreign key, thanks in advance
so i edit my models.py like this
class Connect(models.Model):
......
def get_usernameinf(self):
return ', '.join(self.usernameinf.all().values_list('username', flat=True))
and views.py like this
if request.method == 'POST':
.....some code.....
if ipform.is_valid() and formm.is_valid():
simpanForm = formm.save()
for form in ipform:
simpanIp = form.save(commit=False)
...... some code ..
simpanIp.connect_id = simpanForm
simpanIp.save()
and its work, now the result is my "connect_id" got value from "Connect id"
id is a Python builtin that gives a unique ID for an object. I would guess that you did not intend to pass it get_object_or_404 on this line:
get_object_or_404(Connect, pk=id)
The calling convention for this functions seems to be that it is meant to be an integer for the primary key in a database table. Figure out where you should be getting your primary key from and set it correctly.
Pro-tip: avoid using names that are predefined by Python (see here for a full list). It can lead to headaches like the one you just had.

How do I save m2m field session from a form to another?

I'm doing a multi step form where everything is saved at the end. In my models I have a m2m checkbox field and I'm using django Sessions to grab the forms datas to show it on the final step.
The issue is that the m2m field (checkboxes) is not saved when I submit the final form.
Here is my views file :
views.py
def step1(request):
initial={'name': request.session.get('name', None), 'checkbox': request.session.get('checkbox', (False,))} #cookies
form = FormOneForm(request.POST or None, initial=initial)
if request.method == 'POST':
if form.is_valid():
request.session['name'] = form.cleaned_data['name']
request.session['checkbox'] = form.cleaned_data.get('checkbox')
return HttpResponseRedirect(reverse('step2'))
return render(request, 'step1.html', {'form': form})
def step2(request):
form = FormTwoForm(request.POST or None)
if request.method == 'POST':
if form.is_valid():
formtwo = form.save(commit=False)
formone2 = FormOne.objects.create(checkbox=request.session.get('checkbox')) #error is here
formone = FormOne.objects.create(name=request.session['name'])
formtwo.owner = formone
formtwo.save()
formone2.save_m2m()
return HttpResponseRedirect(reverse('step3'))
return render(request, 'step2.html', {'form': form})
models.py
class Font(models.Model):
font_name = models.CharField(max_length=100)
font_family = models.CharField(max_length=100)
font_link = models.CharField(max_length=100)
...
class FormOne(models.Model):
name = models.CharField(max_length=40)
checkbox = models.ManyToManyField(Font, blank=True)
...
class FormTwo(models.Model):
owner = models.ForeignKey(FormOne)
name = models.CharField(max_length=40)
...
this code gives me this error :
'checkbox' is an invalid keyword argument for this function
How can I achieve what I am trying to realise ?
Try to save object first:
formone2 = FormOne.objects.create(name=request.session['name'])
formone2.checkbox.add(request.session.get('checkbox')
The problem is that you need to save object before use Many-to-many relations. See docs:
You can’t associate it with a Publication until it’s been saved

Categories

Resources