I have another method about getting the list of checkbox - python

A method that is recommended by most of people:
files_form_checked_chkbox = request.POST.getlist("file_of_chkbox")
for every_file in files_form_checked_chkbox:
#do somethig
This is B method that I find:
keys = request.POST.keys()
for key in keys:
if key != "csrfmiddlewaretoken":
#do somethig
This is my template:
<p>List</p>
<form action="..." method="post">
{% csrf_token %}
{% for key in keys %}
<p>
<input type="checkbox" name="file_of_chkbox" value="{{key}}">
<a href="..." >{{key}}</a>
</p>
{% endfor %}
<input type="submit" value="Delete files" />
</form>
Both methods can do same thing.
I see. It's sure that A is better than B and A is explained many time.
I use request
But I want to understand why B is't recommended with reson.

B is not doing the same thing as A.
While looping over request.POST.keys() you are doing a lot of extra work by getting the POST parameters you don't even need.
First option is doing exactly what you need to do - get the list of checkbox values. And it is readable.

I prefer the B method, this one implements the "Synchronizer token pattern" to prevent Cross-site request forgery vulnerability
Learn more about CSRF:
http://en.wikipedia.org/wiki/Cross-site_request_forgery
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet

Related

Pass var value from HTML to python

Im using python3 and i have this HTMl which create buttons that it gets from a python list :
</style>
</head>
<body>
<ul>
{% for thing in value %}
<form method="get" action="/loader" value="submit">
<button class="button button">{{ thing }}</button>
</form>
{% endfor %}
</ul>
</body>
</html>
my python code:
#app.route("/test", methods=["GET"])
def test():
a = ["a1","a2"]
return render_template('sbutton.html', value=a)
#app.route("/loader", methods=["GET"])
def loader():
data = request.args.get()
print(data)
return render_template('loader.html', value=password)
So i will see buttons a1 and a2 in the website http://localhost/test
And when i press one of them i will redirect to /loader which is a route in my python code to another html.
I want that when i press a button, for example a1, i will get this information back to my python
inside the loader function.
i tried <form method="get" action="/loader" value="submit">
Added the value="submit but i dont get anything under print(data)
I just need to know on which button client clicked when he is redirected to /loader in my code.
I want to keep this value as a var in my python.
Thanks
data = request.args.get() should be called on the exact parameter you want to fetch, e.g. get('username'). Examples are here. As an aside, the data is passed from HTTP, the protocol that the values are transported through, not HTML, the markup language. If you want all values, request.args will return a dictionary with key-value pairs of all GET parameters passed.
I solved it, i was able to catch the button value name like this :
{% for thing in value %}
<form method="get" action="/loader">
<input type=hidden name="{{ thing }}">
<button class="button button">{{ thing }}</button>
</form>
{% endfor %}
And my code it redirects to :
#app.route("/loader", methods=["GET"])
def loader():
data = dict(request.args)
for key in data:
print(key)
return render_template('loader.html', value=password)
So now after i click the button i get the value back to my python /loader function
If client press on a1 button ill get a1 in python.

How to delete NDB value by key

I want to delete the selected value from the database in ndb, I have the following html code:
Getting the Data in Rooms as:
Class Method:
all_rooms = Room.query().fetch()
template_values = {
'logout_url': users.create_logout_url(self.request.uri),
'rooms': all_rooms
}
template = JINJA_ENVIRONMENT.get_template('rooms.html')
self.response.write(template.render(template_values))
HTML:
{% for i in rooms %}
<br/>
<form action="/rooms" method="post">
<input type="hidden" name="roomKey" value="{{ i.key }}"/>
<input type="submit" value="Delete" name="button"/>
</form>
{{i.key}}
Room Nummber:{{ i.roomNumber }}
<br/>
{% endfor %}
Which OutPuts As Following:
Key('Room', 4644337115725824) Room Nummber:10
I am passing the key to the delete method which is coming as:
Key('Room', 4644337115725824)
How should I retrieve key from it in order to delete the value Room Value.
Use i.key.urlsafe(). This will convert the key to a "url safe" string which is exactly where you plan to use it: in a url.
When you get the roomKey values back, you can convert them back from strings in urlsafe format to ndb Key objects by doing ndb.Key(urlsafe=roomKey) (see this link).
BONUS TIP: This would be extremely insecure code. Okay if this app is just for you (after sign-in) but dangerous if for untrusted users. Why? Well, someone could mock your HTML with keys for any object of any type and then simulate clicking the delete button. Your GAE-side code would blindly convert the urlsafe strings to keys and delete stuff.

Django dynamic page generation with templates

I want to generate a page using templates and content blocks. The homepage generates a bunch of checkboxes to generate a searchquery for some specific values.
<div id="searchbar">
{% for foo in bar %}
<input type="checkbox" name="foovar" value={{foo.name}}{%if foo.name in p %}checked=checked{%endif%}>{{foo.name}}<br>
{%endfor%}
<input type="submit" value="Submit">
</div>
<div id="searchresult">
{% block content %}
{% endblock %}
The value 'bar' is the parameter passed to the template containing all specific values:
return render_to_response('testlink/foobar.html',{'bar':strings_from_database})
Now, upon submitting the values, they are passed to my view, some magic happens, and the result is passed via
return render(request,'extend/extend.html',{'result':result,'p':queried_values})
result is the result, p contains the queried values (to keep the checkboxes checked after submitting).
{% extends "testlink/foobar.html" %}
{% block content %}
<b>results:</b> <br>
{% for result in result %}
{{result.someattribute}}<br>
{% endfor %}
{% endblock %}
Now, my problem: The checkboxes disappear, probably as the 'for foo in bar' loop is executed again. Is there a way to prevent that from happening, without to hardcode the checkboxes into my template? This would work (i did it with a few checkboxes, but doing this with too many searchvalues is no fun. Also i would like to avoid additional database hits and passing the parameters again.
I agree with the comments above, using forms is almost always a better idea. But in response to your problem, if you are not passing the bar variable to the template, the loop that parses the checkboxes will not be executed. You would need to add bar to the context for extend.html:
return render(request,'extend/extend.html',
{'result':result,'p':queried_values, 'bar':strings_from_database})
Are you not doing this just to prevent hitting the DB twice? Has it proven a very expensive query to run?
Apart from setting up caching, you can always pass ALL the checkboxes "names" along with the form. You can add hidden inputs, like so:
{% for foo in bar %}
<input type="checkbox" name="foovar" value="{{foo.name}}" {%if foo.name in p %}checked="checked"{%endif%}>{{foo.name}}<br>
<input type="hidden" name="foovar_all" value="{{foo.name}}" />
{%endfor%}
Then you need to collect the values with something like:
bar = request.POST.getlist('foovar_all')
But you would need to rethink your code so the bar variables hold just the names of those objects in both views, it looks like it is a list of objects currently. Again, is it really necessary to avoid that query?

python, create dynamic html name values..

i need a small help.. i am looping over objects which are in db and rendering all objects to template, so far so good. but what i want is that every rendered html name field should have different name so that i can refer to all of them latter. my code is this:
{% for p in products %}
<input type="number" name="name1" value="{{p.arg1}}" size="12"/>
<input type="number" name="name2" value="{{p-arg2}}" size="12"/>
{% endfor %}
but if i have 4 objects in DB, then i will have 8 rendered input fields in template, but all of them will have the "name" value as name1 and name2, is it possible to create 8 different names dynamically so that i can refer to all of them in my view again...
thanks
Use the forloop.counter variable
{% for p in products %}
<input type="number" name="name-{{forloop.counter}}-arg1" value="{{p.arg1}}" size="12"/>
<input type="number" name="name-{{forloop.counter}}-arg2" value="{{p.arg2}}" size="12"/>
{% endfor %}
The forloop.counter is 1-indexed. There is also the forloop.counter0 for indices
starting with 0.
Are you sure though that django formsets isn't what you need?

increment a variable in django templates

All,
How Can we increment a value like the following in django templates,
{{ flag =0 }}
{% for op in options %}
{{op.choices}}<input type="radio" name="template" id="template" value="template{{flag++}}"/>
{% endfor %}
thanks..
I don't think it's intended you should alter data in your templates. For in your specific case, you could instead use the forloop.counter variable.
For example:
{% for op in options %}
{{op.choices}}<input type="radio" name="template" id="template{{forloop.counter}}" value="template{{forloop.counter}}"/>
{% endfor %}
Also note that I added that number to the id attributes of the <input /> tag. Otherwise you'll have multiple inputs with the same id.
EDIT: I didn't note that it was a radio input. You could of course have the same name for each <input type="radio" />.
You explicitly can't do that in a template. Variable assignment is not allowed.
However if all you want is a counter in your loop, you just need to use {{ forloop.counter }}.
You might also want to look into having Django forms produce these values

Categories

Resources