Adding form action in html in laravel - html

I am unable to pass url in views html form action tag.
<form method="post" action="??what to write here??" accept-charset="UTF-8">
I want to set it's action to WelcomeController#log_in function in WelcomeController file in controllers.
Here are my routes:
Route::get('/','WelcomeController#home');
Route::post('/', array('as' => 'log_in', 'uses' => 'WelcomeController#log_in'));
Route::get('home', 'HomeController#index');
After submitting it keeps the same url
http://localhost:8000/
And the main error line
Whoops, looks like something went wrong.
After that there is 1/1 TokenMismatchException in compiled.php line 2440:

You can use the action() helper to generate an URL to your route:
<form method="post" action="{{ action('WelcomeController#log_in') }}" accept-charset="UTF-8">
Note that the Laravel 5 default installation already comes with views and controllers for the whole authentication process. Just go to /home on a fresh install and you should get redirected to a login page.
Also make sure to read the Authentication section in the docs
The error you're getting now (TokenMismatchException) is because Laravel has CSRF protection out of the box
To make use of it (and make the error go away) add a hidden field to your form:
<input name="_token" type="hidden" value="{{ csrf_token() }}"/>
Alternatively you can also disable CSRF protection by removing 'App\Http\Middleware\VerifyCsrfToken' from the $middleware array in app/Http/Kernel.php

Laravel 5.8
Step 1: Go to the path routes/api.php add:
Route::post('welcome/login', 'WelcomeController#login')->name('welcome.login');
Step2: Go to the path file view
<form method="POST" action="{{ route('welcome.login') }}">
</form>
Result html
<form method="POST" action="http://localhost/api/welcome/login">
<form>

if you want to call controller from form action that time used following code:
<form action="{{ action('SchoolController#getSchool') }}" >
Here SchoolController is a controller name and getSchool is a method name, you must use get or post before method name which should be same as in form tag.

1) In Laravel 5 , form helper is removed .You need to first install laravel collective .
Refer link: https://laravelcollective.com/docs/5.1/html
{!! Form::open(array('route' => 'log_in')) !!}
OR
{!! Form::open(array('route' => '/')) !!}
2) For laravel 4, form helper is already there
{{ Form::open(array('url' => '/')) }}

Use action="{{ action('WelcomeController#log_in') }}"
however TokenMismatchException means that you are missing a CSRF token in your form.
You can add this by using <input name="_token" type="hidden" value="{{ csrf_token() }}">

For Laravel 2020. Ok, an example:
<form class="modal-content animate" action="{{ url('login_kun') }}" method="post">
#csrf // !!! attention - this string is a must
....
</form>
And then in web.php:
Route::post("/login_kun", "LoginController#login");
And one more in new created LoginController:
public function login(Request $request){
dd($request->all());
}
and you are done my friend.

In Laravel 8:
Step 1: In the blade file:
<form action="{{ route('authLogin') }}" method="post">
#csrf
....
</form>
Step 2: And then in web.php:
use App\Http\Controllers\UsersController;
Route::post('login-user', [UsersController::class, 'login'])->name('authLogin');
Step 3: And in the UsersController:
public function login(Request $request){
dd($request->all());
}
Happy to share. Thanks to ask this question.
** For more information, please see https://laravel.com/docs/8.x/routing#generating-urls-to-named-routes

{{ Form::open(array('action' => "WelcomeController#log_in")) }}
...
{{ Form::close() }}

You need to set a name to your Routes.
Like this:
Route::get('/','WelcomeController#home')->name('welcome.home');
Route::post('/', array('as' => 'log_in', 'uses' => 'WelcomeController#log_in'))->name('welcome.log_in');
Route::get('home', 'HomeController#index')->name('home.index');
I just put name on Routes that need this. In my case, to call from tag form at blade template.
Like this:
<form action="{{ route('home.index') }}" >
Or, You can do this:
<form action="/" >

Form Post Action :
<form method="post" action="{{url('login')}}" accept-charset="UTF-8">
Change your Route :
In Routes -> Web.php
Route::post('login','WelcomeController#log_in');

The following should work.
{{ Form::open( array('url' => action('WelcomeController#log_in'), 'files'=>true,'method'=>'post') ) }}
...
{{ Form::close() }}

I wanted to store a post in my application, so I created a controller of posts (PostsController) with the resources included:
php artisan make:controller PostsController --resource
The controller was created with all the methods needed to do a CRUD app, then I added the following code to the web.php in the routes folder :
Route::resource('posts', 'PostsController');
I solved the form action problem by doing this:
I checked my routing list by doing php artisan route:list
I searched for the route name of the store method in the result table in the terminal and I found it under the name of posts.store
I added this to the action attribute of my form: action="{{route('posts.store')}}" instead of action="??what to write here??"

Your form is also missing '{{csrf_field()}}'

Related

Flask-SQLAlchemy MySQL application won't write to database [duplicate]

I'm using Flask-WTF:
Here is my form:
from flask.ext.wtf import Form, TextField
class BookNewForm(Form):
name = TextField('Name')
Here is the controller:
#book.route('/book/new', methods=['GET', 'POST'])
def customers_new():
form = BookNewForm()
if form.is_submitted():
print "submitted"
if form.validate():
print "valid"
if form.validate_on_submit():
flash("Successfully created a new book")
return redirect(url_for('.books_show'))
return render_template('views/books_new.html', form=form)
Now the problem is, if you look at my print statements, it always prints submitted, but it NEVER prints valid and validate_on_submit() is never executed. Why?
You're not inserting the CSRF field in the HTML form.
<form method=post>
{{ form.csrf_token }}
{{ form.name }}
<input type=submit>
</form>
After adding form.csrf_token to the template (docs), the form will validate as expected.
Add print(form.errors) after validating the form to see the errors that were raised. errors will be empty before validation. In this case, there is an error about missing
#book.route('/book/new_no_csrf', methods=['GET', 'POST'])
def customers_new_no_csrf():
form = BookNewForm()
print(form.errors)
if form.is_submitted():
print("submitted")
if form.validate():
print("valid")
print(form.errors)
if form.validate_on_submit():
flash("Successfully created a new book")
return redirect(url_for('.books_show'))
return render_template('books_new.html', form=form)
{}
submitted
{'csrf_token': [u'CSRF token missing']}
127.0.0.1 - - [29/May/2012 02:01:08] "POST /book/new_no_csrf HTTP/1.1" 200 -
127.0.0.1 - - [29/May/2012 02:01:08] "GET /favicon.ico HTTP/1.1" 404 -
I created an example on GitHub.
you can print errors
print form.errors
or
app.logger.debug(form.errors)
and if you got csrf-error, you should set form.csrf_token in your template.
I came across this when trying to render a FormField being iterated over my FieldList in my template. I had to embed two hidden_tag elements one for the FieldList form and one for the FieldForm form, search the template comments for keyword "HIDDEN TAG"
class ParamRangeForm( FlaskForm ):
minX = FloatField( )
maxX = FloatField( )
class ParamRangesForm( FlaskForm ):
paramRanges = FieldList( FormField( ParamRangeForm ) )
submit = SubmitField( 'Submit' )
def loadParams( self ) :
for paramName in ["p1" , "p2" , "p3", "p4"] :
prf = ParamRangeForm( )
prf.minX = -100.9#float('-inf')
prf.maxX = 100.5#float('-inf')
self.paramRanges.append_entry( prf )
...
<form action="" method="POST" enctype="multipart/form-data">
{{ rangesForm.hidden_tag() }} <!--#### HIDDEN TAG #1 -->
<table>
<!--Print Column Headers-->
<thead>
<tr>
<th class="ColumnHeader">Parameter</td>
<th class="ColumnHeader">Min</td>
<th class="ColumnHeader">Max</td>
</tr>
</thead>
<!--Print Parameter Rows-->
<tbody>
{% for paramRange in rangesForm.paramRanges %}
<tr>
{{ paramRange.hidden_tag() }} <!--#### HIDDEN TAG #2 -->
<td>p{{ loop.index }}</td>
<td>{{ paramRange.minX }}</td>
<td>{{ paramRange.maxX }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{{ rangesForm.submit() }}
</form>
insert this after the tag in template html file:
{{ form.csrf_token }}
I was clearing the flask session if I wasn't logged in before every request. This was causing this issue.
#main.before_request
def before_request():
if not current_user.is_authenticated():
# TODO clean sessions may cause CSRF missing issue
session.clear()
print "Session Cleared"
return redirect(url_for('auth.login'))
I think the API has changed.Maybe try changing
from flask.ext.wtf import Form
to:
from flask_wtf import Form
I spent a several hours debugging a validation issue with Flask-WTF. The issue like many others was a CSRF validation issue. However, mine was not caused by any of the common issues I have found.
The standard Flask-WTF implementation of CSRF requires two things be delivered to the browser.
One: The hidden CSRF form field e.g.
<input id="csrf_token" name="csrf_token" type="hidden" value="ImYzODdmZTdhYTRlMmNkYWRjYmRlYWFmZjQxMDllZTQ1OWZmYzg3MTki.XKvOPg.gUCkF9j-vg0PrL2PRH-v43GeHu0">
Two: The session cookie HTTP response header e.g.
Set-Cookie: session=eyJjc3JmX3Rva2VuIjoiZjM4N2ZlN2FhNGUyY2RhZGNiZGVhYWZmNDEwOWVlNDU5ZmZjODcxOSJ9.XKvOPg.a3-W62MHvaGVkv2GYCi-dgpLE3Y; HttpOnly; Path=/
If either of these are missing the browser will fail to send the proper CSRF validation. Of course, this in turn causes the form validation to fail.
If the csrf_token hidden field is present in the form but the session cookie is missing, you will receive the following response when the form is submitted...
Bad Request
The CSRF session token is missing.
In my case the session cookie was missing because of a bug in my code. I needed to serve a custom HTTP header across the entire Flask site. I included it like this...
class LocalFlask(Flask):
def process_response(self, response):
response.headers['my-header'] = 'My Header Value'
return response
app = LocalFlask(__name__)
This however causes anything that rellys on the the Flask.response.headers method to fail. One of those is Flaks-WTF setting the session cookie HTTP header.
This can be solved by adding the super() method to the LocalFlask class so that it inherits methods form the Flask class.
class LocalFlask(Flask):
def process_response(self, response):
response.headers['my-header'] = 'My Header Value'
#LocalFlask inherits methods from Flask
super(LocalFlask, self).process_response(response)
return response
app = LocalFlask(__name__)
Well I tried all the solutions mentioned
form.hidden_tag()
form.csrf_token
form.csrf
with
app.secret_key=""
app.config["SECRET_KEY"]=""
but form.validate_on_submit() always returned false.
None of these seem to work for me, so I used the basic method and this method
import request
request.method="POST"
or
form.is_submitted()
These two worked for me

How do I access a single field while using For Loop to iterate through all the fields of a ModelForm in Django Template?

I have a model which has four ForeignKey fields, so they are dropdown fields in the form.
class Package(models.Model):
patient=models.ForeignKey(Patient, on_delete=CASCADE)
diagnosis=models.ForeignKey(Diagnosis, on_delete=CASCADE)
treatment=models.ForeignKey(Treatment, on_delete=CASCADE)
patient_type=models.ForeignKey(PatientType, on_delete=CASCADE)
date_of_admission=models.DateField(default=None)
max_fractions=models.IntegerField(default=None)
total_package=models.DecimalField(max_digits=10, decimal_places=2)
The forms.py:
class PackageForm(ModelForm):
class Meta:
model=Package
fields='__all__'
widgets={
"patient_type" : forms.Select(attrs={"onblur":"mf();"}),
"max_fractions" : forms.NumberInput(attrs={"onfocus":"mf();", "onblur":"tp();"}),
"total_package" : forms.NumberInput(attrs={"onfocus":"tp();", "onblur":"onLoad();"}),
'date_of_admission': DateInput(attrs={'type': 'date'}),
The views.py:
def package_view(request):
if request.method=='POST':
fm_package=PackageForm(request.POST, prefix='package_form')
if fm_package.is_valid():
package=fm_package.save()
IpdReport.objects.create(patient=package.patient, package=package)
fm_package=PackageForm(prefix='package_form')
return render (request, 'account/package.html', {'form5':fm_package})
else:
fm_package=PackageForm(prefix='package_form')
return render (request, 'account/package.html', {'form5':fm_package})
The Template:
<form action="" method="post" novalidate>
{% csrf_token %}
{{form5.non_field_errors}}
{% for fm in form5 %}
<div>
{{fm.label_tag}}
{{fm}}
<span>{{fm.errors|striptags}}</span><br><br>
</div>
{% endfor %}
<button type="submit" id="savebtn">Save</button>
</form>
Now, what I want is to insert an Anchor Tag next to all the foreign_key fields, in the template, to add a new object into the original table. For example, an Add Patient option next to the Patient's dropdown field, when clicked, a new, small window would show up with Patient form. The user enters the new patient's data, saves it and the same name shows up in the dropdown.
But as I am using a For Loop in the template, how would I be able to access those foreign key fields and apply the options? Any suggestions, please?
If it isn't a problem I would move away from rendering all of the fields with the 'forloop'. Instead I would use notation: form.field to render different fields. So it would look like:
{{ form.patient.label_tag }}
{{ form.patient }}
It should be much easier to navigate through fields this way, but of course it will require more typing :)

how to delete user from return in controller

route not working, where should I put #csrf and #method('DELETE')? because it does not delete the user. before the problem happens, #csrf and #method('DELETE') was in blade view. But when I put #csrf and #method('DELETE') in return it shows an error.
$employees = DB::table('users')->leftjoin('roles', 'users.role_id', '=', 'roles.id')->leftjoin('supervisors', 'users.manager_id', '=', 'supervisors.id')
->select(['users.id','users.name','users.department','users.email','users.leaves_available','roles.name_role','supervisors.name_supervisor']);
return Datatables::of($employees)
->addColumn('action', function ($employees) {
return '<form action="'.route('employee.destroy', $employees->id).'" method="post">
<button type:"submit" class="btn btn-sm btn-danger">Delete</button>
</form>
</div>
</div>
</div>
</div>';
})->make(true);
in the form I use route('employee.destroy', $employee->id) then the parameter will be http://localhost:8000/employee/1 and I want the user got delete.
EmployeeController.php
public function destroy($id)
{
DB::table('users')->delete($id);
return redirect()->route('home')
->with('success','Employee have been deleted');
}
This is my web.php
Route::get('employee/{id}', 'EmployeeController#destroy');
I expect the destroy function will run and redirect back to home. But what I get is :
The POST method is not supported for this route. Supported methods:
GET, HEAD, PUT, PATCH, DELETE.
Change the route from get to post. Like this
Route::post('employee/{id}', 'EmployeeController#destroy');
Because, you are using post method in your form but your route is in get. Both need to be same.

How to edit html content in Django forms?

Because I am not from English Naive country.
Default html content from Django form, is not suitable for my country.
Could someone tell me how to edit html content in forms.py?
I just want to keep English variable for later SQL column settings, but change html content in form.
in forms.py
class DjUserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta():
model = DjUser
fields = ('username', 'email', 'password')
in html
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ user_form.as_p }}
<input type="submit" value="註冊">
</form>
It showed all English content in html, like Username, Email Address etc..
The thing I needed is 使用者名稱, 電子信箱 etc.. The html contents I want to edit:
You can use attr for styling and naming you're form fields, it will go something like this:
class DjUserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput(attrs={
'class': 'my-class',
'placeholder': '使用者名稱, 電子信箱',
}))
also you will perhaps need to do some localization for you're application.

Django : HTML form action directing to view (or url?) with 2 arguments

Started learning django about a week ago and ran into a wall. Would really appreciate any enlightenment...
models.py
class data(models.Model):
course = models.CharField(max_length = 250)
def __str__(self):
return self.course
html
Converted the objects in models.course to schlist
<link rel="stylesheet" type="text/css" href="{% static '/chosen/chosen.css' %}" />
<form action={% views.process %} method="GET">
<div>
<h4 style="font-family:verdana;">First Course: </h4>
<select data-placeholder="Course" style="width:350px;" class="chosen-select" tabindex="7">
<option value=""></option>
{% for item in schlist %}
<option> {{ item }} </option>
{% endfor %}
</select>
</div>
</br>
<div>
<h4 style="font-family:verdana;">Second Course:</h4>
<select data-placeholder="Course" style="width:350px;" class="chosen-select" tabindex="7">
<option value=""></option>
{% for item in schlist %}
<option> {{ item }} </option>
{% endfor %}
</select>
</div>
</br>
<input type="submit" value="Compare!" />
</form>
urls.py (having my doubts if this works..)
urlpatterns = [
url(r'^(\d+)/(\d+)$',views.process, name = 'process'),
]
view.py
def process(request,q1 ,q2):
obj1= get_object_or_404(Schdata, course = q1)
obj2= get_object_or_404(Schdata, course = q2)
........
Was wondering if it is possible for the form action to direct the action to
(1) view.py or (2) url.py (and eventually to a view.py) with 2 arguments selected?
If so how should the form action be? {{view ?}} or {{url ?}}. Am I missing out the definition of my arguments in my HTML?
Directing to views.py:
User input is CharField, could use get_object_or_404 to get the model pk. However when defining my urls.py I would get a Noreverse error as my url arguments is the primary key.
Directing to urls.py:
Url arguments is primary key. From the way I see it, I need to magically convert my User input Charfield to a pk before passing it to urls.py
Is there a (or) function for get() in django? E.g get_object_or_404(pk = q1 or course = q1)?
Would really appreciate any advice. Been staring at this for hours.
You are trying to use the reverse resolution of urls in Django.
In your html file correct form action url to the following and method should be POST:
<form action={% url 'process' %} method="POST">
In case you are trying to pass parameters along then use this:
<form action={% url 'process' request.user.id 4 %} method="POST">
Reference:
https://docs.djangoproject.com/en/1.10/topics/http/urls/
Yes i'm late but it can help others for better understanding how Django processes the request.
Django 3.0 pattern
How Django processes the request
Basic :
First Django check the matching URL.
If URL is matched then calling the defined view to process the request. (Success)
If URL not matched/found the Django invokes error Page Not Found
In detail reading :
Official Django Documentations How Django processes a request
These are your URL patterns :
urlpatterns = [ path('profile/edit/<int:pk>/',views.editprofile, name='editprofile'),]
Third argument in urlpatterns is for if you want to change the url pattern from current to this :
urlpatterns = [ url('profile/edit/user/id/<int:pk>',views.editprofile, name = 'editprofile'),]
You don't need to redefine url pattern in all Templates where you using url name.
For Example :
This is my template profile.html where i used the url name instead of hard coded url.
<a class="item" href="{% url 'editprofile' user.id %}" >Edit profile </a>
Solution of your problem :
.html
Only use url name instead of hard coded url in your templates and pass arguments.
<form action={% process no_of_arguments %} method="POST">
views.py
Here you can process your request
def process(request,no_of_arguments):
Become good django developer
You can also use Django ModelForms for your model.
Using model forms or simple form you can do multiple things
Modular approach
Write server side validation in related form instead of doing in views.py
Readable code - Clean code