How to use SUBMIT form to save message in Database - python

I was asked to Create a simple Flask app which stores just a single text
field, On a single web page, and on which the user should see a form with the "message"
field. Below the form should be a list of existing messages in the
database. When user types something in the "message" field and submits the
form, the "message" should be saved to a table in SQLite. AND After the message is saved, user should come back to the page with the form and message list.
I am stuck at a POINT
I am not being able to SUBMIT the message
My page do retrieve messages from the database which is already stored in the database while I created it.
But Can SOMEONE please guide for the codes to SUBMIT the message filled in the form.
My message.html code is:
{% extends "template.html "%}
{% block content %}
<h2>You are in the Message Page</h2>
<br/>
<p><h4>In this page, You can view the Existing Messages and can also Submit your own message.</h4></p>
<br/><br/>
<h3>Enter Your Message:</h3><br/>
<form action="" method='POST'>
<dl>
<dt>Message:
<dd><input type="text" name=msg_msg maxlength=80 style="width:300px">*Maximum Length = 80
</dl>
<input type=submit value="Submit Message">
</form>
<h3>The Existing Messages:</h3>
{% for item in message %}
Msg_ID: <B>"{{ item.msg_id }}"</B><br/>Message: {{ item.msg_msg }} <br/><br/>
{% endfor %}
{% endblock %}
and my routes.py code for this is:
#app.route('/message')
def message():
g.db = connect_db()
cur = g.db.execute('select msg_id, msg_msg from msg')
message = [dict(msg_id=row[0], msg_msg=row[1]) for row in cur.fetchall()]
g.db.close()
return render_template('message.html', message=message)
#app.route('/message', methods=['GET', 'POST'])
def message_1():
error = None
if request.method == 'POST':
for request.form['input_msg'] = text:
g.db = connect_db()
cur = g.db.execute('insert into msg_msg from msg')
message = [dict(msg_id=row[0], msg_msg=row[1]) for row in cur.fetchall()]
g.db.close()
return render_template('message.html', message=message)
#error = 'Invalid Entry, Please Try Again.'
else:
# session['logged_in'] = True
return redirect(url_for('message'))
return render_template('message.html' , error=error)

Use 1 message view
#app.route('/message', methods=['GET', 'POST'])
def message():
cur = db.execute('select id,msg from msg_msg')
message = [dict(msg_id=row[0], msg_msg=row[1]) for row in cur.fetchall()]
if request.method == 'POST':
g.db = connect_db()
cur = g.db.execute('insert into msg_msg (msg) values (?)',request.form['input_msg'])
message = [dict(msg_id=row[0], msg_msg=row[1]) for row in cur.fetchall()]
g.db.close()
return render_template('message.html' , message = message)
message.html
{% extends "template.html "%}
{% block content %}
<h2>You are in the Message Page</h2>
<br/>
<p><h4>In this page, You can view the Existing Messages and can also Submit your own message.</h4></p>
<br/><br/>
<h3>Enter Your Message:</h3><br/>
<form action={{ url_for('message') }} method='POST'>
<dl>
<dt>Message:
<dd><input type="text" name=msg_msg maxlength=80 style="width:300px">
</dl>
<input type=submit value="Submit Message">
</form>
<h3>The Existing Messages:</h3>
{% for item in message %}
Msg_ID: <B>"{{ item.msg_id }}"</B><br/>Message: {{ item.msg_msg }} <br/><br/>
{% endfor %}
{% endblock %}

Related

django redirect to form view and autofill with previously entered values

I have following scenario.
User fills out a form
If the user clicks the "continue" button and the form is valid the user will be redirected to a summary view
In the summary view the user checks the input again. He can either continue or go back.
If he continues the data will be saved in the database, if he goes back he can edit the form.
Since in step 4 the user is at the view summary I have to redirect him to the home view. I don´t want the user to fill out the entire form again, the previously entered data should be autofilled if he goes back.
Something special: I am using django-tagify2 for one input in the form to get tags rather then text. If the user goes back the tags should be rendered correctly in the tagify specific form.
So here are my files:
home.html
{% extends "messenger/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="message-container">
<form method="POST" autocomplete="off">
{% csrf_token %}
{{ form|crispy }}
<button name="sendmessage" class="btn btn-outline-info" type="submit">Continue</button>
</form>
</div>
{% endblock content %}
summary.html
{% extends "messenger/base.html" %}
{% block content %}
<h4>Zusammenfassung</h4>
<p><b>Empfänger: </b>{{ receiver }}</p>
<br>
<p><b>Betreff: </b>{{ subject }}</p>
<br>
<p><b>Nachricht: </b>{{ message }}</p>
<button>Edit</button>
<button>Continue</button>
{% endblock content %}
home view
#login_required(login_url='login')
def home(request):
if request.method == 'POST' and 'sendmessage' in request.POST:
message_form = MessageForm(request.POST)
if message_form.is_valid():
receiver_list = message_form['receiver'].value().split(';')
subject = message_form['subject'].value()
message = message_form['textmessage'].value()
#create sessions and send data to next view
session_receiver = receiver_list
request.session['session_receiver'] = session_receiver
session_subject = subject
request.session['session_subject'] = session_subject
session_message = message
request.session['session_message'] = session_message
return redirect('summary')
else:
message_form = MessageForm()
return render(request, 'messenger/home.html', {'form': message_form})
summary view
def summary(request):
receiver = request.session.get('session_receiver')
subject = request.session.get('session_subject')
message = request.session.get('session_message')
return render(request, 'messenger/summary.html', {'receiver':receiver,
'subject':subject,
'message':message})
So what is the best way to do this?
Can I use the session variables to set the fields in the form?
I don´t want to change the logic in the app. I want a home/summary/success view/template where I can loop as long is I want between home and summary until the user is happy with his entered form data
How about checking request.session when there is get request to home view? Then you can bind message_form = MessageForm() to session data.
You can check out htmx and django-htmx. You can do what you want easily without session by swapping HTML with context.
I played around with the session values and views and finally got a way to redirect to other views with prefilled form fields based on session values.
#login_required(login_url='login')
def home(request):
if request.method == 'POST' and 'sendmessage' in request.POST:
message_form = MessageForm(request.POST)
if message_form.is_valid():
ad_group = message_form['ad_group'].value().split(';')
ad_user = message_form['ad_user'].value().split(';')
subject = message_form['subject'].value()
message = message_form['textmessage'].value()
#create sessions and send data to next view
session_ad_group = ad_group
request.session['session_ad_group'] = session_ad_group
session_ad_user = ad_user
request.session['session_ad_user'] = session_ad_user
session_subject = subject
request.session['session_subject'] = session_subject
session_message = message
request.session['session_message'] = session_message
return redirect('summary')
else:
if request.session.get('session_subject'):
message_form = MessageForm(initial={'ad_group': request.session.get('session_ad_group'),
'ad_user': request.session.get('session_ad_user'),
'subject': request.session.get('session_subject'),
'textmessage': request.session.get('session_message')})
return render(request, 'messenger/home.html', {'form': message_form})
else:
message_form = MessageForm()
return render(request, 'messenger/home.html', {'form': message_form})
def summary(request):
ad_group = request.session.get('session_ad_group')
ad_user = request.session.get('session_ad_user')
subject = request.session.get('session_subject')
message = request.session.get('session_message')
if request.method == 'POST' and 'edit' in request.POST:
message_form = MessageForm(initial={'ad_group':ad_group, 'ad_user': ad_user,
'subject':subject, 'textmessage':message})
return render(request, 'messenger/home.html', {'form': message_form})
return render(request, 'messenger/summary.html', {'ad_group':ad_group,
'ad_user': ad_user,
'subject':subject,
'message':message})
Template
{% extends "messenger/base.html" %}
{% block content %}
<h2>Zusammenfassung</h2>
<div class="border-top pt-3">
<p><b>AD-Gruppe: </b>{{ ad_group }}</p>
<p><b>AD-User: </b>{{ ad_user }}</p>
<br>
<p><b>Betreff: </b>{{ subject }}</p>
<br>
<p><b>Nachricht: </b>{{ message }}</p>
<div class="buttoncontainer">
<form name="edit" action="" method="post">
{% csrf_token %}
<button class="btn edit_btn" formaction="{% url 'messenger-home' %}">Zurück</button>
</form>
<form name="senden" action="" method="post">
{% csrf_token %}
<button class="btn continue_btn" formaction="{% url 'send_messages' %}">Nachricht senden</button>
</form>
</div>
</div>
{% endblock content %}

How do I show an error message when I have an invalid log in?

I'm working on a web app right now and I don't know how to display an error message when the user types in an invalid log in name. How do I go about this?
this is my login.html
{% block body %}
<h1>Login</h1>
{% if error %}
<p>Invalid Username</p>
{% endif %}
<form method="POST" action="{{ url_for('login') }}">
<input type="text" name="username" placeholder="Your Username">
<input type="submit" value="Submit">
</form>
<a href='{{variable6}}'>Sign Up</a>
{% endblock %}
this is my app.py
#app.route("/login", methods=["GET", "POST"])
def login():
if flask.request.method == "GET":
return flask.render_template("login.html")
if flask.request.method == "POST":
username = flask.request.form["username"]
cursor.execute(
"SELECT user_name FROM public.users WHERE user_name = %s", [username]
)
results = cursor.fetchall()
if len(results) != 0: # if a user exists, "log" them in
return flask.redirect(flask.url_for("main"))
else:
return flask.render_template("login.html")
I believe that your problem is that you are not defining what the "error" variable is, you could fix this by when you are returning the render_template in the last line of app.py, adding error=True, leaving you with this as your last line for app.py.
return flask.render_template("login.html", error=True)
As otherwise Jinja (the templating language you used in login.html) would not know what error and would get the type None as the value of error in the {% if error %} statement in login.html and since None is not equal to true, it would skip over the code you want to run.
Hope this helps :)

Issue with csrf_token while using Flask and WTForms

I'm trying to set up a basic "Contact" form for my website, which will basically take in values and then put them into a CSV file. The issue I'm having is that the entries cannot be validated cause they're missing a csrf_token?
Here's the relevant code from my app.py:
#app.route('/contact_end', methods=['POST'])
def handle_contact():
form = ContactForm()
print(form.name.data)
if form.validate_on_submit():
print("yup")
with open('data/messages.csv', 'a') as f:
print("oh shit")
writer = csv.writer(f)
writer.writerow([form.name.data, form.email.data, form.message.data])
print("waddup")
return redirect(url_for('contact_handler.html'), name=form.name.data)
print(form.errors)
return render_template('contact.html', form=form)
It skips over the if statement as it never ends out printing the "yup", and instead it prints out the error:
{'csrf_token': ['The CSRF token is missing.']}
The template that this connects to is:
{% extends "base_template.html" %}
{% block title %}Contact us {% endblock %}
{% block content %}
<p>Feel free to use the contact form below to send us any questions you might have.</p></br>
<form action="/contact_end" method="post">
{{ form.csrf_token }}
<label>Your Name <input type="text" name="name"/></label></br>
<label>Your Email <input type="text" name="email"/></label></br>
<label>Your Name <textarea name="message"></textarea></label></br>
<button type="submit">Send</button>
<button type="reset">Clear</button>
</form>
{% endblock %}
I've tried messing with form.csrf_token and .hidden_tags(), but with no success.
As well, this is the initial part of app.py that brings you to the page in the first place, the one above is the endpoint for the form:
#app.route('/contact')
def contact():
return render_template('contact.html', form=form)
Finally, here's my ContactForm class:
class ContactForm(FlaskForm):
print("yep")
name = StringField('Name', validators=[InputRequired()])
email = EmailField('Email', validators=[InputRequired(), Email()])
message = TextAreaField('Message', validators=[InputRequired()])
I've made sure to set my secret key, as well. Anyone have any idea why this isn't working? Many thanks.
You still need to create the form instance in your contact() function:
#app.route('/contact')
def contact():
form = ContactForm()
return render_template('contact.html', form=form)

Form Validation message not being displayed - Flask

I'm having trouble getting error messages in Flask to render.
I suspect this is related to the blueprints. Previously, the logic seen in views.py was in the users blueprint, but I've since ported it over to the main blueprint. Anyhow, since then, I am unable to get error messages to render.
The specific line I think I'm having trouble with is:
self.email.errors.append("This Email is already registered")
project/main/views.py
#main_blueprint.route('/', methods=['GET', 'POST'])
#main_blueprint.route('/<referrer>', methods=['GET', 'POST'])
def home(referrer=None):
form = RegisterForm(request.form)
# prepares response
resp = make_response(render_template('main/index.html', form=form))
if form.validate_on_submit():
do_stuff()
return resp
project/main/index.html
<h1>Please Register</h1>
<br>
<form class="" role="form" method="post" action="">
{{ form.csrf_token }}
{{ form.email(placeholder="email") }}
<span class="error">
{% if form.email.errors %}
{% for error in form.email.errors %}
{{ error }}
{% endfor %}
{% endif %}
</span>
</p>
<button class="btn btn-success" type="submit">Register!</button>
<br><br>
<p>Already have an account? Sign in.</p>
</form>
project/user/forms.py
class RegisterForm(Form):
email = TextField(
'email',
validators=[DataRequired(), Email(message=None), Length(min=6, max=40)])
def validate(self):
print "validating"
initial_validation = super(RegisterForm, self).validate()
if not initial_validation:
print "not initial validation"
return False
user = User.query.filter_by(email=self.email.data).first()
print user
if user:
print self
print "error, email already registered"
self.email.errors.append("This Email is already registered")
return False
return True
When attempting to debug, the value for 'print user' from this is:
project.user.forms.RegisterForm object at 0x7fa436807698
Got it to work, #glls, you were correct.Rewrote the code as:
#main_blueprint.route('/', methods=['GET', 'POST'])
#main_blueprint.route('/<referrer>', methods=['GET', 'POST'])
def home(referrer=None):
# prepares response
resp = make_response(render_template('main/index.html', form=form))
if form.validate_on_submit():
do_stuff()
form = RegisterForm(request.form)
return resp

Flask and Python how to make search engine for data from mysql database

I want to make some kind of search engine for student's information by entering their first name in html input field, but I have some troubles with my code. I am using Flask with Python though.
Here is my project.py code:
#app.route('/search', methods=['GET', 'POST'])
def search():
if request.method == "POST":
db = MySQLdb.connect(user="root", passwd="", db="cs324", host="127.0.0.1")
c=db.cursor()
c.executemany('''select * from student where name = %s''', request.form['search'])
for r in c.fetchall():
print r[0],r[1],r[2]
return redirect(url_for('search'))
return render_template('search.html')
Here is my search.html code:
{% extends "hello.html" %}
{% block content %}
<div class="search">
<form action="" method=post>
<input type=text name=search value="{{ request.form.search}}"></br>
<div class="actions"><input type=submit value="Search"></div>
</form>
</div>
{% for message in get_flashed_messages() %}
<div class=flash>
{{ message }}
</div>
{% endfor %}
{% endblock %}
When I hit Search button nothing happens, I checked database it has some data in it so it is not empty, I can't find where am I making a mistake, please help?
Make sure, action point to proper url
I think you render the form with wrong action for submitting the form.
Your version is using action="" and I guess, it shall be action="/search"
So your template shall be changed like:
{% extends "hello.html" %}
{% block content %}
<div class="search">
<form action="/search" method=post>
<input type=text name=search value="{{ request.form.search}}"></br>
<div class="actions"><input type=submit value="Search"></div>
</form>
</div>
{% for message in get_flashed_messages() %}
<div class=flash>
{{ message }}
</div>
{% endfor %}
{% endblock %}
Do not redirect out of your result
Your existing code is processing POST, but within first loop it ends up returning with redirect
#app.route('/search', methods=['GET', 'POST'])
def search():
if request.method == "POST":
db = MySQLdb.connect(user="root", passwd="", db="cs324", host="127.0.0.1")
c=db.cursor()
c.executemany('''select * from student where name = %s''', request.form['search'])
for r in c.fetchall():
print r[0],r[1],r[2]
return redirect(url_for('search')) # <- Here you jump away from whatever result you create
return render_template('search.html')
Do render your template for final report
Your code does not show in POST branch any attempt to render what you have found in the database.
Instead of print r[0], r[1]... you shall call render_template()
Something like this
#app.route('/search', methods=['GET', 'POST'])
def search():
if request.method == "POST":
db = MySQLdb.connect(user="root", passwd="", db="cs324", host="127.0.0.1")
c=db.cursor()
c.executemany('''select * from student where name = %s''', request.form['search'])
return render_template("results.html", records=c.fetchall())
return render_template('search.html')

Categories

Resources