Using a URL as a URL parameter in Django Rest Framework - javascript

I have a model whose unique field is an address. The thing is, I am trying to get instances of this model using AJAX.
var address = 'http://example.com/blog/2/';
$.ajax({
url: 'http://sitemy.com/api/get_content/'+encodeURIComponent(address),
type: 'GET',
dataType: 'json',
success: function(json) {
console.log('Success');
}
});
In my urls.py, I have the following code:
url(r'^api/get_content/(?P<url>.+)/$', views.get_content),
So I am trying to use this URL pattern to capture the get request. However, I am constantly getting a 404 error since the url sent from the request does not match my pattern. What gives? How can I solve this?
In case its important, in my views, I am doing the following:
def get_content(request, address):
try:
content = Content.objects.get(address=urllib.unquote(address))
except:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = ContentSerializer(content)
return Response(serializer.data)
Any help would be appreciated. Also, I welcome any general advice regarding the encoding of URLS, as that just boggles my mind for some reason. Thanks.

Related

Updating page elements immediately on input changes with django and AJAX inside GET request

I want to update elements in the page to tell a user in real-time how many objects will be affected by their choice of criteria in a form.
For an example to work with, the form asks for a number and the django logic will delete any model instance with a pk less than that value once the submit button is clicked - but before clicking the user wants to know how many they will be deleting:
<span id="number-changed">NULL</span> objects will be deleted
so the end result I want is that #number-changed will be populated by a value like MyModel.objects.filter(pk__lt=input_number).count().
I have set up an AJAX call on changes to the input via:
$("input").change( function() {
$.ajax({
type: "GET",
url: "{% url 'myapp:bulkdelete' %}",
data: {
csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),
},
success: function (data) {
// code to update #number-changed
}
I am wondering how I implement in the view so that on successful GET the success function can use the value I retrieve. Some pseudo-code:
# views.py
class MyView(FormView):
# ...
def get(self, request, *args, **kwargs):
input_number = ???
number_changed = MyModel.objects.filter(pk__lt=input_number).count()
# presumably some super().get() call here
return ???
Questions:
Can I retrieve the current input_number via request or does it need to be passed as a url parameter when making the AJAX request?
How can I add my required information, number_changed in this case, to the return of the get() method, and how to access this inside success?
The way I have implemented AJAX with django before has being using POST requests and I simply return a JsonResponse with my required data. However, an initial get() is called when loading the page and needs to return a full HttpResponse - so ultimately is there a way to add my additional information into this, or am I going about it completely wrong.
An Ajax request is exactly the same as any other request from the point of view of the server. You can just include the data in the querystring, which you then access in the view via the request.GET dict.
jQuery will generate that querystring for you from the data parameter; note, you don't need a csrf token for a GET request. So:
type: "GET",
url: "{% url 'myapp:bulkdelete' %}",
data: {
input_number: $(this).val(),
},
...
And in the view:
def get(self, request, *args, **kwargs):
input_number = request.GET["input_number"]

How to access data passed into Flask with an AJAX call?

I am working on a project that displays hotel and airbnb data using flask and a sql database. We are trying to create a "favorite button" so the user can favorite/unfavorite listings. I've got an AJAX call to a Flask endpoint that will the make corresponding SQL queries to the "favorites" table. My problem is, I can't seem to access the data I'm passing into Flask.
Here is my AJAX call on the client-side:
function unfavoriteClicked(uid, itemid, type){
$.ajax({
type: "POST",
url: "/unfavorite",
data:{uid:uid, itemid:itemid, type:type},
contentType: 'application/json;charset=UTF-8',
success: function(data) {
console.log(data);
},
error: function(jqXHR) {
alert("error: " + jqXHR.status);
}
});
}
And here is my Flask code:
#app.route('/unfavorite', methods=["GET","POST"])
def unfavorite():
if request.method == "POST":
return request.form
return "this shouldn't happen"
Note that I've taken the SQL logic and other things out since I've figured out that I am not accessing the data correctly in Flask.
I am sure that the AJAX request goes through, because when I return something like "hello", it shows up in the console log. However, when I try to access the data dictionary I'm passing in, it returns a "500 internal server error" or some other kind of error depending on what I'm trying to access. I've tried to access a bunch of different things from looking at other stackoverflow posts (like request.form['data'], request.data, request.args, etc) but nothing seems to allow me to access the data. However, it does seem to allow me to access "request.method".
I was wondering if there is something fundamental that I am missing here that would be a reason why I cannot pass in data to Flask? Or any other suggestions for doing this "favorite" button are appreciated. Thanks!
So considering the main issue that you want to tackle is accessing the data that is been passed by your web page using Ajax. I have a solution which might work in your case.
So there are two parts in which i will explain how you can solve this problem.
1) Passing the data to your python controller/function to further process the data.
$.post("url_to_which_you_want_to_pass_data", {variable_name_to_access_in_python:any_value/variable_from_front_end},
function(response, status){
call_back_function_code
});
2) Accessing the data that has been passed from the webpage in python flask
#app.route('/unfavorite', methods=["GET","POST"])
def unfavourite:
if request.method == "POST":
any_variable_name = request.form.get("variable_name_to_access_in_python","")
print(any_variable_name) #If you want to print
return any_variable_name #If you want to see any_variable_name on web
return None
Hope it Helps! Cheers :)
I don't know if it's the best option, but its worked for me.
JavaScript:
var data = [1, 2, 3, 4]
var frontend_data = {'list':data}
$.ajax({
url: "/unfavorite",
contentType: 'application/json',
type: "POST",
data: JSON.stringify(frontend_data),
dataType: 'json',
success: function(result) {
console.log("Result:");
console.log(result);
}
});
Flask:
#app.post('/unfavorite')
def unfavorite():
data = request.get_json()
print(data['data']) #[1, 2, 3, 4]
return jsonify(data)

reload page after processing javascript output in flask

I have a javascript snipped which uses ajax to send an email address to my flask views.py script. I want to send a message to that address if the email is not in my database or otherwise reload the website and show the user information for that email address. Here is my javascript code which sends the data to my views.py
<script type='text/javascript'>
$(".send_invite_message").click(function(evt) {
var Toemail = document.getElementById('To').value
$.ajax({
url: "/send_invitation_member",
type: "GET",
async: true,
cache: false,
dataType: 'json',
contentType: "application/json; charset=utf-8",
data: { email: Toemail},
success: function(data) {
///do something
},
});
});
</script>
and in flask I would like to now have the option to send an email and if the email already exists in the database to reload the site
#app.route('/send_invitation_member', methods=['GET'])
def send_invitation_member():
if request.method == 'GET':
email = request.args.get('email')
search_result = check database for email entry
if search_result:
return render_template('show_members.html')
else:
send message and return json object
However the ajax script expects a json object back, so I don't know how to reload the site and show the user information. Is there any way to do this directly in flask or do I need to extend my javascript code and load the site from there?
thanks
carl
Since there's no way for an AJAX response to directly affect the page that's calling it, you'll need to extend your javascript a little (but only a bit).
In your success function, let's add the following:
success: function(data) {
if (data['url'] != null) document.location = data['url'];
else console.log('Got a valid JSON response, but no URL!');
}
This code will redirect the page to where the JSON specifies with its 'url' key. Now all that's left is to add it to our Flask code.
#app.route('/show_members')
def show_members():
return render_template('show_members.html')
#app.route('/somewhere_else')
def some_other_route():
return "It all works!"
#app.route('/send_invitation_member', methods=['GET'])
def send_invitation_member():
email = request.args.get('email')
search_result = check database for email entry
if search_result:
destination = url_for('.show_members')
else:
destination = url_for('.some_other_route')
send message and return json object
return Response(response=json.dumps({'url': destination}, mimetype='text/json')
I find when using flask it's better to separate your routes out into different functions depending on the HTTP method. And the url_for method? It's a life saver. You can find its docs here http://flask.pocoo.org/docs/0.10/api/#flask.url_for

AJAX not resolving url correctly

I have an HTML form that I want to submit to a flask endpoint, /add_int. When the form is submitted I intercept it with Jquery and submit the form to the endpoint using AJAX as follows:
var form = $( this ).serialize()
$.post({
url: "{{ url_for('add_int') }}",
data: JSON.stringify(form),
contentType: 'application/json;charset=UTF-8',
success: function(resp) {
console.log(resp);
}
});
The endpoint looks like this:
#app.route('/add_int', methods=['GET', 'POST'])
#login_required
def add_int():
# do stuff
return jsonify(status="success!")
My issue is that I never get to the endpoint.
When I examine my console I see
POST http://127.0.0.1:5000/[object%20Object] 404 (NOT FOUND)
instead of
POST http://127.0.0.1:5000/add_int
as I'd expect.
Note that if I set
url: '/add_int',
I run into the same problem.
I've found cases that use almost identical code that don't mention this problem:
e.g. how can I use data posted from ajax in flask?
My guess, is that my url is being resolved as a String object rather than a url, but I can't figure out why it's happening, and how to fix it.
What's going on?
You should remove the call to JSON.stringify, you can pass a serialized form directly as POST data and JSON.stringify is turning your object into [Object object].
url: '/add_int', isn't working because (it appears that) your frontend is running on a different port than the backend, so it will be rejected as a "cross domain" request. Have you inspected the value that "{{ url_for('add_int') }}" is returning?
Try not specifying the hash keys explicitly. http://api.jquery.com/jquery.post/
$.post("{{ url_for('add_int') }}",
JSON.stringify(form),
function(resp) {
console.log(resp);
},
'application/json;charset=UTF-8'
);

Implementing Ajax calls for a REST API

I have built a back end REST API using Slim Framework and followed the REST format as close as I could.
Once I started working on the Front End I realized that AJAX works great with parameters and not paths
(param file?param=value , paths file/object/method/id)
I am planning on out sourcing or building an APP with xamarin or other 3rd party to consume the API, but for now a Alpha test will be done with HTML and AJAX calls.
Example call example.com/user/test or example.com/advertiser/2
So how do I query the API, do I just concat URL strings?
.ajax({ ... url : 'example.com/user/'+user ...});
EDIT:
Yes I know AJAX is domain sensitive, and Yes I am using verbs GET,POST,PUT and DELETE.
What is going on is the following :
When passing variables in an AJAX request they get appended as
PARAMS example.com/users/?user=Pogrindis
in an REST API at least as far as I read it goes
example.com/users/Pogrindis that's a path
reference parse.com/docs/rest#general-quick
Ajax has set definitions how to do this : https://api.jquery.com/jQuery.ajax/
Your passing user as a param, over get // post method and you are specifying what you expect back.
If i understood the question correctly you are looking at something like:
$.ajax({ url: 'example.com/user/',
data: {user: user}, // Params being sent
type: 'post',// Or get
dataType: 'json' // Or whatever you have
success: function(output) {
//.. do what you like
}
});
There should be no problem.
The data being passed into it will append to the url for GET-requests, i think thats what you mean.. Your data object can be constructed before sending via ajax.
There needs to be a route to query for data. Unless you define some flag on the server to point to the correct location, then you could pass through a route param but you need to have a pointer URL. Building the route can be painful, and subsequent calls will be more challenging but you can do it ?
After doing some research here is a solution used
FRONT END
$.ajax({
url: '/user/'+getid,
data: getdatastring,
type: 'GET',
datatype: 'json',
cache: false,
success: function(data) {
data = JSON.parse(data);
}
});
BACK END
SLIM PHP FRAMEWORK
$app->put('/user/:id', function($id) use ($app,$_pdo) {
$obj = new dbModel($_pdo);
$objApi = new Controller($obj);
$arrParams = json_decode($app->request()->getBody(),true);
$arrUser= $objApi->getUserInfo($id,$arrParams);
print json_encode($arrUser);
});

Categories

Resources