I have a view that edits an instance of model Foo. It's either called with one arg (form post) or three args (initial request to edit the object):
def edit_it(request, key1_id=-1, key2_id=-1):
where key1_id and key2_id identify the particular instance to edit. On entry, I check to see if I've been called from a form post or from a link
if request.method == 'POST':
key1_id = request.key1_id # first thing that doesn't work
key2_id = request.key2_id # (also doesn't work)
foo = Foo.objects.get(key1=key1_id, key2=key2_id)
form = Foo(request.POST, instance=foo)
...
else:
foo = Foo.objects.get(key1=key1_id, key2=key2_id)
form = Foo(instance=foo)
In my template, I explicitly insert <input type="hidden" ... > for key1_id and key2_id. So it seems reasonable that key1_id and key2_id should be in request.POST somewhere, but I've not found it poking through code, docs, and google.
Or am I completely confused and I should do this differently? I tried specifying the key[12]_id fields in the model with "widget=forms.HiddenInput", but widget doesn't work here: key1_id is a primary key and key2_id is ForeignKey whose job is just to avoid fishing for other people's objects by modifying key1_id in the URL.
The html that results (now slightly modified thanks to the suggestion to maintain the args to the post) is this:
<table>
<form action="/seededit/u=2/sh=14" method="post">
<div style='display:none'>
<input type='hidden' name='csrfmiddlewaretoken'
value='19a559c496e637cdbf3132ce8e147cc4' /></div>
[...]
<tr>
<td><input type="hidden" name="user_id" value="2" />
<input type="hidden" name="shareable_id" value="14" /></td>
<td><input type="submit" value="Submit" name="submit" /></td>
</tr>
</form>
</table>
</p>
It's not request.key2_id It's request.POST['key2_id]` request.POST is a QueryDict that acts like a dictionary, so print request.POST will show you a dictionary.
That being said, you can still use/define those fileds as HiddenInput and then use django's form validation to make sure that they are the right type/exist etc. There are loads of options when it comes to handling forms, request variables, and validation.
Related
i'm trying to pass values as parameters using url_for but i have some problems as i have first some data loaded by a function and then, some data inserted manually using the <input ../> constructs. How can I do?
<td align = "center"> <a href = "{{url_for ('insertResults', idGia = attribute [0], language = attribute [4], level = attribute [5], info = info, written = written, oral = oral, session = session)}} "type =" submit "class =" btn btn-primary "> Insert </td>
where info, written and oral are the data entered as input in the following ways:
<td align = "center"> <input type = "text" placeholder = "100" id = "info" name = "info" /> </td>
<td align = "center"> <input type = "text" placeholder = "100" id = "written" name = "written" /> </td>
<td align = "center"> <input type = "text" placeholder = "100" id = "oral" name = "oral" /> </td>
The url_for function is executed on the server side. It is not possible to pass parameters from form fields to this.
Are you sure you want to use a GET request for this? It seems to me that a POST request makes more sense in your situation.
The following example shows you different methods with which you can transfer variables with a POST request and query them within your route. The data largely find their place within the request body. Only the attribute with the name "attr0" is sent within the url.
<form action="{{ url_for('indert_results', attr0=attr[0]) }}" method="POST">
<input type="hidden" name="val0" value="{{ attr[1] }}" />
<input type="text" name="val1" />
<input type="text" name="val2" />
<button type="submit">Submit</button>
</form>
#app.route('/insert-results/<int:attr0>', methods=['POST'])
def insert_results(attr0):
val0 = request.form['val0']
val1 = request.form.get('val1')
val2 = request.form.get('val1', 'default-value1')
print(
f'attribs: {attr0}',
f'values: {val0}, {val1}, {val2}',
sep='\n'
)
# ...
If you do insist on a GET request, I still advise you to use a form so that you can transfer the entries from the form fields as query parameters.
All data is transmitted in different sections of the url. The query parameters are added to the url in the form "?param0=value0¶m1=value1".
<form action="{{ url_for('insert_results', attr0=attr[0], attr1=attr[1]) }}" method="GET">
<input type="text" name="param0" />
<input type="text" name="param1" />
<input type="text" name="param2" />
<button type="submit">Submit</button>
</form>
#app.route('/insert-results/<int:attr0>-<str:attr1>', methods=['GET'])
def insert_results(attr0, attr1):
param0 = request.args['param0']
param0 = request.args.get('param1')
param1 = request.args.get('param2', 'default-value2')
print(
f'attribs: {attr0}, {attr1}',
f'params: {param0}, {param1}, {param2}'
sep='\n'
)
# ...
Regardless of whether you use the form or ask for the arguments within the url, you use a kind of dictionary which allows you to use .get(key [, default] [, type = <func_ptr>]) to ensure that a KeyError is bypassed, a default value is passed and possibly the type of the value is converted.
Choose the transmission method wisely and consider the visibility of the data for third parties, taking into account that the transmission may later take place in encrypted form. You should also consider the amount of data you want to send. The more data you want to transfer, the sooner you will switch to a POST request.
Especially with several data records that are transmitted individually, you can later think of a transmission using ajax. However, this is a more complex solution and the explanation would lead too far at this point.
i want to create two same name submit in html like this
<input type="submit" name="key" value="up">
<input type="submit" name="key" value="down">
but i want to use flask-wtf to do it, i don't know how to create Class?is like this?
class NameForm(FlaskForm):
submit = SubmitField('up')
submit = SubmitField('down')
No. Doing it like that will simply overwrite the class attribute submit. Do it like this:
class NameForm(FlaskForm):
key = SubmitField('not_used_string')
Then in your html after return render_template('page.html', form=form) you render it like this:
{{ form.key(value='up', id="A1") }} # -> will render <input id="A1" name="key" type="submit" value="up">
{{ form.key(value='down', id="A2") }} # -> will render <input id="A2" name="key" type="submit" value="down">
You don't have to supply id's but if you don't they will both be key.
Note that in order to have the same name you can only have one class attribute with that name.
how to retrieve a form search parameters in a django generic listView. My url is:
url(r'postsearch$', views.PostsList.as_view(), name='postsearch'),
My generic listview is:
class PostsList(generic.ListView):
model = Post
template_name = 'posts/post_list.html'
def get_queryset(self):
localisation = #how to get location
discipline = #how to get discipline
return Post.objects.filter(.......)
and my form is:
<form class="form-inline text-center" action="{% url 'posts:postsearch' %}" id="form-searchLessons" method="get">
<div class="form-group">
<input type="text" class="form-control" id="typeCours" list="matieres" placeholder="Matieres: e.g. Math, Physique,.." name="discipline">
<datalist id="matieres">
<option value="value1">
<option value="value2">
</datalist>
</div>
<div class="form-group">
<input type="text" class="form-control" id="Localisation" placeholder="Lieu: Bousaada, Douaouda,.."
name="localisation" onFocus="geolocate()">
</div>
<button type="submit" class="btn btn-default" id="btn-getLessons">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span> Trouver !
</button>
</form>
I want to get the Posts by applying a filter according to the lacalisation and matieres introduced in the search fields (in the form)
You can add the search terms to your url regular expression.
url(r'postsearch/(?P<localisation>\w+)/(?P<descipline>\w+)/$', views.PostsList.as_view(), name='postsearch'),
(Note, mind the trailing slash)
In your get_queryset method you can use those given url parameters
def get_queryset(self):
localisation = self.kwargs['localisation'] or None
discipline = self.kwargs['discipline'] or None
filters = {}
if localisation:
filters.update(localisation: localisation)
if discipline:
filters.update(discipline: discipline)
return Post.objects.filter(**filters)
Eventually you should relocate getting the parameters outside your get_queryset, but that is up to you.
I'm not sure about the security risks doing it this way. Anyone having more information about the security risks during this operation, please share.
I build a library that can help you to solve this problem, you just have to put in the searchable_fields the attributes you want to filter and it will take care of the rest.
https://github.com/SchroterQuentin/django-search-listview
I'm finding it overly difficult to customize ClearableFileInput as set as the default widget in a modelForm that includes an ImageField in the model.
Particularly I don't want the Delete Checkbox that is part of the widget. I've tried customizing/overriding the rendering in a number of ways to get rid of the checkbox including setting the widget to FileInput and overriding the render method where subclassing the widget in a widgets.py file.
The simplest I can explain the problem is like this:
forms.py
class SpecImageForm(ModelForm):
orig_image = forms.ImageField(required=False, widget=forms.FileInput)
class Meta:
model = SpecImage
fields = ['orig_image',]
# The intention is to have more than one SpecImageForm once this is working but for now the
# max_num is set to 1
SpecImageFormSet = inlineformset_factory(Spec, SpecImage, form=SpecImageForm, extra=1, max_num=1)
Despite explicitly setting the FileInput against the widget it renders like this in my template - still including the checkbox which I don't think should be present using FileInput.
<fieldset>
<legend>Images</legend>
<input id="id_specimage_set-TOTAL_FORMS" name="specimage_set-TOTAL_FORMS" type="hidden" value="1" />
<input id="id_specimage_set-INITIAL_FORMS" name="specimage_set-INITIAL_FORMS" type="hidden" value="0" />
<input id="id_specimage_set-MAX_NUM_FORMS" name="specimage_set-MAX_NUM_FORMS" type="hidden" value="1" />
<ul>
<li>
<label for="id_specimage_set-0-orig_image">Orig image:</label>
<input id="id_specimage_set-0-orig_image" name="specimage_set-0-orig_image" type="file" />
</li>
<li>
<label for="id_specimage_set-0-DELETE">Delete:</label>
<input id="id_specimage_set-0-DELETE" name="specimage_set-0-DELETE" type="checkbox" />
<input id="id_specimage_set-0-id" name="specimage_set-0-id" type="hidden" />
<input id="id_specimage_set-0-car" name="specimage_set-0-car" type="hidden" />
</li>
</ul>
</fieldset>
The relevant part of the template is this:
<fieldset>
<legend>Images</legend>
{{ image_form.management_form }}
{% for form in image_form %}
<ul>
{{ form.as_ul }}
</ul>
{% endfor %}
</fieldset>
The only thing slightly different that I'm doing is using an inlineformset_factory.
I've also tried to override the rendering of a widget using widgets.py but similarly seem unable to rid myself of the defualt settings - principally based on this thread.
Any ideas or solution to rid myself of the checkbox would be gratefully received!
I think this is to do with the inlineformset_factory applying a default can_delete parameter set to true, which was present regardless of how I'd prepared the form to use with it. Simply passing can_delete=False got rid of the Delete checkbox.
SpecImageFormSet = inlineformset_factory(Spec, SpecImage, form=SpecImageForm, extra=1, max_num=1, can_delete=False)
In addition when I rendered the form on it's own (without using inlineformset_factory) there was no sign of a 'Delete checkbox'. Then I found this SO post that explained why.
Getting there.
I have a form that is supposed to create a new 'Quote' record in Django. A 'Quote' requires a BookID for a foreign key.
This is my form
<form method="POST" action="{% url 'quotes:createQuote' %}">
{% csrf_token %}
<section>
<label for="q_text">Quote Text</label>
<input type="text" name="text" id="q_text" placeholder="Enter a Quote" style="padding-left:3px"> <br>
<label for="q_book">Book ID</label>
<input type="text" name="bookID" id="q_book" placeholder="Enter Book ID" style="padding-left:3px"> <br>
<label for="q_disp">Display Quote Now?</label>
<input type="radio" name="display" id="q_disp" value="True"> True
<input type="radio" name="display" value ="False">False <br>
<button value="submit">Submit</button>
</section>
</form>
And this is the method that it is targeting
def createQuote(request):
#b = get_object_or_404(Book, pk=request.bookID)
return HttpResponseRedirect(reverse('quotes:index'))
Somewhere in that request argument I assume there is some sort of field that contains the bookID the user will pass in on the form. How do I get at that information?
Bonus points for anyone who can tell me some way I can visualise data like I might with console.log(some.collection) in Javascript
if request.method == "POST":
book_id = request.POST['book_id']
Assuming you're sure it's in there. Otherwise you'll need to verify/provide a default value like you would for a normal python dictionary.
As for visualising the data, do you mean printing it to the console? In which case if you're running the django runserver you can just do print some_data. If you want it formatted a little nicer, you can use pretty print:
import pprint
pp = pprint.PrettyPrinter()
pp.pprint(some_data)