How to send dynamic hidden form variables using POST - django

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>

Related

How to assign function to button in Django

urlpatterns=[
path('login/',views.LoginUser,name='login'),
path('logout/',views.LogoutUser,name='logout'),
path('register/',views.RegisterUser,name='register'),
path('delete/<str:pk>',views.DeleteUser,name='delete'),
path('',views.home,name='home'),
#path('usersSettings/',views.UserSettings,name='userSettings'),
path('users/<str:pk>/',views.users,name='users'),
path('parameters/',views.parameters,name='parameters'),
path('EbotManual/',views.EbotManual,name='EbotManual'),
path('LedManual/',views.LedManual,name='LedManual'),
path('TestRutins/',views.TestRutins,name='TestRutins')
]
I am designing a website based on django. I want to update the user information and delete the user if wanted in the same page. I created updating and it works properly. But when I address the delete user function to same html file , the button that I want it to delete user also updates just like the other button. I need both buttons to work for their own purposes. I thought that without changing anything assigning delete function to button might help thats why I wrote the title like that. Thank you!
<div class="login--wrapper">
<form method="POST" class="form">
{% csrf_token %}
<div class="center">
<h1>Kullanıcı Ayarları</h1>
{% csrf_token %}
{% for field in form %}
<div class="mb-3">
<label for="exampleInputPassword1" class="from-label">{{field.label}}</label>
{{field}}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Update Info</button>
<button type="submit" class="btn btn-primary">Delete User </button>
</div>
def DeleteUser(request,pk):
user=DataEbotUser.objects.get(id=pk)
if request.method=='POST':
user.delete()
context={'user':user}
return render(request,'home/UsersPage.html',context)
def users(request,pk):
user=DataEbotUser.objects.get(id=pk)
form=EditUserForm(instance=user)
if request.method=='POST':
form=EditUserForm(request.POST, instance=user)
if form.is_valid():
form.save()
context={'form':form , 'users':users}
return render(request,'home/UsersPage.html',context)
url patterns:
urlpatterns=[
path('login/',views.LoginUser,name='login'),
path('logout/',views.LogoutUser,name='logout'),
path('register/',views.RegisterUser,name='register'),
path('delete/<str:pk>',views.DeleteUser,name='delete'),
path('',views.home,name='home'),
#path('usersSettings/',views.UserSettings,name='userSettings'),
path('users/<str:pk>/',views.users,name='users'),
path('parameters/',views.parameters,name='parameters'),
path('EbotManual/',views.EbotManual,name='EbotManual'),
path('LedManual/',views.LedManual,name='LedManual'),
path('TestRutins/',views.TestRutins,name='TestRutins')
]
The problem is that your two buttons submit the form to the same page that rendered the form. There is no way to tell them apart.
If you want each button to perform a different action, one way to do this would be:
<button type="submit" class="btn btn-primary">Update Info</button>
<a class="btn btn-danger" type="button" href="{% url 'delete' user.pk %}">Delete User</a>
Since the function users is the only one to manage the update of the user's information based on the form data, the button Update Info remains in the form of submit button.
The Delete User button on the other hand is different. It simply calls the function DeleteUser passing it a pk which will be used to delete a user.
Here are some things to consider:
The function DeleteUser must not be called directly. It is the function users which must render the page.
You have to render the user object in the context of your function users, to be able to retrieve the pk of the user who will be used for the button delete
Function DeleteUser must not render the template but redirect to another url like home. Something like return redirect('home')

Flask Form, keep values after submit

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

Referencing forms fields generated with Wagtail Form Builder

I have generated a simple contact form with four fields using Wagtail Form Builder. The challenge I'm having, is that I'm unable to reference the form fields with css classes individually, since I'm not sure where I should get the field id and label name from.
Here is the code that renders the form:
<h1>{{ page.title }}</h1>
{{ page.intro|richtext }}
<form action="{% pageurl page %}" method="POST" class="sky-form contact-style">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
If referencing the fields individually is not possible, what will be the other method(s) to achieve the same result?
Wagtail formbuilder creates a dynamic form - the id (name) of each field is created by the following code: str(slugify(text_type(unidecode(self.label))))
(from https://github.com/torchbox/wagtail/blob/master/wagtail/wagtailforms/models.py#L90)
So the field label is converted to ascii characters and then to a slug. For example, if you have a field name First Name it will be converted to 'first-name'.
An easy way to find out what is the actual id of the form fields that wagtail formbuilder creates is to actually output the fields in a template by enumerating them:
{% for field in form %}
{{ field }}
{% endfor %}
and then inspect the produced html code to see their actual ids (you'll see <input class="textinput textInput" id="id_first-name" maxlength="255" name="first-name" type="text"> so you'll know that the id of the field is first-name)

How to assign form id to Django ModelForm?

I am using django-webtest to create automated functional tests for my application.
As I have multiple forms on a single web page, I'm currently using a hard-coded index to select the form of interest. For instance:
# Forms on this page are: forms[0] = Establishment form,
# forms[1]= School Form
school_form = school_page.forms[1]
school_form['phone'] = self.school_phone_number
school_form.submit(value='Submit')
I would like to use the form id instead of a hard-coded index to select the form of interest, so that the code is maintainable. But when I print school_form.id in my code, the value is None.
Template is:
<form action="" method="post" >
{% csrf_token %}
<p>
{{ establishment_form|crispy }}
<br><br>
{{ school_form|crispy }}
</p>
<button type="submit" class="btn btn-lg btn-primary">Submit</button>
I couldn't locate in the Django documentation how to assign the form id (not the form field id) to a ModelForm. Could someone help me with this?
I'm using Django 1.7, django-webtest 1.7.8, WebTest 2.0.18 and django-crispy-forms 1.4.0.
Django forms aren't responsible for outputting the form element itself. So there is nothing to be done at the form declaration level.
You can always pass an attribute from the view and use it in your template:
<form id="{{ form_id_from_view }}" action="." method="POST">
You can directly assign the id to the form element in your template.
<form id="my_id" name="some_name" action="/my/url/" method="POST">

Easiest way to get the value of a key in request.POST

I have a user with a list of schools he has entered in his userprofile. I want to give him the ability to delete any one of his entries.
The following is the way I am currently using to delete a database entry, based upon the value of a key in the template:
# in template
{% for education in educations %}
<p>{{ education.school }}
<input type="submit" name="delete_{{education.id}}" value="Delete" /></p>
{% endfor %}
# in view
if 'Delete' in request.POST.values():
for key in request.POST.keys():
if key.startswith('delete'):
education_id = key[7:]
profile.educations.remove(Education.objects.get(id=education_id))
Is there an easier way to get the value of a key, rather than having to iterate over for key in request.POST.keys()? Thank you.
Forms are free. Make more of them.
{% for education in educations %}
something something
<form action="..." method="POST">
<input type="hidden" name="id" value="{{ education.id }}">
<input type="submit" value="Delete">
</form>
{% endfor %}
Then in the view:
id = request.POST['id']
profile.educations.remove(...)
Or put the id a GET parameter, instead of a hidden field (just make sure you don't use GET method for a form — those should never have any side effects).
While I also agree that forms are nice, you can also simplify your code a bit:
if 'Delete' in request.POST.values():
for key in request.POST.keys():
if key.startswith('delete'):
education_id = key[7:]
profile.educations.remove(Education.objects.get(id=education_id))
Could be simplified into:
for education_id in [key[7:] for key, value in request.POST.iteritems() if value == 'Delete' and key.startswith('delete')]:
profile.educations.remove(Education.objects.get(id=education_id))
I came up with another approach using the filter function but it was much messier and looked less elegant than the above.
if request.method == 'POST' and 'button_name' in request.POST.keys():
do_something
elif other button name