Ember store data to django backend - django

I'm new to Ember and I'm trying to communicate with a django server via RESTful API. So far I have managed to get the information from the server but if I try to send some information back I get a "CSRF Failed: CSRF token missing or incorrect." error.
In the resources of Chrome's developer tools I can see that I don't have any cookie. I've read that I should the "X-CSRFToken": "cookie" in my adapter but since I don't have a cookie I don't know what to do.
So I' m in dead end...
Here is my code:
Server Response:
[{"username":"user1","password":"123","email":"user1#example.com"},
{"username":"user2","password":"456","email":"user2#example.com"}]
Ember Model:
import DS from 'ember-data';
export default DS.Model.extend({
username: DS.attr(),
password: DS.attr(),
email: DS.attr()
});
Ember Adapter:
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
host: '/api',
contentType: 'application/json',
dataType: 'json',
headers: {
username: 'XXXX',
password: 'XXXX'
},
buildURL: function(modelName, id, snapshot, requestType, query) {
var url = this._super(modelName, id, snapshot, requestType, query);
return url + "/";
}
});
Ember Serializer:
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
primaryKey: 'username'
});
Ember Route: import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.store.findAll('account');
}
});
Ember Controller:
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
signup(){
console.log('My username is: ', this.get('username'));
console.log('My password is: ', this.get('password'));
console.log('My email is: ', this.get('email'));
var account = this.store.createRecord('account', {
username: this.get('username'),
password: this.get('password'),
email: this.get('email')
});
account.save();
}
}
});
Thank you in advance for your help.

I resolved my issue.
The problem was that I was using http://localhost:4200/ instead of http://127.0.0.1:4200/ and that's why I couldn't find django's cookie.
As soon as I found django's cookie, I just add an attribute to the header of the adapter.
My new adapter is shown below:
Ember Adapter:
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
host: '/api',
contentType: 'application/json',
dataType: 'json',
headers: {
"X-CSRF-Token": 'django token',
username: 'XXXX',
password: 'XXXX'
},
buildURL: function(modelName, id, snapshot, requestType, query) {
var url = this._super(modelName, id, snapshot, requestType, query);
return url + "/";
}
});

Related

Ember.js : Modify request URL

I create an Ember app with a Symfony REST api. I also use the REST adapter for my requests.
I have 2 models in my app : users and their related comments.
I already created CRUD operations for my user properties and now I focus on the CRUD operations for comments.
Model user.js
export default DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
comments: DS.hasMany('comment')
});
Model comment.js
export default DS.Model.extend({
title: DS.attr('string'),
message: DS.attr('string'),
user: DS.belongsTo('user')
});
I have a route which shows all comments (and other data) of a given user. The request loads the user object and his relations. On the view I also have a form and an action to create a new comment for this user.
Route users/get.js
import Ember from 'ember';
export default Ember.Route.extend({
id: null,
model(params) {
this.set('id', params.user_id);
return this.get('store').findRecord('user', params.user_id, {include: 'comments'});
},
});
Route users/get/comments.js
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
return this.modelFor('user.get', params.user_id);
},
});
Controller users/get/comments.js
import Ember from 'ember';
export default Ember.Controller.extend({
newComment: null,
user: null,
init: function() {
this._super(...arguments);
let comment = this.store.createRecord('comment');
this.set('newComment', comment);
},
actions: {
saveComment: function() {
let user = this.get('model');
let comment = this.get('newComment');
comment.set('user', user);
comment.save();
}
}
});
Everything works, except for the request sent to the backend. I loaded the comments from the user, so I expect a call to :
POST http://my-app.local/users/comments/
Instead the call is sent to :
POST http://my-app.local/comments/
Do you know why and how could I correct it ?
Second problem, the model is loaded from the 'user.get' route. This works because the user comes from this route to this page, but... It's doesn't work if the user enters directly the URL for comments. That sound logical, but I have no clue how to correct this problem... Can you help me ?
This can be done by rewrite the CommentAdapter.urlForCreateRecord method. Which affect new comment record requests.
adapters/comment.js
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
urlForCreateRecord(modelName, snapshot) {
return '/users/comments'; // the url you want
}
});
There are several urlFor... method you might need to customise your url.
Just check out the document
http://devdocs.io/ember/classes/ds.buildurlmixin/methods#urlForCreateRecord

findAll throwing error

I am using a simple findAll query in my ember application ( ember-version: 2.12.0, ember-data-version: 2.12.1 ) and I get the following error:
Assertion Failed: You can no longer pass a modelClass as the first argument to store.buildInternalModel. Pass modelName instead.
I am using the RESTAdapter and RESTSerializer.
Here is my team model:
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
projects: DS.hasMany('project'),
users: DS.hasMany('user'),
members: Ember.computed('users', function() {
return this.get('users.content.length');
}),
leader: DS.belongsTo('user', {
inverse: 'team'
})
});
and my team serializer:
import ApplicationSerializer from './application';
import DS from 'ember-data';
export default ApplicationSerializer.extend(DS.EmbeddedRecordsMixin,{
attrs: {
users: { async: true },
projects: { async: true }
}
});
Despite the error, the team objects I requested are in the store. I had no luck in solving this so far.
Actually the problem was in the serializer and the payload from the server. I should have attrs: {users: {embedded: 'always'}} as users where in the payload from the server.

Assertion Failed: You must include an 'id' for account in an object passed to 'push' Ember.js v-2.4

I'm new to Ember and I can't find anywhere a solution to my problem. I have read the questions here in stack and in other ember forums, but none of them seems to work for me.
I'm trying to create a simple signup form. I should note that for the backend I use django.
Here is my code:
Server Response:
[{"username":"user1","password":"123","email":"user1#example.com"},
{"username":"user2","password":"456","email":"user2#example.com"}]
Ember Model:
import DS from 'ember-data';
export default DS.Model.extend({
username: DS.attr(),
password: DS.attr(),
email: DS.attr()
});
Ember Adapter:
import DS from 'ember-data';
export default DS.RESTAdapter.extend({
host: '/api',
contentType: 'application/json',
dataType: 'json',
headers: {
username: 'XXXX',
password: 'XXXX'
}
});
Ember Serializer:
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
primaryKey: '_id'
});
Ember Route:
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.store.findAll('account');
}
});
Ember Controller:
import Ember from 'ember';
export default Ember.Controller.extend({
actions: {
signup(){
console.log('My username is: ', this.get('username'));
console.log('My password is: ', this.get('password'));
console.log('My email is: ', this.get('email'));
var account = this.store.createRecord('account', {
username: this.get('username'),
password: this.get('password'),
email: this.get('email')
});
account.save();
}
}
});
With this implementation I get the aforementioned error. Any help would be appreciated. Thank you in advance.
Your backend should respond with an id, i.e
{"id":123,"username":"user1","password":"123","email":"user1#example.com"}
You don't really need to use the serializer, unless you want a specific field to act as an id. So in the example above, ember-data would expect your backend to return
{**"_id":123**,"username":"user1","password":"123","email":"user1#example.com"}
Or you could do something like this:
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
primaryKey: 'username'
});
And use your username as an id.
I fixed my error. The problem was that the backend was using username as id so ember could not recognized it.
The fixed code for the Ember Serializer is:
import DS from 'ember-data';
export default DS.JSONSerializer.extend({
primaryKey: 'username'
});

Ember data JSON Api adapter set all attributes to undefined

In an application using ember 2.1.0 and ember-data 2.1.0, I have this model :
# app/models/user.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr()
});
And this route :
# app/routes/subscriptions/new.js
export default Ember.Route.extend({
model() {
this.store.findRecord('user', 1).then(function(data) {
console.log(data.id)
console.log(data.get('email'))
})
return this.store.find('user', 1);
}
});
I have this adapter :
import DS from 'ember-data';
export default DS.JSONAPIAdapter.extend({host: 'http://localhost:5000'})
This data is returned by the server :
{"data":{"id":"1","type":"users","attributes":{"email":"test#test.com"}}}
In the console, I have the user id but the email is undefined. In the template, {{model.email}} gives nothing.
I may miss something but it's so simple. Is it my mistake or a bug?
You have to also specify email attribute in model:
export default DS.Model.extend({
name: DS.attr('string'),
email: DS.attr('string')
});

How do I get cookies to to be sent with my requests to the backend in ember app?

Is there a way in Ember to send cookies with the requests to the backend?
For example: if my client URL is protocol://example.com. The cookies that belong to the same domain will be in the request header when I navigate to protocol://example.com/profile. However, they do not persist in the subsequent request/s the profile route model method makes -> example to protocol://example-host/posts. How do I make those cookies persist?
/app/routes/profile.js:
import Ember from "ember";
import AuthenticatedRouteMixin from "simple-auth/mixins/authenticated-route-mixin";
export default Ember.Route.extend({
model() {
return this.store.findAll("post");
},
renderTemplate() {
this.render("header", {
outlet: "header"
});
this.render("profile");
}
});
/app/adapters/application:
import Ember from "ember";
import DS from "ember-data";
export default DS.RESTAdapter.extend({
host: 'http://example-host.com',
corsWithCredentials: true,
crossDomain: true,
xhrFields: { withCredentials: true }
});
This works in my production app. Code in app/adapters/application.js:
import Ember from 'ember';
$.ajaxSetup({
xhrFields: {
withCredentials: true
}
});
export default DS.RESTAdapter.extend({
ajax(url, method, hash) {
hash = hash || {};
hash.crossDomain = true;
hash.xhrFields = {
withCredentials: true
};
return this._super(url, method, hash);
}
})
You can also set individual header values to be sent with each ember-data request. Useful if you need to pass an API key with all your requests.
In your adapter (app/adapters/application.js):
import DS from 'ember-data';
import { get } from '#ember/object';
import { computed } from '#ember/object';
export default DS.RESTAdapter.extend({
headers: computed(function() {
return {
'API_KEY': get(document.cookie.match(/apiKey\=([^;]*)/), '1'),
'ANOTHER_HEADER': 'Some header value'
};
}).volatile()
});