Django create/update multiple models in one rest request - django

I have a form in Vue which takes in data that is spread into multiple models when sent to django .
Rest JSON is
data = {
people:{
name: "MyName",
age: 34
},
classes:{
name:"Valgris",
tag:3492,
comment:"gob gdjoisu is tsutsi"
}
}
-THE MODELS FIELD IN DJANGO ARE
class Classes(models.Model):
name = models.CharField(_ max_length=50)
age = models.IntegerField()
class People(models.Model):
name = models.CharField(_ max_length=50)
tag = models.IntegerField()
comment= models.TextField()
--- I tried tried using perform_create in my view, and also use create in serializer but I am unable to do it. request.data does not seem to like me popping out data and saving the result. It just doesn't work well.
Is there a way out. or do I have to send two request to create People and Classes model

I think you have to use two request for your purpose.
As serializer of django-rest-framework requires your request.data as an argument,
yourSerializer(yourModel, data=request.data)
so it will not operate with the data of two models that you are sending from vue.
Also, If you want to do these API calls with one another then you can call other API inside the first one API's response.
axios
.post("first/API/call/url", dataModel1, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then((response) => {
console.log(response);
axios
.post("second/API/call/url", dataModel2, {
headers: {
"Content-Type": "multipart/form-data",
},
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
})
.catch((error) => {
console.log(error);
});
Note: popping out data and changing it is fine for one model but for two model it's not fine.

Related

stale token even for first time user Djoser and DRF

the newly registered user get email for activation . He clicks on the links and move to an activation page .then he clicks on verify button which take uid and token from the link and post it to auth/users/activation/ and then gets the response stale token for the given user no matter how fast he click on the link on verify link . result is same. I am using djoser for activation and all user related stuff.and redux in the frontend for api calls and also the React as frontend
here is my settings.py:
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(days=30),
'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
'AUTH_HEADER_TYPES': ('JWT','Bearer'),
'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule' ,
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
}
DJOSER = {
'LOGIN_FIELD': 'email',
'USERNAME_CHANGED_EMAIL_CONFIRMATION': True,
'PASSWORD_CHANGED_EMAIL_CONFIRMATION': True,
'SEND_CONFIRMATION_EMAIL': True,
'SET_USERNAME_RETYPE': True,
'SET_PASSWORD_RETYPE': True,
'PASSWORD_CHANGED_EMAIL_CONFIRMATION':True,
'PASSWORD_RESET_CONFIRM_URL': 'password/reset/confirm/{uid}/{token}',
'SEND_ACTIVATION_EMAIL': True,
'ACTIVATION_URL': 'activate/{uid}/{token}',
'SOCIAL_AUTH_TOKEN_STRATEGY': 'djoser.social.token.jwt.TokenStrategy',
'SOCIAL_AUTH_ALLOWED_REDIRECT_URIS': ['https://negoziohub.herokuapp.com/google', 'http://127.0.0.1:8000/facebook'],
'SERIALIZERS': {
'user_create': 'base.serializers.UserSerializer',
'user': 'base.serializers.UserSerializer',
'user_delete': 'djoser.serializers.UserDeleteSerializer',
}
}
here is userAction.js:
export const activate = (uid, token) => async (dispatch) => {
try {
dispatch({
type: USER_ACTIVATE_REQUEST
})
const config = {
headers: {
'Content-type': 'application/json',
}
}
const body = JSON.stringify({ uid, token });
const { data } = await axios.post(`/auth/users/activation/`, body,
config
)
dispatch({
type: USER_ACTIVATE_SUCCESS,
payload: data
})
// dispatch(login())
localStorage.setItem('userInfo', JSON.stringify(data))
} catch (error) {
dispatch({
type: USER_ACTIVATE_FAIL,
payload: error.response && error.response.data.detail
? error.response.data.detail
: error.message,
})
}
}
Any help would be appreciated. Thanks❤❤❤
I know it's too late to answer your question but I will do it just for other folks out there who might face the same issue in the future.
I had the same problem and I couldn't find anything on the internet, which drove me to dive deep in the source code of Djoser. The issue in my case was that I changed the default behavior to change the state of the user and set user.is_active = True. This was the issue as Djoser sends the stale token error if user.is_active != False.
Hope this helps.

Django REST Framework Delete Method Request receives Forbidden 403

views.py
class DeviceView(viewsets.ModelViewSet):
serializer_class = DevicesSerializer
queryset = Devices.objects.all()
permission_classes = [permissions.IsAuthenticated]
Axios Request
axios.delete(`api/devices/${data.id}/`, {}, {
headers: {'X-CSRFToken': csrftoken }
})
.then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
});
When I carry out this request on my front-end, I get a response of :"DELETE http://localhost:3000/api/devices/4/ 403 (Forbidden)". Where 4 is the ID belonging to the record I would like to delete.
I am currently using Session Authentication in Django and I have passed in my CSRF Token value into the header of my request.
When I use other methods like PUT and POST on forms, they work fine. But, not DELETE
What am I doing wrong to receive this error?
Turns out I just needed to remove the empty body in the Axios request.
axios.delete(`api/devices/${data.id}/`, {
headers: {'X-CSRFToken': csrftoken }
})
.then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
});

Django REST with React: axios PATCH with FormData not updating any data

I am trying to make a form that edits the user's profile data and uses the patch method to change all the fields except the username because the username is the primary key and only identifier of a specific user.
Update:
-I changed it to a regular PATCH method and the data does not update
-I also made sure formData sends the correct data, which it does
From reading previous questions, I've learned that a normal axios.patch method does not work with FormData and I've followed the instructions of adding:
formData.append("_method", "PATCH")
and changing the axios method to axios.put, however, I still receive a 400 error which states, in the data section:
username: ["This field is required."]
Help would be much appreciated. Thank you, kind strangers!
Edit Profile Submit:
onSubmit = (e) => {
e.preventDefault();
const { firstName, lastName, profile } = this.state;
const username = localStorage.getItem("username");
formData.append("_method", "PATCH");
formData.append("firstName", firstName);
formData.append("lastName", lastName);
formData.append("profile_picture", profile);
this.props.onUpdate(formData, username);
};
Axios Request
export const userUpdate = (formData, username) => {
axios
.post(`http://127.0.0.1:8000/user/api/${username}`, {
formData,
headers: { "Content-Type": "application/x-www-form-urlencoded" },
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error.response);
});
};
User models.py
class User(models.Model):
firstName = models.CharField(max_length = 20, blank = True, default='Anonymous')
lastName = models.CharField(max_length = 25, blank = True, default='')
username = models.CharField(max_length = 50, unique=True, primary_key=True)
profile_picture = models.ForeignKey('upload.Profile', on_delete=models.CASCADE, null=True)
Profile Picture models.py
class Profile(models.Model):
image = models.ImageField(blank=False, null=False, upload_to=profile_path, default='f_profile.jpg')
You are supposed to be using PATCH if you want a patch request.
export const userUpdate = (formData, username) => {
axios
.patch(`http://127.0.0.1:8000/user/api/${username}`, {
formData,
headers: { "Content-Type": "application/x-www-form-urlencoded" },
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error.response);
});
};
Also, drop the _method from the form. Unless you have a specific view to make something of it, you won't need it.

Get UID and token obtain from password reset in react form

I am working on password reset and I have used django rest-auth, I have successfully got the token and uid from email link by hitting rest-auth/password/reset/,
but for to confirm I want the token and uid in react form so I can change it how can I get the uid and token which the rest auth return in email link in react js form
axios.post('http://127.0.0.1:8000/rest-auth/password/reset/',payload)
.then(res=>{
console.log(res)
})
.catch(err=>{
console.log(err)
})
its working perfect and it returns me:
http://127.0.0.1:8000/rest-auth/password/reset/confirm/MQ/594-5faaa46be4277e6a1879/
how can I get the uid and token from url in react form?
You should configure your react router to get the params from url.
e.preventDefault();
fetch("http://127.0.0.1:8000/rest-auth/password/reset/confirm/", {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}, body: JSON.stringify({
"new_password1": this.state.new_password1,
"new_password2": this.state.new_password2,
"uid": this.props.match.params.uid,
"token": this.props.match.params.token,
})
})
// .then(response => response.json())
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})

How to reload an async belongsTo relationship?

The model I have:
Post = DS.Model.extend({
author: DS.belongsTo('user',{ async: true })
});
but the url for the author is /post/{id}/author and it is passed via a key-value in the links-hash of the payload:
{
post: {
id: 1,
links: {
author: 'author'
}
}
}
The data is retreived by post.get('author') which calls the url /posts/1/author.
But now I want to reload the author data. When I try:
post.get('author').then(function(author) {
author.reload();
});
the author is reloaded by calling /users/{author_id} instead of /posts/1/author. How can I fix this issue?