I'm building a test aplication to insert data into database and I keep on getting error "local variable 'form' referenced before assignment". I read a few articles and I do not understand how should I approach the problem in case the method is not POST.
All I'm trying to acchieve with this test application is to go to specified page, insert some numbers in the fields and then submit them. After that I want to check DB if they got submitted correctly.
views.py
def cost(request):
if request.method == 'POST':
form = CostForm(request.POST)
if form.is_valid():
amount = request.POST.get('amount', '')
cost = request.POST.get('cost', '')
cost_obj = Cost(amount = amount, cost = cost)
cost_obj.save()
return HttpResponseRedirect('/vnos/')
else:
form = CostForm()
return render(request, "cost.html", {'form': form})
models.py
class Cost(models.Model):
cost = models.FloatField()
amount = models.FloatField()
forms.py
class CostForm(forms.Form):
date = forms.DateField()
amount = forms.FloatField()
class Meta:
model = Cost
fields = ['cost', 'amount']
Your else statement is indented too far. Move it back one level.
Two other points: you should be getting the data from the form after validation, not direct from the POST:
amount = form.cleaned_data['amount']
cost = form.cleaned_data['cost']
And secondly, you could make it even simpler by using a ModelForm.
Related
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.
I'm in process of creating a page where you can add a customer with some information regarding to them. I want to assign an unique id for each customer. I of course type in the basic information myself, but I also need a field in the form that has been populated with a generated random id, that has been checked in the database if it already exists. If it doesn't then fill it into the form, and if it does then generate a new one until a not used one is found.
Models.py
class Opretkunde(models.Model):
Fornavn = models.CharField(max_length=30)
Efternavn = models.CharField(max_length=50)
Telefon = models.IntegerField()
Adresse = models.CharField(max_length=50)
Postnummer = models.IntegerField()
IA = models.CharField(max_length=10)
salgsperson = models.CharField(max_length=150, default="missing")
The field IA is the field which should be automatically populated with the randomly generated value
forms.py
class Opret_kunde_form(ModelForm):
class Meta:
model = Opretkunde
fields = ['Fornavn', 'Efternavn', 'Telefon', 'Adresse', 'Postnummer', 'IA']
views.py
def index(request):
if request.method == 'POST':
form = Opret_kunde_form(request.POST, request.FILES)
if form.is_valid():
instance = form.save(commit=False)
instance.salgsperson = request.user
instance.save()
return HttpResponseRedirect(reverse('createUser:createUser'))
else:
form = Opret_kunde_form()
return render(request, 'createCustomer.html', {'form': form})
The function im using to generate a value looks like this
def random_with_N_digits(n):
range_start = 10**(n-1)
range_end = (10**n)-1
return randint(range_start, range_end)
I'm thinking of something that could look like this
Uniquevalue = random_with_N_digits(8)
If Uniquevalue Opretkunde.objects.filter(IA=Uniquevalue).exists()
generate new uniquevalue
check again and if it doesnt exist then insert to form
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!
I'm still learning Django. I have a wizard like form workflow where each form is filling out information in succession.
I have a model form that represents what I want inputted from the form:
Models.py
class AccountParameters(models.Model):
acctFilterName = models.ForeignKey(AccountFilters)
excludeClassification = models.ManyToManyField(ClassificationNames)
tradingCash = models.FloatField()
Forms.py
This is a dumbed down form and doesn't represent the real implementation. It was for testing.
class AccountSelectionForm(forms.ModelForm):
acctFilterName = forms.ModelChoiceField(queryset=AccountFilters.objects.all().values_list('acctFilterName', flat=True),
label="Account Filters:",
empty_label="Select Here..."
)
excludeClassification = forms.ModelMultipleChoiceField(queryset=ClassificationNames.objects.all().values_list('classificationName', flat=True),
label="Classifications Exclusion:"
)
tradingCash = forms.IntegerField(label="Remove accounts whose trading cash < % of AUM")
class Meta:
model = AccountParameters
fields =['excludeClassification', 'tradingCash',]
exclude = ['acctFilterName']
labels = {
'acctFilterName': _('Account Filters:')
}
views.py
def accountSelections(request): # NewRebalnce 2: AccountParameters with Accounts and Trading Form
if request.method == "POST":
form = AccountSelectionForm(request.POST)
if form.is_valid():
accountParameters = AccountParameters
#tradingCash = form.cleaned_data['tradingCash']
return render(request, 'NewRebalance_3.html', {'model_selection_form': ModelSelectionForm()})
else:
form = AccountSelectionForm()
return render(request, 'NewRebalance2.html', {'account_selections_form': form})
I'm not sure that I'm using Modelforms correctly. What I needed was a way to create a select drop down for my acctFilterName so I created the query set manually.
When I save the form it's not valid and in the form cleaned data I get the following:
Notice that the cleaned data only has the tradingCash field.
What am I doing wrong? Is there a better way to do this? Why is the Form in valid?
try to remove .values_list('acctFilterName', flat=True) from the ModelChoiceField and remove .values_list('classificationName', flat=True) from the ModelMultipleChoiceField.
They should be like this:
acctFilterName = forms.ModelChoiceField(
queryset=AccountFilters.objects.all(),
label="Account Filters:",
empty_label="Select Here...")
excludeClassification = forms.ModelMultipleChoiceField(
queryset=ClassificationNames.objects.all(),
label="Classifications Exclusion:")
.values_list will strip your queryset of all the data the ModelChoiceField needs to recognize the item, leaving only the model fields you specify as an argument. Namely, what you're removing here is the primary key of the model which is fundamental.
Why are you redeclaring the fields on your AccountSelectionForm ModelForm???
Better this way:
class AccountSelectionForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.fields['excludeClassification'].queryset = ClassificationNames.objects.all().values_list('classificationName', flat=True)
self.fields['acctFilterName'].queryset = AccountFilters.objects.all().values_list('acctFilterName', flat=True)
class Meta:
model = AccountParameters
fields =['excludeClassification', 'tradingCash',]
exclude = ['acctFilterName']
labels = {
'acctFilterName': _('Account Filters:')
}
I am trying to achieve a rather simple thing, but got stuck with an error and have no idea where does it come from.
I want to create and save an object in my views. The code is very simple:
models.py:
class Iteration(models.Model):
user = models.ForeignKey(User)
one_two = '1-2 weeks'
two_four = '2-4 weeks'
four_six = '4-6 weeks'
six_eight = '6-8 weeks'
DURATION_CHOICES = (
(one_two, '1-2 weeks'),
(two_four, '2-4 weeks'),
(four_six, '4-6 weeks'),
(six_eight, '6-8 weeks'),
)
duration = models.CharField(max_length=100, choices=DURATION_CHOICES, default=two_four)
project = models.ForeignKey(Project)
def is_upperclass(self):
return self.duration in (self.one_two, self.six_eight)
views.py:
def New_iteration(request, slug):
form = IterationForm()
user = request.user
project = Project.objects.get(user=user, slug=slug)
if request.method == 'POST':
form = IterationForm(request.POST)
errors = form.errors
if form.is_valid:
user = request.user
duration = request.POST['duration']
project = Project.objects.get(user=user, slug=slug)
new_iteration = Iteration(user.id, form.cleaned_data['duration'], project.id)
new_iteration.save()
return HttpResponseRedirect("/dashboard/")
else:
return HttpResponse("not valid")
return render(request, "new_iteration.html", {"form" : form, "project" : project, "user" : user})
I am receiving an error invalid literal for int() with base 10: '2-4 weeks'. I think it comes from
new_iteration = Iteration(user.id, form.cleaned_data['duration'], project.id)
line, but I'm not sure what to do.
You shouldn't create the object as
new_iteration = Iteration(user.id, form.cleaned_data['duration'], project.id)
you need to pass data as keyword parameters as
new_iteration = Iteration(user = user, duration = form.cleaned_data['duration'],
project = project)
However, I believe IterationForm is model form and you want to get project before saving the iteration, more better way is
if form.is_valid(): #note this is function call
user = request.user
project = Project.objects.get(user=user, slug=slug)
new_iteration = form.save(commit=False)
new_iteration.project = project
new_iteration.save()
I have solved the task. I should have added my forms.py for better understanding. I have edited my forms.py file and defined there, that the only "selectable" field should be "duration", and Django should get other stuff (user and project) when initiating the form in views.
The other mistake was that I did not pass data as keyword parameters, thanks Rohan.
So I have added fields = ('duration',) to my ModelForm and re-initiaded the form with keyword arguments now.