Additional field in django form - python

I am creating a form in Django. When I POST the data, the data is naturally sent. My problem is, I want to pass an additional property to the POST data, that is not any of the form fields, but an additional one.
So that I can later do something like (pseudocode):
def form_view(request):
if request.method == 'POST':
form = MyForm(request.POST)
if form.is_valid():
extra_field = form.cleaned_data['extra_field']
#or maybe
extra_field = form.extra_field
#...
else:
form = MyForm()
#...
Anything that might work in order to pass an extra property, which is not a field but a simple variable, to the POST request.

If you want to pass anything to django as a POST request from the HTML, you would use a hidden input
<input type="hidden" name="foo" value="bar" />
print request.POST['foo'] # out: bar
If you want to modify the POST dictionary in python from your view, copy() it to make it mutable.
mutable_post = request.POST.copy()
mutable_post['foo'] = 'bar'
form = MyForm(mutable_post)

There are a few ways to do this. One, is you can just add it to your template.
<form action="." method="post">{% csrf_token %}
{{ form.as_p }}
<input type="hidden" name="extra_field" value="{{ extra }}" />
<input type="submit" value="submit" />
</form>
Another way is to add the field to your form class, but use a hidden widget. I'm not sure if this is what you want. If it is, just add a comment and I can explain this point further.

In your form's clean method, you can add new information to the cleaned_data, something like: form.cleaned_data['extra'] = 'monkey butter!', then if the form.is_valid(), you have your extra info.
What you do finally will depend on what your extra information is, and where it is available to you.

Related

Django passing parameter to CreateView and filling the form with it

I want to make a CreateView with the form already completed with an argument that will be passed to it from another view.
There is the initial view with an input field. Like this:
<form role="form" action="" method="post">
{% csrf_token %}
<div class="col-sm-6">
<div class="form-group">
<div class="form-line">
<label>{{form.cpf.label}}</label><strong style="color:red;"> *</strong>
{% if form.cpf.errors %}<label class="error">{% for error in form.cpf.errors %}{{error}}{% endfor %}</label>{% endif %}
{{form.cpf}}
</div>
</div>
</div>
<button class="btn btn-success foot-btn" type="submit"><i style="vertical-align:middle" class="material-icons">add</i><span style="vertical-align:middle">Verificar</span></button>
</form>
When the user submits this form he will be redirected to another page. Asking if he wants to insert that value in the DB.
Right now I'm trying to redirect like this, trying to pass the POST value as a parameter to the CreateView
return redirect(reverse('blacklist:addcpfview', args=(request.POST['cpf'],)))
But I can't seem to get this parameter in the CreateView.
I know this I'm probably very wrong in the way I'm currently doing, but I'm a beginner with Django and want to know the best way to do this.
UPDATE
The CreateView
class AdicionarCPFView(CreateView):
form_class = CPFForm
template_name = 'blacklist/cpf/addCPF.html'
success_url = reverse_lazy('blacklist:cpfselectview')
def get_context_data(self, **kwargs):
context = super(CreateView, self).get_context_data(**kwargs)
context['title_complete'] = 'Adicionar CPF'
return context
As you use CreateView - it has a special method to fill initial values - get_initial
What you need is to override this method and read variable from kwargs there.
def get_initial(self):
initial = super().get_initial()
# cpf - it's the name of the field on your current form
# self.args will be filled from URL. I'd suggest to use named parameters
# so you can access e.g. self.kwargs['cpf_initial']
initial['cpf'] = self.args[0]
return initial
Another way to achieve this is to use session.
So when before you redirect you do request.session['initial_cpf'] = request.POST['cpf]
And in create view you access not self.args but self.request.session
And a side note - in first view it's a good practice not to read variable from POST, but use a form instead.

How to manually make field in HTML? Django

in forms.py
class PlaceOrder(forms.ModelForm):
class Meta:
model = Order
fields = ["Product_ID","HowMany","DateSubmit",]
to call a form i usually use
{{ Form }}
that will render the form automatically
but is it possible to make it manually?
for example i want the form to be exactly like this
<input id="Product_ID" type="hidden" value="{{ Product.PId }}" >
<input id="HowMany" type="text">
<input id="DateSubmit" type="hidden" value="{{ date }}" >
i have tried wrapping them in
{% for field in form %}
but it gave the wrong output
Sorry if this is confusing
but i don't really know how to explain it,
i am still new to Django
You should be able to access individual fields in the form using something like
{{Form.Product_ID}}
which will give you the Product_ID field widget.
Now if you want to access the already pre-filled data you should be able to do so with
{{Form.Product_ID.label}}
or
{{Form.Product_ID.value}}
Also check:
https://docs.djangoproject.com/en/dev/topics/forms/#looping-over-the-form-s-fields

Django Form request not saving data to db

I am using a django form in atemplate to save data entered to database.
In my view after the request is made, the response is redirected correctly but the data is not saved to db.
I might be missing something. but am unable to find it even after a lot of debugging.
here is what has been done so far:
views.py:
from .models import testmodel
def testview(request):
if request.method== 'POST':
form=MapForm(request.POST)
if form.is_valid():
test1=request.POST.get('t1')
print meaningid1
test2=request.POST.get('t2')
print meaningid2
pobj=testmodel(test1=test1,test2=test2)
pobj.save()
return HttpResponse('Successful')
after this the response message "Successful" is seen
from template:
<form action="/testview/" method="post"> {% csrf_token %}
{{form.as_p}}
<input type="text" name="t1" value='' id='t1'/> <br><br><br>
<input type="text" name="t2" value='' id='t2'/><br>
<input type="submit" value="Submit" />
</form>
from forms.py:
from .models import testmodel
class MapForm(forms.ModelForm):
class Meta:
model = testmodel
fields = ['test1','test2']
after the data is entered in form it is going to page /testview and showing message on page. but from backend data is not been saved to db.
Can some one suggest what could be done
Thanks
In python, indentation matters.
def testview(request):
if request.method== 'POST':
form=MapForm(request.POST)
if form.is_valid():
test1=request.POST.get('t1')
print meaningid1
test2=request.POST.get('t2')
print meaningid2
pobj=testmodel(test1=test1,test2=test2)
pobj.save()
return HttpResponse('Successful')
In the above code 'Successful' will be displayed regardless of whether the form is actually successful or not. You need to push your return statement four spaces to the right, and you also need to add an else clause which handles the situation where the form is not valid. Typically that is just to display the form again (with form errors which wil be displayed for you automatically is you use form.as_p or form.as_table)

Pyramid: using form data for route matching and POST simultaneously

I'm using Pyramid to build a webapp, and I've got two views where one leads to the other:
config.add_route("new", "/workflow/new")
config.add_route("next", "/workflow/{id}/next")
The new view is really very simple and presents only an HTML form as a Jinja2 template for the user to fill in some information:
<form method="post" action="{{ request.route_url('next',id='') }}" >
<input type="text" name="id" value="Identifier" />
...
<input type="submit" name="next" value="Next" />
</form>
The question here regards the action of that form: how can I use the content of the text input field id, perhaps process it a little, and then pass it on in the route request?
Note that in this scenario the form data is passed from the new view to the next view, and that should stay the same.
When the form is posted, the forms fields will be available in the request object, see
http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/webob.html#request
I believe it is also a good idea to post to the same url (<form action="#" method="post">), so that you can validate the form. Then you can process and redirect to the next url when the form is valid, or recreate the form with errors if it isn't.
So your view may end up something like this;
from pyramid.httpexceptions import HTTPFound
from pyramid.url import route_url
def myview(request):
if request.method == 'POST':
# Validate the form data
if <form validates successfully>:
# Do any processing and saving here.
return HTTPFound(location = route_url('next', id=request.params['id'], request=self.request))
else:
request.session.flash("The form isn't valid.")
# Do some stuff here to re-populate your form with the request.params
return { # globals for rendering your form }
There are already many questions/answers addressing this, such as How can I redirect after POST in Pyramid?

Web server ini-file editor using django

I wish to edit ini files over web server, decided to use django, been using it for few days now. I can't figure out how to accomplish this. I have ini file structure looking like this:
{'GROUP', {PROPERTY : VALUE}}
Example when I read this kind of ini file:
[LOG]
FilePath = C:/Log
[CMD]
Level = 5
I will get my data structure filled like this:
{'LOG', {'FilePath' : 'C:/Log',},
{'CMD', {'Level', '5'}}}
Loop looks like this:
for group in settingsDict:
print group # group
for property in settingsDict[group]:
print property , # property
print settingsDict[group][property] # value
I am using ini file parser.
I am having trouble understanding how to correctly develop in django: views.py is some kind of controller for django and templates are views and model would be my ini file (probably linked with db using django model), or am I getting something wrong?
I have no problem passing this dictionary to template, making a for loop in it and creating html tags like: <input type="text" name={{ property }} value={{ value }} maxlength="100" />. But how do I then post all the edited values back to control to save them in file (or db)? I Would need all 3 values, that is GROUP, PROPERTY and VALUE.
Then I discovered django also has html widgets, which you create in views.py and then pass it to template. But this is where I stop understanding things, since I am creating widget in my controller class, but even if I am.
Shall I create a list of all django widgets and pass it to template? Same question occurs, how do I get all the widget values back to controller (views.py)?
Update (11.6.2012):
My code looks like this:
views.py
class DynForm(forms.Form):
def setFields(self, kwds):
keys = kwds.keys()
keys.sort()
for k in keys:
self.fields[k] = kwds[k]
def settings(request):
global Settings #my ini dict
kwargs = {}
for group in Settings:
for property in Settings[group]:
kwargs[property] = forms.CharField(label = property, initial = Settings[group][property])
f = DynForm()
f.setFields(kwargs)
return render_to_response('/settings.html',
{
'textWidget' : f,
})
#csrf_exempt
def save(request):
if request.method == 'POST': # If the form has been submitted...
form = DynForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
# process form data
# and return response
settings.html
<form action="/save/" method="post">
{% csrf_token %}
{% for field in textWidget %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label }}: {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Save" /></p>
</form>
The problem is, DynForm(request.POST) returns null so I can't get field values. My request.POST is correct, containing all fields and values. As much as I know, I am not suppose to parse request.POST data "by hands"?
OK, finally figured it out, taking me a lot of time (I am lacking a lot of python and django knowledge). I can't paste final solution because of copy right permissions, here is the concept:
Form
class DynamicForm(forms.Form):
def __init__(self,*k,**kw):
forms.Form.__init__(self,*k,**kw)
# loop over data from **kw
# create field
# set field default value
Notes about this code:
If form doesn't use super(SuperForm, self).__init__(*args, **kwargs), you must use forms.Form.__init__(self,*k,**kw) so you can append fields to form using self.fields attribute.
If you need to use default field value, use self.data[field] = defVal not initial = defVal. Form becomes unbound and you won't be able to parse data in your request.POST method. Unbound form (and with errors) will always return is_valid() False.
With this class, you have no problems parsing request.POST data. Looping over dynamic form fields looks like this:
View
for name,field in form.fields.items():
# name - field name
# form.data[name] - field value
Notes:
For the sake of simplisity use #csrf_exempt tag before POST method. See http://jordanmessina.com/2010/05/24/django-1-2-csrf-verification-failed/
Template code loops over fields in form displaying field label and value separated with :
Template
<form action="/Tris/save/" method="post">
{% csrf_token %}
{% for field in textWidget %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.non_field_errors }}
{{ field.label }}: {{ field }}
</div>
{% endfor %}
<p><input type="submit" value="Save" /></p>
</form>
Most of the solution is from here: http://jacobian.org/writing/dynamic-form-generation/ and django documentation.

Categories

Resources