Django: how to loop through boolean fields and set all to false - python

So, I have a table called "order" that has a foreign key with the table "store". The order table has a boolean field set by default to false. When a new order is created, I need to loop through the boolean values associated with each individual store and set the other orders to false and the new order to true. Not sure how to create the for loop for that. First I tried to set it into the view, but maybe it can be put into the forms.py file? This my create code so far.
def create(request):
if request.POST:
form = OrderForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/liquors/all')
else:
form = OrderForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('create_order.html', args)
Models provided upon request, you shouldn't need anything except the order model:
class Order(models.Model):
OrderID = models.AutoField(primary_key=True)
storeID = models.ForeignKey(Store)
DateCreated = models.DateField('Date Created', auto_now_add=True)
OrderName = models.CharField('Order Name', max_length=25 )
Active = models.BooleanField()

you must return render_to_response('create_order.html', args) one indentation back. so that validation form will not affected. you don't need to use csrf request if you are using render. I think there is no need to use OrderId in Order model, since it is automattically created. ie id
from django.shortcuts import render
from <appname>.models import Order,Store
def create(request):
if request.POST:
form = OrderForm(request.POST)
if form.is_valid():
#i just assume the storeid variable is exist in request.POST and it is ID.
store_data=Store.objects.get(id=request.POST['storeid'])
#here you might need to update the other orderform to false
Order.objects.filter(storeID=store_data).update(Active=False)
fo=Order(storeID=store_data,Active=True)
frm_order=OrderForm(request.POST,instance=fo)
frm_order.save()
return HttpResponseRedirect('/liquors/all')
else:
form = OrderForm()
return render(request,'create_order.html', {'form':form})

You can use the order object's meta object to loop through the fields. Ex.
for field in order._meta.fields():
if type(field) = django.db.models.fields.BooleanField:
setattr(order, field.name, True)

Related

Django ForeignKey is returning ID number instead of actual string value, particularly for form-based request.POST

I have a website contact form that generates a dropdown box of "names" that are defined in another model "Data". The contact form runs off the model "Quote". As such, I use a ForeignKey reference to populate the "Data" information within the "Quote"-driven form.
However, the next step is to move this data to more python code (i.e., for calculations and placement in an email). But, when I request.POST "name" in the quote views file, I receive an ID (i.e., 1) instead of the actual string value for "name." I have read this is how ForeignKey inherently transfers data.
Like how I returned the actual string version of "name" in the quote dropdown box, how do I get the actual string version of "name" in a data request.POST / data_dictionary assignment? I have seen similar questions, but I am not completely sure of the simplest answer.
models.py (Original one)
class Data(models.Model):
name = models.CharField(max_length=100, null=True)
def __str__(self):
return self.name
models.py (The one tied to the form)
class Quote(models.Model):
name = models.ForeignKey(Data, on_delete=models.CASCADE)
def __str__(self):
return str(self.name)
views.py
def quote_req(request):
submitted = False
if request.method == 'POST':
form = QuoteForm(request.POST, request.FILES)
name = request.POST['name']
if form.is_valid():
data_dict = {
'name_': str(name),
inputdictionary = data_dict
forms.py
class QuoteForm(ModelForm):
helper = FormHelper()
helper.form_show_labels = False
required_css_class = 'required'
class Meta:
model = Quote
fields = ['name',]
Variable Assignment
▼ Local vars
Variable Value
name '1'
Respective Error (I need the actual string value of "name")
IndexError at /quote/
list index out of range
The solution was in tandem with what #dirkgroten mentioned in the comments. I have to add the form.cleaned_data method after the if form.is_valid statement. No other files need to be modified.
views.py
def quote_req(request):
submitted = False
if request.method == 'POST':
form = QuoteForm(request.POST, request.FILES)
name = request.POST['name']
if form.is_valid():
name = form.cleaned_data['name']
data_dict = {
'name_': str(name),
inputdictionary = data_dict

django - form.cleaned_data[] for all fields in model

I am using django to digitalise a form. This form is a little bit complex, and there are a lot of fields in it. I was wondering if Django could do form.cleaned_data[] for all fields, in stead of declaring variables like obj.fieldname = form.cleaned_data['fieldname'] for each field apart.
I tried it with a forloop in the views.py, but that won't work
This is the forloop I'm talking about:
def get_form_naw(request):
if request.method == 'POST':
form = Form1(request.POST)
if form.is_valid():
for x in Model1():
formname = x.name
o = Model1()
o.formname = form.cleaned_data[formname]
o.save()
else:
form = Form1
return render(request, 'folder/home.html', context=locals())
I'm using a mysql database. My forms are declared like this:
forms.py
class Form1(forms.ModelForm):
class Meta:
model = Model1
exclude = ('id')
You shouldn't have to loop through the fields. You are using a model form, so you should just save the form:
if form.is_valid():
obj = form.save()
...
If you really need to set fields dynamically, you can use setattr.
fieldname = 'username'
value = 'my_user'
setattr(obj, fieldname, value)
you can get the instance of the data before saving like this:
if form.is_valid():
obj = form.save(commit=False) #get instance without saving
# do your thing
obj.save() #save into database

submitting 2 forms together, passing primary key from one as foreign key in other

I have created a form using python and django from 2 seperate modelForms in the one html template. Models:
class Action(models.Model):
name = models.CharField("Action name", max_length=50)
keywords = models.CharField("Keywords", max_length=50)
object = models.CharField("Object", max_length=50, blank=True, null=True)
uploadDate = models.DateField("Date", default=get_current_date)
UploadedBy = models.CharField("UploadedBy", max_length=50, default="")
class Image(models.Model):
image = models.FileField(upload_to=get_upload_file_name, default="")
action = models.ForeignKey(Action)
def get_upload_file_name(instance, filename):
return "uploaded_files/%s_%s" % (str(datetime.now().day).replace('.','_'), filename)
forms:
class ActionForm(ModelForm):
#bind form to Action model
class Meta:
model = Action
fields = ['name','keywords', 'object', 'UploadedBy', 'uploadDate']
class ImageForm(ModelForm):
class Meta:
model= Image
fields =['image']
The code which creates the form in views:
def actioncreate(request):
if request.method == "GET":
#create the object - Actionform
form = ActionForm;
form2 = ImageForm;
#pass into it
return render(request,'app/createForm.html', { 'form':form, 'form2':form2})
elif request.method == "POST":
# take all of the user data entered to create a new action instance in the table
form = ActionForm(request.POST, request.FILES)
form2 = ImageForm(request.POST, request.FILES)
if form.is_valid() and form2.is_valid():
act = form.save(commit=False)
img = form2.save(commit=False)
#set the action_id Foreignkey
act.id = img.action_id
act.save()
img.save()
return HttpResponseRedirect('/actions')
else:
form = ActionForm()
form2 = ImageForm;
return render(request,'app/createForm.html', { 'form':form, 'form2':form2 })
The form is created fine but when it is submitted, it trys to save image.id, image.image (filename) and returns null for image.action_id
I am getting the error:
null value in column "action_id" violates not-null constraint
DETAIL: Failing row contains (2, uploaded_files/29_personrunning_Hq8IAQi.jpg, null).
I obviously need to populate the third column with the action.id which django creates itself on submitting the first part 'form'. Is there a way I can get the action.id value and populate the action_id field in the image table in the one form submission?
image.action_id is declared initially as a foreignKey related to action in models.
The first problem is related to act = form.save(commit=False) because it will return an object that hasn’t yet been saved to the database, then act doesn't have an ID. You need to save (and commit) act first.
Also there is another error in following line:
act.id = img.action_id # It should be: img.action_id = act.id
You may want to assign act to img.action. Please note that you are doing it in the wrong way (you are assigning in img.action to act). The best way to do it is:
img.action = act # This is equivalent to img.action_id = act.id
Try swapping these lines:
act.save()
img.action = act

Passing A primary key to the next page in with Django

So I have the following files:
Views.py:
def home(request):
return render(request, 'home/index.html')
def add(request):
if request.method == 'POST': # If the form has been submitted...
# ContactForm was defined in the previous section
form1 = AddEventForm(request.POST) # A form bound to the POST data
#person = AddPersonForm(request.POST) # A form bound to the POST data
if form1.is_valid(): # All validation rules pass
form = form1.save()
request.session['event_data'] = request.POST
#request.session['event_data2'] = form
return HttpResponseRedirect('/add_person/')
#return HttpResponseRedirect(reverse('/add_person', kwargs={'PK':form.pk}))
else:
form1 = AddEventForm() # An unbound form
person = AddPersonForm() # A form bound to the POST data
return render(request, 'add/add.html', {
'form1': form1, 'person': person,
})
def add_person(request):
event_data = request.session.get('event_data')
if request.method == 'POST':
person = AddPersonForm(request.POST)
else:
person = AddPersonForm()
return render(request, 'add_person/add_person.html',{'event_data': event_data, 'person': person,})
models.py:
class event(models.Model):
event_name = models.CharField(max_length=200)
date = models.DateField('Date',default=date.today)
event_id = models.AutoField(primary_key=True)
admin_username = models.CharField(max_length=50)
def __unicode__(self):
return ('%s %s %d') % (self.date, self.event_name, self.event_id)
class Person(models.Model):
eventID = models.ForeignKey(event)
first_name = models.CharField(max_length=50)
second_name = models.CharField(max_length=50)
email = models.EmailField(max_length=50)
phone = models.CharField(max_length=25)
company = models.CharField(max_length=200)
favourite = models.BooleanField(default=False)
def __unicode__(self):
return eventID
This problem has been bugging me for hours. I have an initial page where the user enters some information about an event. If the checks pass the form saves and a primary key is generated. The user is then redirected to another page where they fill out a form about the people they have met there. The problem is I cannot find a way of passing the primary key to the second page (add_people). I need the primary key because it is my foreign key in my Person table and I need to use to pre-populate the eventID in the add_people page.
I initially thought the primary key would be in the request.POST after the form is saved but its not.
Query the table for the primary key using the form inputs as arguments. Once you get the key, pass it as a session variable in the request object.
Here's an answer to the same question but with class-based views instead of function-based views: How do I pass a parent id as an fk to child object's ModelForm using generic class-based views in Django?. In that example, the foreign key is passed from the parent page to the child page by being a parameter in the URL. The child page catches it as a form parameter (in the form's __init__ function), stores it in a hidden field for display (by the View class's get_context_data and html code in the form template), and then submits it as part of the form.
If your form is validated, then your have to set session value as eventID but not request.POST
if form1.is_valid(): # All validation rules pass
form1.save(commit=False)
request.session['event_data'] = form1.cleaned_data['eventID']
form1.save()
return HttpResponseRedirect('/add_person/')

Django set default form values

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)

Categories