Incorrect type. Expected pk value, received str - django

how to post from html form in
django rest framework api i am getting error as Incorrect type. Expected pk value, received str.

Related

django request.POST.items() returns empty list everytime with Postman

I have a django method and I'm just trying to pull out a POST variable:
#csrf_exempt
def update_backer(request):
for k, v in request.POST.items():
print(k, v)
email = request.POST.get("email", "none")
return JsonResponse({"data":{
"email":email
}})
When I try to do a POST via javascript XMLHttpRequest, I wasn't getting the data through. So I fell back to Postman to try to confirm things are working on the django end. And I am posting the data, but django isn't seeing it. Am I doing something obviously wrong?
Edit: Interestingly enough, if I change it to GET instead of POST, it works as I would expect.
For POST request values are sent in request body. You can use application/x-www-form-urlencoded content type so that request body has same format of query params.

Why does Django return http 200 if form data is invalid?

AFAIK Django uses this way to handle forms:
GET: client receives HTML with input elements
user fills out the form
user submits form: http POST
server/Django validates the form. In this case it is invalid
server sends HTML containg the same form and an error message to the user. With http status 200.
Wouldn't it make more sense to use a different http status code if the data is invalid?
PS: I know the Post/Redirect/Get pattern. The question is: "Why 200 if the data is invalid?"

AttributeError with django-rest-auth and django-rest-knox - Token Serializer

I am currently setting up a django backend for a React frontend app.
As part of of, I am using django-rest-auth and django-allauth for registration and authentication. I wanted to implement better token management through django-rest-knox.
I used the following code to start from and modify my existing app with rest-auth and allauth (which works):
https://gist.github.com/AndrewPix/cdd9276b1d5683459b965d5cc4517b26
My problem is the following:
When I POST my credentials to the url /rest-auth/login, in the backend a token gets created for the right user, with all the attributes (e.g. expiry date), but I don't get the token and user returned as part of the API call. Instead I receive the below error:
AttributeError at /rest-auth/login/
Got AttributeError when attempting to get a value for field token on serializer KnoxSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the str instance.
Original exception text was: 'str' object has no attribute 'token'.
Any help would be greatly appreciated. I think something is wrong with the KnoxSerializer but I can't figure out what?
Thanks!
AM
The fix came from the urls! Very simple late night mistakes. The URL path to KnoxLoginView was put after the inclusion of djang-rest-auth urls, instead of before.
By registering the URL url(r'^rest-auth/login/', views.KnoxLoginView.as_view()) , and including that before the line url(r'^rest-auth/', include('rest_auth.urls')) , it works.

Django Google API Client Error..Trying to implement an application that adds events to a users google calendar after authentication

While using the OAuth authentication method I am unable to retrieve the authentication code from the url. Google redirects me to a url with code appended to its end
..I think I am making a mistake in the regex because after authenticating myself and giving the app the permission to manage my calendar I am redirected to
http://127.0.0.1/Main/addloanpremium/?code=4/2wi1hu0Gv8YZuKo79kc-kjCmw7qj0W2EyLYa3qzIe7w# ..How do I extract the code from the url..The above url opens on a new tab and due to my urls.py displays the same form page however when I try to access the 'code' value using request.GET.get('code') it does not give any value..
Exception Value: Can't convert 'NoneType' object to str implicitly
My views.py looks like:
def addloanpremium(request):
if request.method == 'GET':
loan=Loan()
premium=Premium()
user=request.user
#form=loan_pre_form(request.POST)
if(request.GET.get('typelp')=='loan'):
loan.user=user
#premium.user=user
#lots of code here..all values from fields are stored into the db
if(request.GET.get("iscalendar")=="True"):
print(" \n \n entered iscalendar =true \n")
print(" \n \n entered calendar now trying to add event \n \n")
SCOPES = 'https://www.googleapis.com/auth/calendar'
flow=auth2client.client.flow_from_clientsecrets('C:/Users/ghw/Desktop/Expenze/Main/client_secrets.json',SCOPES,redirect_uri='http://127.0.0.1:8000/Main/addloanpremium/')
storage = oauth2client.file.Storage('credentials.dat')
credentials = storage.get()
if not credentials or credentials.invalid:
auth_uri = flow.step1_get_authorize_url()
print("\n value of auth uri is "+auth_uri+"\n")
webbrowser.open(auth_uri)
auth_code = request.GET.get('code')
print("\n value of auth code is "+auth_code+"\n")
### I am getting the auth code wrong
credentials = flow.step2_exchange(auth_code)
storage.put(credentials)
http = httplib2.Http()
http = credentials.authorize(http)
CAL = build('calendar', 'v3', http=http)
.
.#lots of code here
.
return render(request,'Main/loan_pre_form.html',{})
my Main:urls.py:
url(r'^addloanpremium/$',views.addloanpremium,name='addloanpremium'),
my loan_pre_form.html contains
<form action=" {% url 'Main:addloanpremium' %}" method="GET">
Any help would be highly appreciated.
Based from this SO answer, functions return a value and if you don't specify one, it will implicitly return None. Exception Value: Can't convert 'NoneType' object to str implicitly error means that you try to use a NoneType as a string. I guess the problem is that this function doesn't return anything (in one case) so it actually returns NoneType.
Here is an example from Google documentation.
You can also check on these related threads:
Python 3.3.3 TypeError : Can't convert 'NoneType' object to str implicitly
TypeError: Can't convert 'int' object to str implicitly
Django: "Can't convert 'Name' object to str implicitly" on saving object
Hope this helps!

Handling errors with the (now default) Ember Data JSON-API adapter

I am using Ember 1.13.7 and Ember Data 1.13.8, which by default use the JSON-API standard to format the payloads sent to and received from the API.
I would like to use Ember Data's built-in error handling in order to display red "error" form fields to the user. I have formatted my API error responses as per the JSON-API standard, e.g.
{"errors":[
{
"title":"The included.1.attributes.street name field is required.",
"code":"API_ERR",
"status":"400",
}
]}
and when I attempt to save my model the error callback is being correctly executed. If I look within the Ember Inspector I can see that the model's "isError" value is set to true but I can't see how Ember Data is supposed to know which field within the model is the one in an error state? I see from the official JSON-API pages (http://jsonapi.org/format/#errors) that you can include a "source" object within the error response:
source: an object containing references to the source of the error,
optionally including any of the following members:
pointer: a JSON Pointer [RFC6901] to the associated entity in the request document
[e.g. "/data" for a primary data object, or "/data/attributes/title"
for a specific attribute].
parameter: a string indicating which query
parameter caused the error.
but is this what I should be doing in order to tell Ember Data which fields it should mark as being in an error state?
If anyone can help shed some light on this I'd be grateful.
Thanks.
Note the answer below is based on the following versions:
DEBUG: -------------------------------
ember.debug.js:5442DEBUG: Ember : 1.13.8
ember.debug.js:5442DEBUG: Ember Data : 1.13.9
ember.debug.js:5442DEBUG: jQuery : 1.11.3
DEBUG: -------------------------------
The error handling documentation is unfortunately scattered around at the moment as the way you handle errors for the different adapters (Active, REST, JSON) are all a bit different.
In your case you want to handle validation errors for your form which probably means validation errors. The format for errors as specified by the JSON API can be found here: http://jsonapi.org/format/#error-objects
You'll notice that the API only specifies that errors are returned in a top level array keyed by errors and all other error attributes are optional. So seemingly all that JSON API requires is the following:
{
"errors": [
{}
]
}
Of course that won't really do anything so for errors to work out of the box with Ember Data and the JSONAPIAdapter you will need to include at a minimum the detail attribute and the source/pointer attribute. The detail attribute is what gets set as the error message and the source/pointer attribute lets Ember Data figure out which attribute in the model is causing the problem. So a valid JSON API error object as required by Ember Data (if you're using the JSONAPI which is now the default) is something like this:
{
"errors": [
{
"detail": "The attribute `is-admin` is required",
"source": {
"pointer": "data/attributes/is-admin"
}
}
]
}
Note that detail is not plural (a common mistake for me) and that the value for source/pointer should not include a leading forward slash and the attribute name should be dasherized.
Finally, you must return your validation error using the HTTP Code 422 which means "Unprocessable Entity". If you do not return a 422 code then by default Ember Data will return an AdapterError and will not set the error messages on the model's errors hash. This bit me for a while because I was using the HTTP Code 400 (Bad Request) to return validation errors to the client.
The way ember data differentiates the two types of errors is that a validation error returns an InvalidError object (http://emberjs.com/api/data/classes/DS.InvalidError.html). This will cause the errors hash on the model to be set but will not set the isError flag to true (not sure why this is the case but it is documented here: http://emberjs.com/api/data/classes/DS.Model.html#property_isError). By default an HTTP error code other than 422 will result in an AdapterError being returned and the isError flag set to true. In both cases, the promise's reject handler will be called.
model.save().then(function(){
// yay! it worked
}, function(){
// it failed for some reason possibly a Bad Request (400)
// possibly a validation error (422)
}
By default if the HTTP code returned is a 422 and you have the correct JSON API error format then you can access the error messages by accessing the model's errors hash where the hash keys are your attribute names. The hash is keyed on the attribute name in the camelcase format.
For example, in our above json-api error example, if there is an error on is-admin your would access that error like this:
model.get('errors.isAdmin');
This will return an array containing error objects where the format is like this:
[
{
"attribute": "isAdmin",
"message": "The attribute `is-admin` is required"
}
]
Essentially detail is mapped to message and source/pointer is mapped to attribute. An array is returned in case you have multiple validation errors on a single attribute (JSON API allows you to return multiple validation errors rather than returning just the first validation to fail). You can use the error values directly in a template like this:
{{#each model.errors.isAdmin as |error|}}
<div class="error">
{{error.message}}
</div>
{{/each}}
If there are no errors then the above won't display anything so it works nicely for doing form validation messages.
If you API does not use the HTTP 422 code for validation errors (e.g., if it uses 400) then you can change the default behavior of the JSONAPIAdapter by overriding the handleResponse method in your custom adapter. Here is an example that returns a new InvalidError object for any HTTP response status code that is 400.
import DS from "ember-data";
import Ember from "ember";
export default DS.JSONAPIAdapter.extend({
handleResponse: function(status, headers, payload){
if(status === 400 && payload.errors){
return new DS.InvalidError(payload.errors);
}
return this._super(...arguments);
}
});
In the above example I'm checking to see if the HTTP status is 400 and making sure an errors property exists. If it does, then I create a new DS.InvalidError and return that. This will result in the same behavior as the default behavior that expects a 422 HTTP status code (i.e., your JSON API error will be processed and the message put into the errors hash on the model).