ValueError at /logout/ in Django - django-forms

Views.py
def logoutUser(request):
logout(request)
return HttpResponseRedirect('login')
urls.py
path('login/',views.Login,name='login'),
path('logout/',views.logout,name='logout'),
Html
{% if user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{% url 'logout' %}">Logout</a> </li>
The view django.contrib.auth.logout didn't return an HttpResponse object. It returned None instead.
Exception Location: C:\Users\dheeraj\AppData\Local\Programs\Python\Python38\lib\site-packages\django\core\handlers\base.py in _get_response, line 124
I also tried it using render and change url format ,but unable to understand where i am doing mistake.

I have solved it.
just small changes in url.py
path(r'^logout/',views.logout,name='logout'),

Related

validate_on_submit is not working using WTF Forms

When I registered on the page, I see that are the values getting inserted into the database and it is redirecting me to the Login function as mentioned in the code, but I don't understand why the login page itself is getting redirected every time I tried to login, instead, it should get redirected to the chat function.
I see that index function is working clearly
and also the values are getting inserted into database
But when I tried to login it's not getting redirected to the chat page
When I printed "login_form.validate_on_submit", it is always resulting false, so I could see that there is something wrong with the validate_on_submit function, but I'm not getting what it is.
This is my Login Function inside application.py:
#app.route('/login',methods=["GET","POST"])
def login():
login_form=LoginForm()
print(login_form)
if login_form.validate_on_submit():
user_object=User.query.filter_by(username=login_form.username.data)
login_user(user_object)
return redirect(url_for("chat"))
return render_template("login.html", form=login_form)
This is WTForm_Fields.py:
def invalid_credentials(form, field):
""" Username and password checker """
password = field.data
username = form.username.data
# Check username is invalid
user_data = User.query.filter_by(username=username).first()
print(user_data)
if user_data is None:
raise ValidationError("Username or password is incorrect")
# Check password in invalid
elif not pbkdf2_sha256.verify(password, user_data.hashed_pswd):
raise ValidationError("Username or password is incorrect")
class LoginForm(FlaskForm):
"""login form"""
username=StringField('username_label',validators=[InputRequired(message="username required")])
password=PasswordField('password_label',validators=[InputRequired(message="Password Required"),invalid_credentials])
This is login.html:
{% from 'form_helper.html' import displayField %}
{% extends 'prelogin-template.html'%}
{%block title%}Login{%endblock%}
{%block content%}
<h2>Login now!</h2>
<p>Enter your username/Password to start!!</p>
<form action="{{ url_for('login') }}",method='POST'>
{{displayField(form.username,"Username",autocomplete='off',autofocus=true)}}
{{displayField(form.password,"Password")}}
<div class="form-group">
<input type="submit" value="Login" class="btn btn-warning">
</div>
{{ form.crsf_token }}
</form>
{%endblock%}
This is prelogin-template.html:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>{%block title%}{%endblock%}-Let's Chat </title>
</head>
<body>
{% with messages=get_flashed_messages(with_categories=true) %}
{% if messages %}
Category:{{ messages[0][0] }}
{{messages[0][1]}}
{% endif %}
{% endwith %}
{%block content%}
{%endblock%}
</body>
</html>
This is form_helper.html:
{% macro displayField(fieldName,placeholderValue) %}
<div class='form-group'>
{{fieldName(class="form_control",placeholder=placeholderValue,**kwargs)}}
<ul class="formError">
{% for error in fieldName.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</div>
{% endmacro %}
The way I see it, there are no problems in your form_helper.html, prelogin-template.html, login.html and WTForm_Fields.py files. However, there is an issue in your Login Function. I think that Database query error has occurred. One suggestion is to simply add .first() at the end of the user object. flask_login sometimes does not log a user in when you provide flask_sqlalchemy.BaseQuery object as the parameter.
Try doing this in Login Function inside application.py:
#app.route('/login',methods=["GET","POST"])
def login():
login_form=LoginForm()
print(login_form)
if login_form.validate_on_submit():
user_object=User.query.filter_by(username=login_form.username.data).first() #<--add here
login_user(user_object)
return redirect(url_for("chat"))
return render_template("login.html", form=login_form)
This should smoothly log a user in.

Laravel calling controller function from blade file not working

I have a Laravel project where I'm trying to call a controller function from blade file called nav.blade.php, but I'm getting following error:
syntax error, unexpected fully qualified name
"\App\Http\Controllers\ProductC...", expecting ":".
nav.blade.php
{{ use \App\Http\Controllers\ProductController; }}
<div class="container">
<ul class="navbar-nav mr-auto">
{{ $is_admin = ProductController::isAdmin(); }}
#if($is_admin == "admin")
<li class="nav-item">
<a class="nav-link" href="/posts">Admin</a>
</li>
#endif
</ul>
</div>
ProductsController.php
public static function isAdmin()
{
$user_id = Auth::id();
$user = User::findOrFail($user_id);
$is_admin = $user->role;
if($is_admin==="admin"){
return "admin";
}elseif($is_admin==="moderator"){
return "moderator";
}else{
return "user";
}
}
You access the static controller function from the blade template.
<?php
$isAdmin= App\Http\Controllers\ProductController::isAdmin();
?>
{{ }} are used to echo anything you want. If you want to import a class, one solution is to do like the following:
<?php
use \App\Http\Controllers\ProductController;
$is_admin = ProductController::isAdmin();
?>
<div class="container">
<ul class="navbar-nav mr-auto">
#if($is_admin == "admin")
<li class="nav-item">
<a class="nav-link" href="/posts">Admin</a>
</li>
#endif
</ul>
</div>
But this isn't a best practice I recommend you to move isAdmin() method from ProductController and set it as global function of your system so you can directly access it from your view without importing a controller.
Never EVER use a controller in a Blade. That is not good in any way and would require me a lot of explanation that is already in some blogs...
A controller is ONLY used for accessing something through a URL, do something and done, it is not a Service class where you do business logic anywhere you want.
So, move that method to a Service class (do not confuse with Service Provider) and use it in the blade. It would still be better to pass that variable to the view and not using any class just for that...

spring boot thymleaf i am trying to use conditional if in tymeleaf and tie it to a controller class to return true or false no pojo needed

i have a nav bar that i am using as a template.. see pic
if i am on any of the tabs then i want home to show. But if i am on the home page i don't want Home tab to show its redundant. i cant seem to figure out how to write the thymleaf code..
i have something like this the first line is what i am interested in fixing... can you please help with the controller part also i am sure i can do a model.addAttribute line in each method call and set the isActive to true except the home method i can set the isActive to false ... thank you
li th:text="${isActive} ? 'Home : "
<li th:text="${isActive} ? '<a th:href="#{/}">Home</a> : " </li>
<li><a th:href="#{/about}">About</a></li>
<li class="auctions">Auctions <i class="fas fa-caret-down"></i>
<ul>
<li>Current Auctions</li>
<li>Register</li>
</ul>
</li>
<li><a th:href="#{/contact}">Contact</a></li>
<li><a th:href="#{/locations}">Locations</a></li>
you can use this in controller:
model.addAttribute("isActive",true);
and use this in html code:
<li th:if="${isActive == null || !isActive}"><a th:href="#{/}">Home</a></li>
read more about Conditionals in Thymeleaf and simple conditionals if and unless

Updating a SQL Alchemy list without reloading the page?

I am working on a small Flask app and the user is able to update a list of items via using a form to submit some data.
I am currently using SQL Alchemy as the ORM for my database and using the list in my template to display the items. I want to update it so that when the list is updated. The page is updated without the user having to reload the page.
I have tried this with AJAX using the below script but the update is not occurring.
$(document).ready(function(){
$('form').on('submit',function (e) {
$.ajax({
type: 'post',
url: '/todo',
data: $('#todoInput').serialize(),
success: function (q) {
console.log(q);
}
});
e.preventDefault();
});
}
My template:
{% extends "base.html" %}
{% block script %}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="{{ url_for('static', filename='js/custom.js') }}"></script>
{% endblock %}
{% block content %}
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<div class="alert alert-success" role="alert">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
<div class="row justify-content-md-center">
<div class="col-md-auto">
<h1>What needs to be done today?</h1>
</div>
</div>
<div class="row justify-content-md-center">
<div class="col-md-auto">
<form action="" method="post">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.todo (id="todoInput") }}
{{ form.submit (class_="btn btn-primary btn-sm") }}
</div>
</form>
<div id="todoList">
<ul class="list-group">
{% for todo in todos %}
<li class="list-group-item d-flex justify-content-between align-items-center">
{{ todo.body }}
<button type="button" class="close" aria-label="Close"><span aria-hidden="true">×</span></button>
</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endblock %}
Model:
from datetime import datetime
from app import db, login
from flask_login import UserMixin
from werkzeug.security import generate_password_hash, check_password_hash
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
password_hash = db.Column(db.String(128))
todos = db.relationship('Todo', backref='owner', lazy='dynamic')
def __repr__(self):
return '<User {}>'.format(self.username)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
#login.user_loader
def load_user(id):
return User.query.get(int(id))
class Todo(db.Model):
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
def __repr__(self):
return '<Todo {}>'.format(self.body)
Route:
#app.route('/todo', methods=['GET', 'POST'])
def todo():
if current_user.is_authenticated:
form = TodoForm()
todos = current_user.todos.order_by(Todo.timestamp.desc()).all()
if form.validate_on_submit():
new_todo = Todo(body=form.todo.data, owner=current_user)
db.session.add(new_todo)
db.session.commit()
flash('Todo added')
todos = current_user.todos.order_by(Todo.timestamp.desc()).all()
return render_template('todo.html', form=form, todos=todos)
return render_template('todo.html', form=form, todos=todos)
flash('You first need to login or register')
return redirect(url_for('index'))
The todos list is what im trying to update. But it just reloads the page :/
You need to do two things. Firstly you need to be sure that your database is updated. That means that your form was submitted successfully. This can be done by submitting the form manually via an ajax call. This is more or less what you did. Did you check, whether your backend receives the form-submission and updates the database?
Secondly you need to update the html in the browser. Normally the page is refreshed automatically if your form is submitted. If you dont want a page reload, you need to add some client-side logic, to ensure that the page is updated. This can easily be done with a little bit of javascript.
Edit:
Your custom js might be missing }); at the end. Or did you just forget to post it here?

Refresh page without reload. Wagtail

Where can i put ajax get data code in Wagtail? I have following page model:
class ScreencastPage(Page):
content_panels = Page.content_panels + [
InlinePanel(
'groupstage_screencast_relationship', label="Choose Teams",
panels=None, max_num=2),
]
parent_page_types = ['home.HomePage']
def matches(self):
matches = [
n.match for n in self.groupstage_screencast_relationship.all()
]
return matches
And my template:
{% for spiel in page.matches %}
{% if forloop.first == forloop.last %}
<div id="fullscreen">
<ul class="ulup">
<li class="logo_bg first_team">{% image spiel.team_1.team_logo width-400 class="logo" %}<p>{{spiel.team_1.title}}</p></li>
<li class="first_team_score">{{ spiel.team_1_total_score }}</li>
<li class="colons">:</li>
<li class="second_team_score">{{ spiel.team_2_total_score }}</li>
<li class="logo_bg second_team">{% image spiel.team_2.team_logo width-400 class="logo" %}<p>{{spiel.team_2.title}}</p></li>
</ul>
</div>
{% endif %}
{% endfor %}
I started writing js. Just exaple:
$(document).ready(function() {
setInterval(function(){
$.ajax({
type: "GET",
url: {% pageurl page %},
data: {},
success: function(data) {
console.log(data);
$(".first_team_score").contents()[0].textContent = data.team_1_total_score;
$(".second_team_score").contents()[0].textContent = data.team_2_total_score;
}
})
}, 10000);
});
The idea is that the page will automatically update the value of <li class="first_team_score">{{ spiel.team_1_total_score }}</li> and <li class="second_team_score">{{ spiel.team_2_total_score }}</li> without reloading the page.
I found here great example, but they using view.py
We also need to write a new view.py or have wagtail some method for that?
UPDATE
Thanks #Ben-Dickinson from wagtail slack community. He shared a link to the documentation where it is indicated how it's possible to solve such a problem.
I have here another problem. How to convert matches to json?
To catch ajax requests we can use the Page serve() method and use if request.is_ajax():. So I did following inside my ScreencastPage(Page):
def serve(self, request):
if request.is_ajax():
result = [
{
'team_1_name': match.team_1.title,
'team_1_score': match.team_1_total_score,
'team_2_name': match.team_2.title,
'team_2_score': match.team_2_total_score,
}
for match in self.matches()
]
json_output = json.dumps(result)
return HttpResponse(json_output)
else:
return super(ScreencastPage, self).serve(request)
This code from above was the result of help from #gasman, this topic you can find here Converting value to json inside serve method
The final result of the HTML/JS code is:
<div id="match1">
<ul class="ulup">
<li class="logo_bg first_team">{% image spiel.team_1.team_logo width-400 class="logo" %}<p>{{spiel.team_1.title}}</p></li>
<li class="first_team_score">{{ spiel.team_1_total_score }}</li>
<li class="colons">:</li>
<li class="second_team_score">{{ spiel.team_2_total_score }}</li>
<li class="logo_bg second_team">{% image spiel.team_2.team_logo width-400 class="logo" %}<p>{{spiel.team_2.title}}</p></li>
</ul>
</div>
JS:
$(document).ready(function() {
setInterval(function(){
$.ajax({
type: "GET",
url: {% pageurl page %},
dataType: 'json',
success: function(data) {
$("#match1 .first_team").contents()[0].textContent = data[0]["team_1_name"];
$(".first_team_score").contents()[0].textContent = data[0]["team_1_score"];
$("#match1 .second_team").contents()[0].textContent = data[0]["team_2_name"];
$(".second_team_score").contents()[0].textContent = data[0]["team_2_score"];
}
})
}, 10000);
});
data[0] is becoz my data returns database of two matches and i need only first one

Resources