I want to get value is selected in ChoiceField - python

I wrote forms.py like
# -*- coding: utf-8 -*-
from django import forms
class InputForm(forms.Form):
name = forms.CharField(max_length=100)
select1 = forms.ChoiceField(widget=forms.RadioSelect,required=False)
select2 = forms.ChoiceField(widget=forms.RadioSelect,required=False)
in html
<div>
{{ f.select1 }}
<label for="select1" dataGoTo="7">select1</label>
{{ f.select2 }}
<label for="select2">select2</label>
</div>
in views.py
def get_data(request):
if request.method == "POST":
form = InputForm(data=request.POST)
if form.is_valid():
name = form.cleaned_data['name']
I want to get value which select1 or select2 is selected.
How should I write in views.py?

You could accomplish this in Javascript using Ajax. Right click the page in your browser and select 'view source'. Figure out what are your form's and select element's id or class. Then in your Javascript (jQuery) right the following:
"use strict";
$(document).ready(function() {
$('form#form_id').on('submit', function(){
// your option elements must have a 'value' attribute
var selectedValue = $('select#select_id').val();
$.ajax({
type:'POST',
url:'your/view/url',
data:{
'selected': selectedValue,
},
dataType: 'json',
success:function(data){
// error handling
if (data['status']==='ok') {
// display success message
} else {
console.log(data);
}
}, // success
}); //ajax
}); // on form submit
}); // document ready
Then in your views.py:
from django.views.generic import View
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import JsonResponse
class SomeAjaxView(LoginRequiredMixin, View):
def post(self, request, *args, **kwargs):
if request.user.is_authenticated:
selected = request.POST.get('selected', None)
if selected:
# do something here
return JsonResponse({'status':'ok'})
else:
return JsonResponse({'status':'ko', 'error': 'Value missing'})
return JsonResponse({'status':'ko', 'error': 'Not authenticated'})
Using Ajax has the benefit of not refreshing the entire page on submit. This is the industry-standard practice nowadays.

Related

Django - "return render(...)" doesn't work in a view that interacts with an ajax request

I want to solve this task: I click a button on the first page and after that my view creates a chat room and redirects me to the chat page.
I decided to use ajax request for this task, but I have a problem, my view works until line return render(request, 'chat/chatroom.html'), the chat room is created, but the chat/chatroom.html page doesn't open, I don't understand why. I have no errors, the return render(request, 'chat/chatroom.html') line does nothing.
My code:
html
<button type="submit" id="chat-button" value="{{advertisement.author.id}}">Write to the author</button>
<script>
$(document).on('click', '#chat-button', function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '{% url "main_app:create-chat" %}',
data: {
send_to_id: $('#chat-button').val(),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
action: 'post'
},
success: function (json) {
},
error: function (xhr, errmsg, err) {
}
});
})
</script>
views.py
from django.contrib.auth import get_user_model
from django.shortcuts import render, redirect, get_object_or_404
from django.db.models import Q
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from chat.models import Thread
User = get_user_model()
#method_decorator(csrf_exempt, name='dispatch')
class CreateChat(View):
def post(self, request):
send_to_id = int(request.POST.get('send_to_id'))
send_to = User.objects.get(id=send_to_id)
auth_user = request.user
final_q = Q(Q(first_person=send_to) & Q(second_person=auth_user)) \
| Q(Q(first_person=auth_user) & Q(second_person=send_to))
thread = Thread.objects.filter(final_q)
if not thread:
Thread.objects.create(first_person=auth_user, second_person=send_to)
return render(request, 'chat/chatroom.html')
urls.py
app_name = 'main_app'
urlpatterns = [
...
path('create_chat', CreateChat.as_view(), name='create-chat')
]
I guess ajax request is not the best solution, but I don't know how to implement this feature in another way.
Thanks for the help.
AJAX always returns to request when it is called, so you can't render it to a new view. so to do this, when the request has been successfully completed, return status 200, etc. when getting the success response in AJAX call. likely in
success: function (json) {
},
redirect it to the desired view. so the code will be like that.
from http.client import OK
from django.http import JsonResponse
#method_decorator(csrf_exempt, name='dispatch')
class CreateChat(View):
def get(self,request):
return render(request, 'chat/chatroom.html')
def post(self, request):
send_to_id = int(request.POST.get('send_to_id'))
send_to = User.objects.get(id=send_to_id)
auth_user = request.user
final_q = Q(Q(first_person=send_to) & Q(second_person=auth_user)) \
| Q(Q(first_person=auth_user) & Q(second_person=send_to))
thread = Thread.objects.filter(final_q)
if not thread:
Thread.objects.create(first_person=auth_user, second_person=send_to)
return JsonResponse({},status=OK)
and the AJAX request will be like that
<script>
$(document).on('click', '#chat-button', function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '{% url "main_app:create-chat" %}',
data: {
send_to_id: $('#chat-button').val(),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
action: 'post'
},
success: function (json) {
location.href = "create-chat" // from here render create-chat
},
error: function (xhr, errmsg, err) {
}
});
})
</script>

Unable to render a template after using fetch in django

I have the following requirement:
Send data to backend using fetch()
receive the data in a view and render another template ( route to a different view)
The following is my code snippet:
JS:
fetch("/addpost", {
method: "POST",
body: JSON.stringify({ value: selecteddict }),
headers: {
"Content-type": "application/json;",
},
})
.then((res) => {
return res.text();
})
.then((text) => {
console.log(text);
});
// the data is being sent successfully
Django View1:
#csrf_exempt
def addpost(request):
if request.method == 'POST':
song = json.loads(request.body.decode('utf-8'))['value']
print(song)
# I want to redirect to another view called createpost that renders a new page
return JsonResponse({'status':201})
return render(request, 'addpost.html')
Django createpost view:
def createpost(request):
return render(request, 'createpost.html')
The view createpost is working fine when given the required path but it is not rendering when it's redirected from addpost
Please suggest a solution to this.
Your addpost view returns as JsonResponse in case of a POST request. If you want to redirect somewhere you need to use redirect() instead of JsonResponse()

Passing dynamically created json url to ajax and display to html page

I am currently working on a system where the login checking of username and password is checked by a python function. If the login details are correct, it will be redirected to a profile page (which i named dashboard). My problem is that my dahsboard/profile route reutrns a json if it is a POST and has also correct login details. I want this json data to be displayed in the html file. I managed to do it but I have used the variables in my jinja template. Although I have accomplished my goal (display the credentials in the html page), I would want it to be handled by ajax. How do I accomplish that?
Below are the codes I have tried so far (passing the data to the jinja variables)
#app.route('/dashboard', methods=['GET', 'POST'])
def dashboard():
if request.method == 'GET':
#get the username passed along with the redirect
data1= getdatafromdb('getdata1',(request.args.get('uname'),))[0][0]
data2= getdatafromdb('getdata2',(code,))[0]
if 'Error' in str(data2):
return jsonify({'status': 'error', 'message': data2[0][0]})
return render_template('dashboard.html', firstname=data2[1],
middleinitial=data2[2],
lastname=data2[3],
contact=data2[4],
code=data2[5],
affiliation=data2[6],
city=data2[7])
elif request.method == 'POST':
return True
return render_template('dashboard.html')
Currently, it appears that you are running your validation process in your /dashboard route, which is not correct if you wish to redirect your user to that very page once their credentials are validated. Instead, you need to create your separate login method with ajax. First, from the / (home) route, render the template that contains the input boxes with ajax:
home.html:
<html>
<body>
<input type='text' name='username' id='username'>
<div class='username_failed'></div>
<input type='password' name='password' id='password'>
<div class='password_failed'></div>
<button type='button' class='login'>Login</button>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('.login').click(function() {
var username = $('#username').val();
var password = $('#password').val();
$.ajax({
url: "/login",
type: "get",
data: {username: username, password:password},
success: function(response) {
if (!response.status){
$('.'+response.issue+'_failed').html('<p>'+response.message+'</p>')
}
else{
window.location.replace('/dashboard'); //redirect to dashboard
}
},
error: function(xhr) {
//Do Something to handle error
}
});
});
});
</script>
</html>
Then, the login route will valid the input dynamically from the ajax in home.html. Previously, you need to create a function to validate the username and password. A possibility is to first check if they are empty, and then query the database:
import typing
def check_if_valid(username:str, password:str) -> typing.Dict[str, typing.Any]:
if not username or not password:
return {'status':False, 'issue':'username' if not username else 'password', 'message':f'{[username, password][username]} cannot be empty'}
_username = check_valid_username_from_db(username)
_password = check_valid_password_from_db(username, password)
if not _username:
return {'status':False, 'issue':'username', 'message':'Invalid username'}
if not _password:
return {'status':False, 'issue':'password', 'message':'Invalid username or password'}
return {'status':True}
#app.route('/login')
def login():
username = flask.requests.args.get('username')
password = flask.requests.args.get('password')
_r = check_if_valid(username, password)
if _r.status:
data2= getdatafromdb('getdata2',(code,))[0]
for i, a in enumerate(['firstname', 'middleinitial', 'lastname', 'contact', 'code', 'affiliation', 'city']):
flask.session[a] = data2[i]
flask.session['user_validated'] = _r.status
return flask.jsonify(_r)
Now, all your user data, if the user was successfully validated, will be stored as part of the session. Now, you can create your dashboard page, first with the html for the dashboard:
dashboard.html:
<html>
<body>
<h1>Welcome, {{firstname}}</h1>
<h4>Your data:</h4>
{%for d in data%}
<span>{{d.title}}: {{d.value}}</span>
{%endfor%}
</body>
</html>
Then, create the dashboard route with user validator:
def isloggedin(f):
def wrapper(*args):
if not flask.session['user_validated']:
return '<p>Not logged in</p>'
return f(*args)
return wrapper
#app.route('/dashboard', methods=['GET'])
#isloggedin
def dashboard():
from collections import namedtuple
headers = ['firstname', 'middleinitial', 'lastname', 'contact', 'code', 'affiliation', 'city']
data = namedtuple('data', ['title', 'value'])
return flask.render_template('dashboard.html', firstname = flask.session['firstname'], data = [data(a, flask.session[a]) for a in headers[1:]])
Lastly, link all together with the home route:
#app.route('/', methods=['GET'])
def home():
return flask.render_template('home.html')

Django: How to Like an Object with Ajax

Here's my View,
class ObjLike(RedirectView):
def get_redirect_url(self, *args, **kwargs):
id = self.kwargs.get('id')
obj = get_object_or_404(Data, id=id)
user = self.request.user
if user.is_authenticated():
if user in obj.likes.all():
obj.likes.remove(user)
else:
obj.likes.add(user)
So after this view how can I redirect user to the same page?
I used "return redirect(request.META['HTTP_REFERER'])" but it gives an error "name 'request' is not defined"
I can't use the get absolute URL method, i'm using this view at several places.
So, how can I do that?
to like an object with ajax calls do this
first in html we want to make a like button:
<button id="like">Like!</button>
the add a script that contain the ajax:
<script>
$(document).ready(function() {
$("#like").click(function(event){
$.ajax({
type:"POST",
url:"{% url 'like' Obj.id %}",
success: function(data){
confirm("liked")
}
});
return false;
});
});
</script>
the we add the like url to the urlpatterns list:
url(r'like/obj/(?P<pk>[0-9]+)/', views.like, name="like"),
adding the view :
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def like(request, pk)
obj = Obj.objects.get(id=pk)
obj.likes += 1
obj.save()
return HttpResponse("liked")
Note: you can customize the like view to check if user liked already

Issues with ajax in django

I'm using ajax in django first times .. I read some tutorials on the net and I'm trying to make a simple form which posts some information via ajax.
Here is my html form
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
function send_request()
{
$.ajax({
type:"POST",
url:"/ajaxredirect/",
});
}
</script>
<button type="button" onclick="send_request();">change content</button>
and it is my view
def Ajaxquery(request):
if request.is_ajax():
return HttpResponse("ok")
else:
return HttpResponse("error")
it does nothing when i am click on change content button in browser.
Any suggestions would be apperciated
Here is basic request/response setup I have made use of. I got the JSONResponse and AjaxResponse mixins from the Django Braces Module. I also made sure to include the following Django CSRF fix to prevent my AJAX request from being treated as a cross site request forgery.
JQuery:
<script type="text/javascript">
function send_request() {
$.ajax({
type: 'POST',
url: '/ajaxredirect/',
data: $('#your_form').serialize(),
crossDomain: false,
success: function(ctx) { console.log(ctx); },
});
}
</script>
Views.py
from django.views.generic import View
from braces.views import JSONResponseMixin, AjaxResponseMixin
class AjaxResponseView(JSONResponseMixin, AjaxResponseMixin, View):
def post_ajax(self, request, *args, **kwargs):
data = request.POST.items() # form data
ctx = {'hi': 'hello'}
return self.render_json_response(ctx)

Categories

Resources