Django for loop save instance - python

I have a form that has two input fields which are returning the id values that will have to be parsed and added into the database.
This is the code
if form_stage_1.is_valid() and form_stage_2.is_valid():
# GET the new TP to pass to the next instance
form_stage_1.instance.created_by = self.request.user
new_tp = form_stage_1.save()
# Parse and add suppliers to the TP
for supplier_id in request.POST["supplier"]:
form_stage_2.instance.counterpart = Counterpart.objects.get(pk=supplier_id)
form_stage_2.instance.side = 1
form_stage_2.instance.save()
form_stage_2.instance.transaction_proposal.add(new_tp)
# Parse and add clients to the TP
for client_id in request.POST["client"]:
form_stage_2.instance.counterpart = Counterpart.objects.get(pk=client_id)
form_stage_2.instance.side = 2
form_stage_2.instance.save()
form_stage_2.instance.transaction_proposal.add(new_tp)
messages.success(request, "TP created successfully".format())
return redirect("add-tp")
Unfortunately is only adding one client.. why the form_stage_2.instance.save() is only working once?
What would be the most appropriate way to

First of all, do you have 2 forms to fill in ?
Anyway,
for supplier_id in request.POST["supplier"]:
form_stage_2.instance.counterpart = Counterpart.objects.get(pk=supplier_id)
form_stage_2.instance.side = 1
form_stage_2.instance.save()
form_stage_2.instance.transaction_proposal.add(new_tp)
This won't work. You can't save a form instance multiple times I believe.
if form_stage_1.is_valid() and form_stage_2.is_valid():
form_stage_1.instance.created_by = self.request.user
new_tp = form_stage_1.save()
# Parse and add suppliers to the TP
for supplier_id in request.POST["supplier"]:
data = {
'counterpart':Counterpart.objects.get(pk=supplier_id),
'side':1
'transaction_proposal':[new_tp]
}
stage2_instance = Stage2ModelClass.objects.create(**data)
# Parse and add clients to the TP
for client_id in request.POST["client"]:
data = {
'counterpart':Counterpart.objects.get(pk=client_id),
'side':2
'transaction_proposal':[new_tp]
}
stage2_instance = Stage2ModelClass.objects.create(**data)
messages.success(request, "TP created successfully".format())
return redirect("add-tp")
Solution can be somewhat like this.
You can use,
for client_id in request.POST["client"]:
data = {
'counterpart':Counterpart.objects.get(pk=client_id),
'side':2,
'transaction_proposal':[new_tp]
}
form = FormClassStage2(data)
if form.is_valid():
form.save()
But I don't think you need to initialize a form here.

Related

Django: Pass a variable/parameter to form from view? [duplicate]

I have a Model as follows:
class TankJournal(models.Model):
user = models.ForeignKey(User)
tank = models.ForeignKey(TankProfile)
ts = models.IntegerField(max_length=15)
title = models.CharField(max_length=50)
body = models.TextField()
I also have a model form for the above model as follows:
class JournalForm(ModelForm):
tank = forms.IntegerField(widget=forms.HiddenInput())
class Meta:
model = TankJournal
exclude = ('user','ts')
I want to know how to set the default value for that tank hidden field. Here is my function to show/save the form so far:
def addJournal(request, id=0):
if not request.user.is_authenticated():
return HttpResponseRedirect('/')
# checking if they own the tank
from django.contrib.auth.models import User
user = User.objects.get(pk=request.session['id'])
if request.method == 'POST':
form = JournalForm(request.POST)
if form.is_valid():
obj = form.save(commit=False)
# setting the user and ts
from time import time
obj.ts = int(time())
obj.user = user
obj.tank = TankProfile.objects.get(pk=form.cleaned_data['tank_id'])
# saving the test
obj.save()
else:
form = JournalForm()
try:
tank = TankProfile.objects.get(user=user, id=id)
except TankProfile.DoesNotExist:
return HttpResponseRedirect('/error/')
You can use Form.initial, which is explained here.
You have two options either populate the value when calling form constructor:
form = JournalForm(initial={'tank': 123})
or set the value in the form definition:
tank = forms.IntegerField(widget=forms.HiddenInput(), initial=123)
Other solution: Set initial after creating the form:
form.fields['tank'].initial = 123
If you are creating modelform from POST values initial can be assigned this way:
form = SomeModelForm(request.POST, initial={"option": "10"})
https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/#providing-initial-values
I had this other solution (I'm posting it in case someone else as me is using the following method from the model):
class onlyUserIsActiveField(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(onlyUserIsActiveField, self).__init__(*args, **kwargs)
self.fields['is_active'].initial = False
class Meta:
model = User
fields = ['is_active']
labels = {'is_active': 'Is Active'}
widgets = {
'is_active': forms.CheckboxInput( attrs={
'class': 'form-control bootstrap-switch',
'data-size': 'mini',
'data-on-color': 'success',
'data-on-text': 'Active',
'data-off-color': 'danger',
'data-off-text': 'Inactive',
'name': 'is_active',
})
}
The initial is definded on the __init__ function as self.fields['is_active'].initial = False
As explained in Django docs, initial is not default.
The initial value of a field is intended to be displayed in an HTML . But if the user delete this value, and finally send back a blank value for this field, the initial value is lost. So you do not obtain what is expected by a default behaviour.
The default behaviour is : the value that validation process will take if data argument do not contain any value for the field.
To implement that, a straightforward way is to combine initial and clean_<field>():
class JournalForm(ModelForm):
tank = forms.IntegerField(widget=forms.HiddenInput(), initial=123)
(...)
def clean_tank(self):
if not self['tank'].html_name in self.data:
return self.fields['tank'].initial
return self.cleaned_data['tank']
If you want to add initial value and post other value you have to add the following :
or None after request.POST
form = JournalForm(request.POST or None,initial={'tank': 123})
If you want to add files or images also
form = JournalForm(request.POST or None,request.FILES or None,initial={'tank': 123})
I hope this can help you:
form.instance.updatedby = form.cleaned_data['updatedby'] = request.user.id
I also encountered the need to set default values in the form during development. My solution is
initial={"":""}
form=ArticleModel(request.POST)
if form.has_changed():
data = {i: form.cleaned_data[i] for i in form.changed_data}
data.update({key: val for key, val in init_praram.items() if key not in form.changed_data})
use form.has_changed ,if form.fields is required you can use this method
How I added the initial to the form:
I read #Sergey Golovchenko answer.
So I just added it to the form in if request.method == 'POST':.
But that's not where you place it, if you want to see what value it got before posting the form.
You need to put it in the form where the else is.
Example here from views.py
def myForm(request):
kontext = {}
if request.method == 'POST':
# You might want to use clean_data instead of initial here. I found something on a stack overflow question, and you add clean data to the Forms.py, if you want to change the post data. https://stackoverflow.com/questions/36711229/django-forms-clean-data
form = myModelForm(request.POST, initial={'user': request.user})
if form.is_valid():
form.save()
return redirect('/')
else:
# you need to put initial here, if you want to see the value before you post it
form = myModelForm(initial={'user': request.user})
kontext['form'] = form
return render(request, 'app1/my_form.html', kontext)

Django - Get previous form filled data when I come back to form [duplicate]

i'm new to django so i'm sorry for my newbie question
i have a model and i need to let user edit data inside it using django forms or any other way.
look at the image above , i want to show this form ready populated with the data and let user update it.
what is the best way to do this ?
EDIT : here is my views.py code
def exam_Edit(request,examName,number=0):
numner = int(number)
number = int(number)
questionNo = int(numner)
Myexam = models.Exam.objects.get(name = examName)
QuestionsAll = models.Question.objects.filter(exam = Myexam)
myQeustion = Question.objects.filter(exam = Myexam)[nextQuestion]
answer1 = models.Asnwers.objects.filter(question=myQeustion)[0]
answer2 = models.Asnwers.objects.filter(question=myQeustion)[1]
answer3 = models.Asnwers.objects.filter(question=myQeustion)[2]
answer4 = models.Asnwers.objects.filter(question=myQeustion)[3]
# HERE IS MY PROBLEM : the line below creates a form with a data but it doesn't save it to the save object
form = QuestionsEditForm(initial = {'questionText':myQeustion.__unicode__() , 'firstChoiceText':answer1.__unicode__(),'secondChoiceText':answer2.__unicode__(),'thirdChoiceText':answer3.__unicode__(),'forthChoiceText':answer4.__unicode__()})
if request.method =='POST':
#if post
if form.is_valid():
questionText = form.cleaned_data['questionText']
Myexam = Exam.objects.get(name = examName)
myQeustion.questionText = form.cleaned_data['questionText']
answer1.answerText = form.cleaned_data['firstChoiceText']
answer1.save()
answer2.answerText = form.cleaned_data['secondChoiceText']
answer2.save()
answer3.answerText = form.cleaned_data['thirdChoiceText']
answer3.save()
answer4.answerText = form.cleaned_data['forthChoiceText']
answer4.save()
variables = RequestContext(request, {'form':form,'examName':examName,'questionNo':str(nextQuestion)})
return render_to_response('exam_edit.html',variables)
please help
Assuming you are using a ModelForm, use the instance keyword argument, and pass the model you are updating.
So, if you have MyModel and MyModelForm (the latter of which must extend django.forms.ModelForm), then your code snippet might look like:
my_record = MyModel.objects.get(id=XXX)
form = MyModelForm(instance=my_record)
And then, when the user sends back data by POST:
form = MyModelForm(request.POST, instance=my_record)
Incidentally, the documentation for ModelForm is here: http://docs.djangoproject.com/en/1.8/topics/forms/modelforms/

Calculating the difference between two fields within a table in Django

I have a model which stores the opening and closing balances of a petrol station. I have an additional third column which is basically the difference between the opening and reading values.
class DailySales(models.Model):
PUMP_NAMES = (
...
)
Pump_name = models.CharField(max_length = 5, choices = PUMP_NAMES)
Opening_reading = models.IntegerField()
Closing_reading = models.IntegerField()
Gross_sales = models.IntegerField(null = True)
Date = models.DateField(auto_now_add= True)
def Calc_gross(self):
self.Gross_sales = self.Opening_reading - self.Closing_reading
super(DailySales,self).save()
the Calc_gross method works when i'm saving only one instance at a time.
But i want to add multiple opening and closing values to the model at once for which i'm using formsets.
SalesForm = modelformset_factory(DailySales, extra = 7, exclude=('Date','Gross_sales'))
This is where the logic falters. Django isnt able to calculate the gross values for each row.
Exception Value:
'list' object has no attribute 'Calc_gross'
I was thinking since its a list , I could iterate over each and invoke the Calc_gross method. What will be the name of the list?
Is there a better way to do this? Would it be logical to use Prefixes (how would u assign a prefix to each form?)
Turns out i could just loop over the formset.
if request.method == 'POST':
sale_Form = SalesForm(data = request.POST)
for Form in sale_Form:
if Form.is_valid():
gross = Form.save()
gross.Calc_gross()
gross.save()
else:
print(sale_Form.errors)

django get_or_create method always results in a new record

Model
class projects(models.Model):
"""Table that holds the details of the projects."""
toiName = models.CharField(max_length=100)
toiOwner = models.CharField(max_length=50)
receiver = models.CharField(max_length=50)
manager = models.CharField(max_length=50)
toiOwnerEmail = models.EmailField(max_length=70)
receiverEmail = models.EmailField(max_length=70)
managerEmail = models.EmailField(max_length=70)
dateUpdated= models.DateTimeField(default=datetime.today())
dateCreated = models.DateTimeField(default=datetime.today())
class Meta:
db_table="projects"
View, the original code to save the model works fine, when I go ahead and edit the form in the view, I always end up with a new record.
data = model_to_dict(projects.objects.filter(toiName=pid, managerEmail=request.user)[0])
if request.method == 'POST':
form = projectsForm(request.POST)
if form.is_valid():
#form = projectsForm(request.POST, instance=projects.objects.get(toiName=pid))
#obj = projects\
obj, created = projects.objects.get_or_create\
(toiName=request.POST['toiName'],
toiOwnerEmail=request.POST['toiOwnerEmail'],
toiOwner=request.POST['toiOwner'],
manager=request.POST['manager'],
receiver=request.POST['receiver'],
receiverEmail=request.POST['receiverEmail'],
dateUpdated=datetime.now(),
dateCreated=data['dateCreated'],
managerEmail=request.user,)
Here created always results in True.
At least this dateUpdated=datetime.now() causes get_or_create to always create new record, because each time datetime.now() is different.
I believe I was using the get_or_create incorrectly, since I was only trying to update the entry.
I fixed the code in the view with:
data = model_to_dict(projects.objects.filter(toiName=pid, managerEmail=request.user)[0])
proj = projects.objects.get(toiName=pid, managerEmail=request.user)
if request.method == 'POST':
form = projectsForm(request.POST)
if form.is_valid():
proj.toiName=form.cleaned_data['toiName']
proj.toiOwnerEmail=form.cleaned_data['toiOwnerEmail']
proj.toiOwner=form.cleaned_data['toiOwner']
proj.manager=form.cleaned_data['manager']
proj.receiver=form.cleaned_data['receiver']
proj.receiverEmail=form.cleaned_data['receiverEmail']
proj.dateUpdated=datetime.now()
#proj.dateCreated=data['dateCreated']
proj.save()
additional to #user1865366 answer, projects.objects.get should be enclose it with try ... except ... like so
try:
proj = Projects.objects.get(toiName=pid,manageEmail=request.user)
except Projects.DoesNotExist :
# do something create new proj and do something with the form
...
otherwise there will be big error screen when django cannot get the object

how to edit model data using django forms

i'm new to django so i'm sorry for my newbie question
i have a model and i need to let user edit data inside it using django forms or any other way.
look at the image above , i want to show this form ready populated with the data and let user update it.
what is the best way to do this ?
EDIT : here is my views.py code
def exam_Edit(request,examName,number=0):
numner = int(number)
number = int(number)
questionNo = int(numner)
Myexam = models.Exam.objects.get(name = examName)
QuestionsAll = models.Question.objects.filter(exam = Myexam)
myQeustion = Question.objects.filter(exam = Myexam)[nextQuestion]
answer1 = models.Asnwers.objects.filter(question=myQeustion)[0]
answer2 = models.Asnwers.objects.filter(question=myQeustion)[1]
answer3 = models.Asnwers.objects.filter(question=myQeustion)[2]
answer4 = models.Asnwers.objects.filter(question=myQeustion)[3]
# HERE IS MY PROBLEM : the line below creates a form with a data but it doesn't save it to the save object
form = QuestionsEditForm(initial = {'questionText':myQeustion.__unicode__() , 'firstChoiceText':answer1.__unicode__(),'secondChoiceText':answer2.__unicode__(),'thirdChoiceText':answer3.__unicode__(),'forthChoiceText':answer4.__unicode__()})
if request.method =='POST':
#if post
if form.is_valid():
questionText = form.cleaned_data['questionText']
Myexam = Exam.objects.get(name = examName)
myQeustion.questionText = form.cleaned_data['questionText']
answer1.answerText = form.cleaned_data['firstChoiceText']
answer1.save()
answer2.answerText = form.cleaned_data['secondChoiceText']
answer2.save()
answer3.answerText = form.cleaned_data['thirdChoiceText']
answer3.save()
answer4.answerText = form.cleaned_data['forthChoiceText']
answer4.save()
variables = RequestContext(request, {'form':form,'examName':examName,'questionNo':str(nextQuestion)})
return render_to_response('exam_edit.html',variables)
please help
Assuming you are using a ModelForm, use the instance keyword argument, and pass the model you are updating.
So, if you have MyModel and MyModelForm (the latter of which must extend django.forms.ModelForm), then your code snippet might look like:
my_record = MyModel.objects.get(id=XXX)
form = MyModelForm(instance=my_record)
And then, when the user sends back data by POST:
form = MyModelForm(request.POST, instance=my_record)
Incidentally, the documentation for ModelForm is here: http://docs.djangoproject.com/en/1.8/topics/forms/modelforms/

Categories

Resources