I'm making a basic chat app with flask.
I have this page and this piece of code
#app.route('/', methods = ['GET', 'POST'])
def chat():
if request.method == 'POST':
message_content = request.form['content']
message_author = request.form['name']
if message_content:
new_message = Message(content = message_content, author = message_author)
db.session.add(new_message)
db.session.commit()
return redirect('/')
else:
all_messages = Message.query.order_by(Message.date.desc()).all()
return render_template('chat.html', posts=all_messages)
and I would like to every time I hit the "Send" button it takes the information of the input in the header and the info of the message. So, my question is, can I take the informations of two different forms with only one button ?
Html code (with a bit of jinja 2):
{% block body %}
<!-- Navbar -->
<nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="/">Chat</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav me-auto mb-2 mb-md-0">
</ul>
<form action="/" class="d-flex" method="POST">
FORM THAT CONTAINS THE NAME -- > <input class="form-control me-2" type="search" id="name" placeholder="Name" value="{% if message_author %}{{ message_author }}{% else %}Unknown{% endif %}" aria-label="Search">
<!-- <button class="btn btn-outline-success" type="submit">Save</button> -->
</form>
</div>
</div>
</nav>
<!-- New message form -->
<br>
<div class="bg-light p-5 rounded">
<h2 class="createPost">New message </h2>
<form action="/" method="POST">
<input type="text" name="content" id="content" class="createPost">
<br>
<input type="submit" value="Send" class="btn btn-outline-dark" id="submit">
</form>
</div>
<hr>
<!-- Display messages -->
{% for post in posts %}
<div class="">
{% if post.author %}
{% if post.date %}
<small class="">{{ post.date.replace(microsecond=0) }} - {{ post.author }} : </small>
{% else %}
<small class="">{{ post.author }}</small>
{% endif %}
{% else %}
{% if post.date %}
<small class="">{{ post.date }} - Unkown : </small>
{% else %}
<small class="">N/A - Unkown</small>
{% endif %}
{% endif %}
<p class="">{{ post.content }}</p>
Delete
<!-- Edit -->
<hr>
</div>
{% endfor %}
{% endblock %}
You could create a hidden input inside your send form and on submit copy the value (with javascript) of the input from the other form.
<input id="name" type="text" value="" name="name" class="btn btn-outline-dark" id="submit">
<form>
<input id="hiddenName" type="hidden" value="" name="name" class="btn btn-outline-dark" >
<input onclick="document.getElementById('hiddenName').value = document.getElementById('name').value" type="button" value="Send" class="btn btn-outline-dark" id="submit">
</form>
Related
Need to make the UI more ordered, can i have indexing for the forms in formset or access the form ID?
<div class="card">
<div class="card-body">
<div id="form-container">
{% csrf_token %}
{{ formset1.management_form }}
{% for form in formset1 %}
<div class="test-form">
{% crispy form %}
</div>
{% endfor %}
<button id="add-form" type="button" class="btn btn-primary">Add Another Request
</button>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</div>
Yeah, you can use forloop.counter within your forloop like this, can assign the value to name or id
<div class="card">
<div class="card-body">
<div id="form-container">
{% csrf_token %}
{{ formset1.management_form }}
{% for form in formset1 %}
{% crispy form %}
</div>
{% endfor %}
<button id="add-form" type="button" class="btn btn-primary"> Add Another Request </button>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</div>
I have a problem with displaying errors on the template for login page. I am using the Login built in view and I made a custom form which inherits from AuthenticationForm and I tried to override the clean() method but if the username or password is not correct is not displaying any ValidationErorr message. Any help?
I created a custom view because I need to inherit from a custom mixin for some restrictions.
my view:
class UserLoginView(IsAuthenticatedMixin, LoginView):
template_name = 'home/auth/login.html'
authentication_form = UserLoginForm
my form:
class UserLoginForm(AuthenticationForm):
username = forms.CharField(widget=forms.TextInput())
password = forms.CharField(widget=forms.PasswordInput())
def clean(self):
cleaned_data = super().clean()
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username is not None and password:
login = authenticate(self.request, username=username, password=password)
if login is None:
raise ValidationError('The username or password are incorrect')
return self.cleaned_data
url:
path('auth/login/', UserLoginView.as_view(), name='login'),
my template:
{% extends 'home/auth/base.html' %}
{% load widget_tweaks %}
{% block content %}
<!-- Outer Row -->
<div class="row justify-content-center">
<div class="col-xl-10 col-lg-12 col-md-9">
<div class="card o-hidden border-0 shadow-lg my-5">
<div class="card-body p-0">
<div class="row">
<div class="col-lg-6 d-none d-lg-block bg-login-image"></div>
<div class="col-lg-6">
<div class="p-5">
<div class="text-center">
<h1 class="h4 text-gray-900 mb-4">Welcome Back!</h1>
</div>
<form class="user" method="POST">
{% csrf_token %}
<div class="form-group">
{% for error in form.non_field.errors %}
<div class="invalid-feedback">
{{ error }}
</div>
{% endfor %}
{% render_field form.username class="form-control form-control-user" id="exampleInputEmail" aria-describedby="emailHelp" placeholder="Enter Username..." %}
</div>
<div class="form-group">
{% render_field form.password class="form-control form-control-user" id="exampleInputPassword" placeholder="Password" %}
</div>
<div class="form-group">
<div class="custom-control custom-checkbox small">
<input type="checkbox" class="custom-control-input" id="customCheck">
<label class="custom-control-label" for="customCheck">Remember Me</label>
</div>
</div>
<input type="submit" name="Login" class="btn btn-primary btn-user btn-block" value="Login">
<hr>
<a href="index.html" class="btn btn-google btn-user btn-block">
<i class="fab fa-google fa-fw"></i> Login with Google
</a>
<a href="index.html" class="btn btn-facebook btn-user btn-block">
<i class="fab fa-facebook-f fa-fw"></i> Login with Facebook
</a>
</form>
<hr>
<div class="text-center">
<a class="small" href="forgot-password.html">Forgot Password?</a>
</div>
<div class="text-center">
<a class="small" href="{% url 'register' %}">Create an Account!</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
View.py
if req.method == 'POST':
df = DocumentForm.objects.filter(document_id=id)
logging.info('LOG: I am here')
if df.exists():
for d in df:
description = req.POST['{}'.format(d.description, False)]
displayName = req.POST['{}'.format(d.displayName, False)]
df.update(displayName=displayName, description=description)
return redirect('/adboard/upd')
HTML File
<form class="needs-validation" action="{{id}}" method="POST" enctype="multipart/form-data" novalidate>
{% csrf_token %}
<div class="row mt-3 mb-3"></div>
{% if messages %}
<div class="alert alert-danger" role="alert">
{% for message in messages %}
{{ message }}
{% endfor %}
</div>
{% endif %}
{% for df in data %}
<div class="form-group">
<small class="text-muted bold-label m-lower">{{{df.field}}}</small>
<label for="validationCustom01">{{df.displayName}}</label>
<input type="text" class="form-control" id="validationCustom01" name="{{df.displayName}}" value="{{df.displayName}}" placeholder="Enter Display Name">
<label for="validationCustom01">{{df.description}}</label>
<input type="text" class="form-control" id="validationCustom01" name="{{df.description}}" value="{{df.description}}" placeholder="Enter description">
<div class="invalid-feedback">
Please enter required fileds.
</div>
<!-- <div class="valid-feedback">
Looks good!
</div> -->
</div>
{% endfor %}
<button type="submit" class="btn btn-primary btn-red btn-block">SAVE</button>
</form>
What I am trying to achieve is.
Pass a variable form to the user to fill
And I get the result.
I can't tell what the input id/name would be because it's a variable.
But I am finding it difficult getting the value from the view.py file.
change
req.POST['{}'.format(d.description, False)]
to
req.POST.get('{}'.format(d.description, False))
I am creating a login page using django but it does not show any messages when I enter wrong passwords or email addresses. I've also checked other messages but it didn't help.
login.html
<div class="right">
<h2>Login</h2>
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }}">
{{ message }}
</div>
{% endfor %}
{% endif %}
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<div class="field">
<div class="label">Email or Username</div>
<input type="text" name="username" id="username" class="form-control">
</div>
<div class="field">
<div class="label">Password</div>
<input type="password" name="password" id="password" class="form-control">
</div>
<button class="login" type="submit">LOGIN</button>
</fieldset>
</form>
<div class="sign_up">
<small>Don’t have an account yet?</small>
<a class="signup" href="{% url 'register' %}">SIGN UP</a>
</div>
</div>
urls.py has this path for the login page(I have imported all the necessary classes):
path('login/', auth_views.LoginView.as_view(template_name='users/login.html') , name='login'),
But the messages are shown when I use this form|crispy in login.html
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Login</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Sign In</button>
</div>
</form>
<div class="border-top pt-3">
<small class="muted-text">
Want a new Account? <a class="ml-1" href="{% url 'register' %}">Sign Up</a>
</small>
</div>
</div>
Here you used LoginView using form it will return it will show you error because of {{ form|crispy }} template tag render form and fields along with field.errors and field.non_field_error.
That's Why you can get an error message if you remove message block in your code it will show you an error there is no connection with form and message in login view
If you want to render you HTML form with CSS you need to explicitly define errors showing block like this
<div class="right">
<h2>Login</h2>
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<div class="field">
<div class="label">Email or Username</div>
<input type="text" name="username" id="username" class="form-control">
</div>
<div class="field">
<div class="label">Password</div>
<input type="password" name="password" id="password" class="form-control">
</div>
<button class="login" type="submit">LOGIN</button>
</fieldset>
</form>
<div class="sign_up">
<small>Don’t have an account yet?</small>
<a class="signup" href="{% url 'register' %}">SIGN UP</a>
</div>
</div>
Here not meaning to use the message framework of Django. Form it self return error in his errors attribute of a form
Hope you satisfied with this answer
so in my home page I extend from 2 things, based on whether or not the user is signed in or not. Then, if they have TRIED to sign in, and failed, i want the inputs to be red:
{% extends extendVar %} #in this case, extendvar=notLoggedIn.html
{% block signIn %}
{% if failure %}
<div class="form-group has-error">
<input type="email" id="email" name="email" placeholder="Email" class="form-control">
</div>
<div class="form-group has-error">
<input type="password" name="password" placeholder="Password" class="form-control">
</div>
{% endif %}
{% endblock %}
notLoggedIn.html then includes from a header page:
<div class="container" style="">
{% include 'header.html' %}
</div>
And this has a block tag:
<div class="header clearfix">
<nav>
<ul class="nav nav-pills pull-left">
<a class="" href="#">
<img alt="Brand" src="{% static 'images/Logo.png' %}" style="height:auto; max-width:470px; margin-top:-22px; margin-bottom:-30px; padding-right:10px;">
</a>
</ul>
<ul class="nav nav-pills pull-right">
<div id="navbar" class="navbar-collapse collapse">
<form class="navbar-form navbar-right" action="{% url 'signIn' %}" method="POST">
{% csrf_token %}
{% block signIn %}
<div class="form-group">
<input type="email" id="email" name="email" placeholder="Email" class="form-control">
</div>
<div class="form-group">
<input type="password" name="password" placeholder="Password" class="form-control">
</div>
<button class="btn btn-primary btn" href="" role="button" style="">Sign in </button>
{% endblock %}
</form>
</div>
</ul>
</nav>
Project name</h3> -->
my only problem is that because i am including header in NotLoggedIn, and then extending that, it doesnt preserve the block tags, and so the signIn blocks are not working. If instead of doing include header, i merely hard-code it, the blocks work perfectly. Any ideas?
According to the django documentation, when you use "include", blocks in the included template are evaluated first, and then substituted in. So in your template, you can't override a block of the included template.
https://docs.djangoproject.com/es/1.9/ref/templates/builtins/#include
Instead of using a block, what if you pass variables down to the include block, to get it to render how you want? For example:
Your template:
{% include 'header.html' with failure=failure %}
header.html:
<div class="form-group {% if failure %}has-error{% endif %}">
<input type="email" id="email" name="email" placeholder="Email" class="form-control">
</div>
<div class="form-group {% if failure %}has-error{% endif %}">
<input type="password" name="password" placeholder="Password" class="form-control">
</div>