I'm working on a webapp that uses Flask as the backend server. There are posts that I'm storing in an SQLAlchemy database, and I want the users to be able to upvote/downvote them without having to log in. I wrote a JavaScript function for upvoting/downvoting that increments the current vote count and then updates the count in the database using Ajax. I want to make sure that the same user doesn't vote on the same post twice; it doesn't have to be robust. I read that cookies could be used for that purpose, or a combination of cookies and IP. I'm having a hard time understanding how to get started: do I assign a cookie to a user in JS or in Flask? How do I check whether the user already voted? I'd appreaciate if someone could show me a simple example or direct me to a good resource. Thanks a lot.
Here's my Javascript part for upvoting:
$(document).ready(function() {
$('#{{ upbtnID }}').click(
function() {
var postID = "{{ answer.id }}";
var data = {
'id': "{{ answer.id }}"
};
var score = document.getElementById('{{ scoreID }}');
var scoreText = score.textContent;
var scoreToInt = parseInt(scoreText, 10);
var newScore = ++scoreToInt;
var scoreToStr = newScore.toString();
$(this).css('border-bottom-color', '#26EDEB');
score.textContent = scoreToStr;
$.ajax({
url: "/upvote",
data: JSON.stringify(data, null, '\t'),
contentType: 'application/json;charset=UTF-8',
type: 'POST',
success: function(response) {;
},
error: function(error) {
alert("Awww");
}
});
});
And the corresponding function in Flask:
# upvote a post
#app.route('/upvote', methods=["GET", "POST"])
def upvote():
if request.method =="POST":
thePostID = int(request.json["id"])
thePost = Answer.query.get(thePostID)
thePost.score += 1
db.session.commit()
data = thePost.score
return ('', 204)
Quoting from Flask snippets:
#app.route('/set_cookie')
def cookie_insertion():
redirect_to_index = redirect('/index')
response = current_app.make_response(redirect_to_index )
response.set_cookie('cookie_name',value='values')
return response
Link: http://flask.pocoo.org/snippets/30/
Related
I am passing a Django QuerySet as a JSON response from a Django view.
def loadSelectedTemplate(request):
if request.is_ajax and request.method == "GET":
templateID = request.GET.get("templateID", None)
template = list(operationTemplates.objects.filter(templateID = templateID))
if operationTemplates.objects.filter(templateID = templateID).exists():
ser_template = serializers.serialize('json', template )
return JsonResponse({"valid": True, "template": ser_template}, status=200)
else:
return JsonResponse({"valid": False}, status = 200)
This response is received by the javascript and it can be logged to the console.
// GET AJAX request
$.ajax({
type: 'GET',
url: "{% url 'loadSelectedTemplate' %}",
data: {"templateID": templateID},
success: function (response) {
// if valid template, add to textarea
if (response["valid"]){
var template = response["template"];
console.log(response);
}
Console.log output for the JSON object looks like this;
{
"valid": true,
"template": "[{\"model\": \"opnoteannotator.operationtemplates\",
\"pk\": 14,
\"fields\": {\"templateCategory\": \"Lower Limb\",
\"templateName\": \"Femoral to below knee Bypass using autologous vein\",
\"templatePreopBundle\": \"WHO check list completed.\\r\\n
Antibiotic Chemoprophylaxis: Co-amoxiclav / Teicoplanin / Gentamicin\",
\"templateIndication\": \"CLTI with night pain / rest pain / tissue loss / infection\",
I want to add the objects in "fields" to a text-area on my web page.
How can I achieve this? I have tried different methods but can't seem to get the values accessed in the Javascript.
Thanks in advance.
Maybe you can try:
console.log(response['template']);
I had to convert to the AJAX input from the view.py to a JSON object even though I was passing it as a JsonResponse.
This solution seems to work.
// GET AJAX request
$.ajax({
type: 'GET',
url: "{% url 'loadSelectedTemplate' %}",
data: {"templateID": templateID},
success: function (response) {
// if valid template, add to textarea
if (response["valid"]){
//var template = response["template"];
var tem = response.template;
//convert to JSON object
var res = JSON.parse(tem);
//Empty text area
document.getElementById("opnoteTextArea").value =""
//Display in text area
document.getElementById("opnoteTextArea").value += "Template Name: " + res[0].fields.templateName;
document.getElementById("opnoteTextArea").value += "\n\nPreopBundle:\n" + res[0].fields.templatePreopBundle;
I am trying to POST the songFiles array pushed from the getTableData() function (inside the ajax request) into the /api/fileNames endpoint, which is then sent to a callback postFileNames() that should post the array, but I just can't seem to get it working. Any help would be appreciated, including maybe other ways to do this.
I'm a bit of beginner with using ajax and flask, I have scoured far and wide for a solution, but can't seem to find any to fit my goal, forgive my lack of knowledge.
JavaScript Code
function getTableData() {
$.ajax({
method: "GET",
url: "/api/getSong",
dataType: "json",
success: function(data) {
createMusicTable();
let indexObj = Object.keys(data.song).length;
for (var i = 0; i < indexObj; i++) {
var song = data.song[i]
var id = data.song[i].song_id;
var fileName = data.song[i].song_file + ".mp3";
songFiles.push(fileName);
appendMusic(song, id);
songTitle.id = "s" + i;
console.log("td-ok");
}
postFileNames(songFiles);
}
});
}
function postFileNames(data) {
$.ajax({
method: "POST",
url: "/api/fileNames",
dataType: "json", // data is an array, so not sure what to put here.
data: data, // not sure if correct
success: function(data) {
// should: post the data into the endpoint.
// data is not logged, goes straight to error.
console.log(data)
},
error: function() {
console.log("cry")
}
})
}
FLASK Endpoint Code
#app.route("/api/fileNames", methods=['POST', 'GET'])
def fileNameStorage():
if request.method == 'POST':
data = request.get_data() # not too sure what to do here either.
return data
else:
return "error" # currently goes to 'return error'
#app.route("/api/fileNames", methods=['POST', 'GET'])
def fileNameStorage():
if request.method == 'POST':
data = {
"id": request.json["id"],
"song_name": request.json["song_name"],
"time_duration": request.json["time_duration"]
}
return data, 200
else:
return "error", 400 # currently goes to 'return error'
Would be more prettier if you would :
#app.route("/songs/", methods=['GET', 'POST'])
def songs():
return Songs().get_songs(), 200
In routes.py file
and the other classes and methods in another file
Maybe try jsonify(array) or json.dump(array) if it's a problem to map the array elements.
I've almost viewed similar kind of questions but my problem has not solved yet.
I've following codes.
Controller
def create
#task_list = TaskList.new(task_list_params)
if #task_list.save
respond_to do |format|
format.json { render json: #task_list}
end
else
return
end
end
Ajax Script
$(document).on('click','.add', function(){
count = 0;
user_id = $('#user_id').val();
var name = $('.new-list').val();
var current = $(this);
if(name){
$.ajax({
method: 'POST',
url: action,
dataType: 'JSON',
data: {
task_list: {
name: name,
user_id: user_id
}
}
}).success(function(response){
var data = JSON.stringify(response);
alert(data.id);
$(current).parent().parent().parent().before(
'<div class="col-md-12">'+
''+name+''+
'</div>'
);
$(current).parent().parent().parent().remove();
$('.add-list').show();
});
}else{
alert('please add title');
}
});
I just want to take id of the record just saved to the database through ajax post request. Here, in success function it just alerts undefined and I don't know what's going wrong.
This is sample response.
.success(function(response){
alert(response.id);
Remove JSON.stringify from your success function. Response is already in JSON format you can directly get the value from it.
JSON.stringfy converts javascript object into string.
Explanation
Your response is already in JSON format and you have used dataType: "JSON" in your AJAX call. Which will make it possible to transfer JSON data between server and client.
When your response is already in JSON format you can use its property without parsing it. I.e response.id
If you have not used dataType: "JSON" and you are passing json encoded response from your controller to view file you have to first decode the response to get its values.
var d = $.parseJSON(response);
alert(d.id);
I would really appreciate some help on this. I have a page that shows products in a store using laravel pagination. I have filters on the page based on brands, category, and available products. for filtering the products I am using a checkbox. if a checkbox is checked I use ajax get request and send status via URL to a controller to filter available products.
status = 1 is for available products, and status = 0 is for all products.Url is looks like this:
/Collections/Newest_Items?status=1&page=2
Here is the situation. I want to know if is it possible to change the variable value in URL and regenerate the URL base on the page number and new filters dynamically? Is it a way to get the URL of the page using jquery and change the values and then change the Url with window.history.pushState("", "", URL);?
Here is my ajax:
$(document).on('click', "#only_available", function () {
if ($('#only_available').is(':checked')) {
var status = 1;
url = '/Collections/Newest_Items?status='+status;
} else {
var status = 0;
url = '/Collections/Newest_Items';
}
window.history.pushState("", "", url);
$.ajax({
url: '/Collections/Newest_Items',
type: "GET",
data: {status: status},
cash: false,
success:
function (response) {
$('#products-load').html(response);
}
});
});
});
I do this by writing the URL by myself. In this situation, I must write the URL after every filter applied to the page. this way I cant get the page the user currently in and it goes back to the first page. But what I want to achieve here is, I want to make the Url dynamically with page number the user currently on with all filters applied to it.
You can use window.location.search which will give you something like: status=1&page=2 in your example. Then you will need to parse out those variables to get the page number you're looking for.
Ok I think I understand what you are asking for. So with each unique filter event that you are firing you need to query the current url before pushstate and get the values with something like this.
For instance if someone clicks Brand then you would get the new brand variable as well as the current status and page variables to pass with ajax like this
also just POST it instead of GET
$(document).on('click', ".brand", function () {
var brand = $(this).attr('id);
//Example how to use it:
var params = parseQueryString();
var status = params["status"]);
var page = params["page"]);
// if you have more variables than this then you would add them here and make sure you pass them along to the ajax data.
url = '/Collections/Newest_Items?status='+status+'&page='+page+'&brand='+brand;
window.history.pushState("", "", url);
$.ajax({
url: '/Collections/Newest_Items',
type: "POST",
data: {status: status, page: page, brand: brand},
cash: false,
success:
function (response) {
$('#products-load').html(response);
}
});
});
var parseQueryString = function() {
var str = window.location.search;
var objURL = {};
str.replace(
new RegExp( "([^?=&]+)(=([^&]*))?", "g" ),
function( $0, $1, $2, $3 ){
objURL[ $1 ] = $3;
}
);
return objURL;
};
tnx to #CesarBielich and #Sokies I finally manage to solve the problem. they give me part of the answer but not all.I made it unique to my question:
what we need here is the path and the parameters that nested in URL. so for getting the path of the route, we must use window.location.pathname and for getting all the parameters must use window.location.search. after that, we must combine the path and params so that the URL comes out of it. then we must add the new parameter like status after that. So that all the parameters can be accessed by the controller. both the old params and the new one. this way laravel pagination knows what url to make, in the href links to other pages.
$(document).on('click', "#only_available", function () {
if ($('#only_available').is(':checked')) {
var status = 1;
} else {
var status = 0;
}
var params = window.location.search;
var path = window.location.pathname;
var old_url = path+params;
var url = old_url+'&status=' + status;
window.history.pushState("", "", url);
$.ajax({
url: url,
type: "GET",
cash: false,
success:
function (response) {
$('#products-load').html(response);
}
});
});
});
I'm sure this has been asked before, however I've been searching for hours and cannot find anything that works so apologies in advance. I'm in the early stages of learning to code with Python on an online course and I'm deviating away from it a little to make it my own.
When a user registers an account, I want to return an error if the username is already taken. Otherwise to create the account and redirect to the login page. However I'm not sure how to do define the if statement to return the correct console response as it only currently returns the user. I want this to return success / error and use ajax to catch this response.
The register model I have so far is:
class RegisterModel:
def __init__(self):
self.client = MongoClient()
self.db = self.client.codewizard
self.Users = self.db.users
def insert_user(self, data):
existing_user = self.Users.find_one({"username": data.username})
if existing_user:
pymsgbox.native.alert('Username already taken!', 'Title')
else:
hashed = bcrypt.hashpw(data.password.encode(), bcrypt.gensalt())
id = self.Users.insert({"username": data.username, "name": data.name, "password": hashed, "email": data.email})
print("uid is", id)
pymsgbox.native.alert('Account created, please login!', 'Title')
And the controller:
class PostRegistration:
def POST(self):
data = web.input()
reg_model = RegisterModel.RegisterModel()
reg_model.insert_user(data)
return data.username
and finally the javascript (not completed with if statement)
$(document).on("submit", "#register-form", function(e){
e.preventDefault();
var form = $('#register-form').serialize();
$.ajax({
url: '/postregistration',
type: 'POST',
data: form,
success: function(response){
console.log(response);
}
});
});
pymsgbox will be replaced by the Javascript when I can get it to work!
Figured it out:
Controller:
class PostRegistration:
def POST(self):
data = web.input()
reg_model = RegisterModel.RegisterModel()
register = reg_model.insert_user(data)
if register:
return register
and then returning "error" in the register model if statement.