Flask Form, keep values after submit - flask

I have a flask form that has some values for a given event. On submit I redirect the user to page where I take the values from the form and calculate some statistics about the event. The user can accept these values, and submit the event to the database, or click an edit button which will take them back to the form for them to modify the values. The issue is since the form has already been submitted, when they click edit and are redirected back to the form, all the values are gone. I want the values to stay because chances are they will only be modifying one or two fields and I don't want them to have to re-enter all of them. Any ideas how to do this?

You can let Flask-wtf generate the form automatically, and it can remember the user input. If you pass the form instance to your Jinja template like this:
form = SomeForm()
return render_template("template.html", form=form)
A minimal example of a form:
class SomeForm(FlaskForm):
name = TextField(label='name', default="")
save = SubmitField(label='Save', description="Save")
And in your Jinja template:
<form method="post" action="the url" class="form-inline">
<ul>
{% for field in form %}
<li>{{ field.label }} {{ field }}</li>
{% endfor %}
</ul>
</form>

You can use window.history.back();.
From History API: "This acts exactly as if the user clicked on the Back button in their browser toolbar"
This works because the browser saves the users inputs , all except for the type="password" ones

Related

How to show a django-tables2 Table in a form while keeping its sort working?

I have a simple forms.Form with forms.ChoiceField in it. Below on the same page is a django-tables2 Table. The ChoiceField drives selection criteria for a query that feeds the table. Simple. The ChoiceField sits inside a form:
<body>
<form action="/e/n/" method="post">
{% csrf_token %}
{{ choiceFieldForm }}
<input type="submit" value="Submit"/>
</form>
{% render_table table %}
</body>
In my urls.py I have:
urlpatterns = [
url(r'^$', views.start, name='start'),
url(r'^n/$', views.n, name='n'),
]
And in my views.py I have:
def n(request):
if request.method == 'POST':
# handle "submit" button click
else:
# !!! table sort sends GET here
The problem is when I click on a table column to sort data, it sends GET on the same URL with the form: /e/n/. In order to return rendered template, I need to assemble the context with all the fields on the page, including the table itself. Now as I mentioned earlier, to pull table data I need to know the currently selected value of ChoiceField, which is not coming with this GET request.
What am I missing?
A am thinking, either have the table send GET on a different URL, so that its column sorting does not interfere with the data on the page. Or figure out how to send necessary data with the GET, so it can be used to re-create output.

Create dynamic form and retrieving values on post in Django

I want the user to be able to select a time period from the drop down then select the number of appointments needed with that time span and have it added to a list. I have been able to accomplish this with simply javascript and Html, but am at a loss as how to get all the values from the table after the user clicks 'submit'.
If I used Django's form API then the fields in the table would display as editable textboxes. Is there a way to make a form with labels/non-editable text instead of fields? That way I can edit the labels with javascript and the values will get passed to the view on Post.
I am new to Django so any suggestions are welcome.
Example
Forms.py Example - Not what I want:
class AppointmentForm(forms.Form):
TimePeriod = forms.IntegerField(label='Time Period')
Amount = forms.IntegerField(label='Amount')
AppointmentFormSet = formset_factory(AppointmentForm)
When I solved much more complex generated form, I just created view, which collected some data, set context and rendered template.
That template was "old style" form, with all the tags written by hands/loops and so, like
{% for p in pairs %}
<option name="name_{{p.id}}" value="{{p.val}}">
{% endfor %}
and
{% for v in vars %}
<input type="text" name="{{v.name}}" value="{{v.val}}">
{% endfor %}
and the form ended in view, where I was looping over request.POST and parsing it manually (mainly)
Not very Django way, but you can do ANYTHING with this approach (and shoot yourself to any leg any time you want too)
Presumably by "labels" you just mean non-editable text, so it could be a <div> or a <p> etc - in this case you will need to have a hidden input which mirrors the content of the label, i.e.
<div class="label">Text here</div>
<input type="hidden" name="form-field-name" value="Text here">
To achieve this in your form, use a forms.HiddenInput widget:
class AppointmentForm(forms.Form):
time_period = forms.IntegerField(widget=forms.HiddenInput)
Obviously the django form isn't going to render the way you need it to, so you'll need to render it using custom html, which will probably look something like this:
{% for field in form %}
<div class="label">{{ field.data }}</div>
{{ field }}
{% endfor %}

How to send dynamic hidden form variables using POST

I have a page that pulls out entries from the database as 'users' and lists them. A typical result looks like this:
John
Marty
Tom
Jane
Chris
Now I would like to click on a specific the name and go to their specific page. For this, I have a form that posts to a view that expects the user that has been "clicked"
So far, I have a form inside a loop that goes through each 'user' in 'users' table. The setup works fine but the major problem is that the form element 'name' is replaced by the last user. No matter, whose name I click it always passes the last user's username.
{% for user in users %}
<h1>{{ user.firstName }} {{ user.lastName }}</h1>
<form action="/friend_profile/" method="post" accept-charset="utf-8">
<input type="hidden" name="selectedFriend" value ={{ user.userName }}>
<button type="submit" value="view profile">
{% endfor %}
I am not using DJango forms and just using request.method == 'POST' for receiving variables.
So my dumb question would be, is there a way to dynamically create 'name' form element and submit its contents specific to the user? Right now, the form always submits the user "Chris" no matter which user I click because its the last one on the list.
Right now, the form always submits the user "Chris" no matter which user I click because its the last one on the list.
That's because you didn't close your <form> tag, so the browser sees one big bunch of nested forms.
Also, you need to quote and escape the value attribute in your hidden input:
<form action="/friend_profile/" method="post" accept-charset="utf-8">
<input type="hidden" name="selectedFriend" value="{{ user.userName|escape }}">
<button type="submit" value="view profile">
</form>

why does password reset works with unregistered email in django?

I have a couple of questions regarding how the password reset works in Django.
How can I do testing on password reset testing during development phase?
The password reset sends email to unregistered email addresses successfully (as appears on screen). I thought it should display "no such registered email address is found" instead of displaying "password reset successful".
Here is the form used for password reset. I am confused from the form action. It submits to itself which is http://127.0.0.1:8000/accounts/password/reset/ but how is that it is redirected to http://127.0.0.1:8000/accounts/password/reset/done/ after submission when it submits to itself.
{% extends "registration/registration_base.html" %}
{% load i18n %}
{% block title %}{% trans "Reset password" %}{% endblock %}
{% block content %}{% blocktrans %}
Forgot your password? Enter your email in the form below and we'll send you
instructions for creating a new one.{% endblocktrans %}
<form method='post' action=''>{% csrf_token %}
<table>
{{ form }}
<tr><td></td><td><input type='submit' value="{% trans "Reset password" %}" /></td></tr>
</table>
</form>
{% endblock %}
I presume the problem is that your development environment isn't set up to send emails? In that case, add this in your settings_local(or equivalent):
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
This will cause emails to be displayed in the runserver terminal. You can copy-paste any links from there.
That is deliberate, to not-allow outside users to poke at the registration form and see whether a particular email has been registered or not. A "privacy feature", I guess we could call it.
POST-ing to the same URL is a standard practice in Django. It is not a requirement, but it just makes sense to do that. It makes sense because that way a single View handles both creating of the Form and receiving the data, see Using a form in a view
And the redirection happens from the View, deliberately:
def form_valid(self, request, form):
# blah blah...
return redirect(success_url)
The redirection after a POST is also a standard practice, and not just in Django: http://en.wikipedia.org/wiki/Post/Redirect/Get
I doesn't display "no such registered email address is found", as it is the best practice approach against phishing attempts. However, you can always write your own code to check if the given email exists in your DB. As for how the user gets redirected to '/accounts/password/reset/done/', I'd have to see the 'Reset password' view to know for sure.

Determining whether a user is associated with an object through another class in a django template

I have a user model, an item model, and a possession model to store data about a user possessing an item. When a user is logged in and viewing an item, I want to display an 'add to my items' button, unless the user already has the item.
I was trying this code in the template:
{% if not user.possession_set.filter(item=item.id) %}
<input type='submit' value='add to my items' />
{% endif %}
where
item is the foreign key name for the item object in my possession model and
item.id is the primary key for the item being displayed to the user
but I get this error:
Could not parse the remainder: '(item=item.id)'
I'm thinking I can't use the .filter() function since that is for querying the database? I found django's template filters, like this one:
http://docs.djangoproject.com/en/1.1/ref/templates/builtins/#get-digit
but there aren't any that can be combined to filter for a certain value of item. It seems I would have all the information in the template to do this, since I'm getting the user and it's possession_set, which should have the item field for each possession, so I'm thinking it's just a syntax thing?
Thanks for the help!
You could write a custom template filter for this.
def owns(user, id):
return not user.possession_set.filter(item=id)
Then, in your template:
{% load mystuff %}
{% if user|owns:item.id %}
Check the Django docs at http://docs.djangoproject.com/en/1.1/howto/custom-template-tags/ for more info. Not sure if passing item.id as the filter argument will work, though.
You can't use such complicated expressions in the template, only in the view. Compute the information, whether user can have this button in the view and pass a single True or False value to the template. For example:
in view
allow_addition = not user.possession_set.filter(item=item.id)
and in template:
{% if allow_addition %}
<input type='submit' value='add to my items' />
{% endif %}