DRF APIView returns empty data object when using apisauce but not on browser view - reactjs

I am trying to query a model to check if an object exists or not using the following APIview function. Unfortunately i am not able to receive any response object in react native apisauce get function as shown below
apisauce function
const checkIfUserExists = (email) =>
client.get("/account/user-exists/?email=" + email);
APIView class
class UserExistsView(APIView):
"""Checks if user exists or not"""
def get(self, request, *args, **kwargs):
username = self.request.GET['email']
try:
user = models.UserProfile.objects.get(email=username)
except models.UserProfile.DoesNotExist:
return Response(data={'message': False})
else:
return Response(data={'message': True})
Results from the browser
What am i doing wrong here?
Print result on shell <Response status_code=200, "text/html; charset=utf-8">

You can do it simplier:
class UserExistsView(APIView):
"""Checks if user exists or not"""
def get(self, request, *args, **kwargs):
email = self.request.GET['email']
user_exists = models.UserProfile.objects.filter(email=email).exists()
return Response(
data={'message': user_exists}
)
If you create a QuerySet and then call .exists(), Django will call the SQL function checking only if the object is in the database, but it will not query it, which is much faster and desired in your call from JS.

Assuming you have a class base component, You could modify your function like below, track the user existence in state. I don't see any errors in your server-side code. but in your javascript code you didn't handle the promise.
checkUserExists= (email) => {
client.get("/account/user-exists/?email=" + email)
.then(response=>{
this.setState({isUserExists : response.data.messgae})
)
}

Related

How to upload files with DRF and React?

I'm learning Django Rest Framework, everything was going well until I had to create a service to upload files to my application.As much as I read the documentation, I can't understand it.
First I want to clarify that I am not a programming expert, I am a
newbie but I am here learning more every day.
From what I've managed to understand so far:
Documents and photos are not stored in the database. These files are stored in a folder.
This is correct ?
I have a form where it allows me to upload multiple files
example:
file.txt, document.doc, photo.png etc...
My view (Frontend):
import { useState } from "react";
import axios from "axios";
const Form = () => {
const [state_files, setState_Files] = useState(null);
const UploadFiles = function (event) {
setState_Files(event);
};
const InsertFiles = async function () {
const formData = new FormData();
for (let index = 0; index < state_files.length; index++) {
formData.append("files", state_files[index]);
}
await axios
.post("http://127.0.0.1:8000/api/v1/upload/", formData)
.then((response) => {
console.log(response.data);
})
.catch((error) => {
console.log(error);
});
};
return (
<>
<input
type="file"
name="files"
multiple
onChange={() => InsertFiles(event.target.files)}
/>
<button>Upload All files</button>
</>
);
};
export default Form;
Backend
url.py
path("upload/", Storage_View.as_view(), name="storage-index"),
storage/view.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.parsers import MultiPartParser
class Storage_View(APIView):
parser_classes = [MultiPartParser]
def put(self, request, filename, format=None):
file_obj = request.data['file']
# ...
# What do I have to do here?
# ...
return Response({'received data': request.data})
Questions:
Why don't I see the button to upload files using the DFR tool? see attached files
The documentation does not explain what I have to do inside the function comment
https://www.django-rest-framework.org/api-guide/parsers/
def put(...):
How do I specify the path where you have to store the files you upload?
Please I need guidance.
1: show your models for more detail. you have to use filefield or
imagefield in your model. You can google and read more about these
fields.
2: put is for update, write your post method to save data. You don't
have to really do anything serious there. just check if
serializer.is_Valid() for request.data and if valid do
serializer.save(). the file or image will be uploaded to upload_to
folder which you define in your model and you will get the link.
3: read more about upload_to in Django. you can define this with the
model field.
I used ModelViewSet and this is how the create method looks like -
def create(self, request, format=None):
data = request.data
if isinstance(data, list): # <- is the main logic
serializer = self.get_serializer(data=request.data, many=True)
else:
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
You are passing a list from frontend and by default, Django works on dictionary, so you will have to manage this. Think of this as your go to code and write your post method.
Feel free to write more if you have doubts, Hope this helps :)

aiohttp server - delete file after FileResponse return

I need to delete a temporary created file after it is returned to a request.
The used method looks like:
async def getBackup(self, request):
context = request.rel_url.query['sn']
filePath = createBackup(context)
return web.FileResponse(
path=filePath,
headers={
hdrs.CONTENT_TYPE: 'application/tar+gzip',
hdrs.CONTENT_DISPOSITION: f"attachement;filename=backup.tar.gz;filename*=UTF-8''backup.tar.gz;",
hdrs.CACHE_CONTROL: 'no-cache'
}
)
# os.unlink(filePath) after file has been served ....
I searched for a signal or callback approach but did not find anything in the documentation.
Any hint or suggestions to make it done?
Could you put it inside a context manager or a try/finally? For example:
async def get_backup(self, request):
async with aiofiles.tempfile.TemporaryFile('wb') as fp:
await create_backup(fp)
return web.FileResponse(path=fp.name)
Or the slightly uglier...
async def get_backup(self, request):
file = await create_backup()
try:
return web.FileResponse(path=file)
finally:
await sleep(1) # perhaps not needed
await aiofiles.os.remove(file)

how to get new data at run time from django?

I am working on a Django project with ReactJs frontend. I have to built a simple chat application in that project where users can communicate with each other.
in django views I have following function to read messages
Views.py
class MessagesListAPI(GenericAPIView, ListModelMixin ):
def get_queryset(self):
condition1 = Q(sender=15) & Q(receiver=11)
condition2 = Q(sender=11) & Q(receiver=15)
return Messages.objects.filter(condition1 | condition2)
serializer_class = MessagesSerializer
permission_classes = (AllowAny,)
def get(self, request , *args, **kwargs):
return self.list(request, *args, **kwargs)
this gives me all the messages between user 11 and user 15.
on frontend I am getting these messages from rest Api by calling above function
frontend
const chatApi = axios.create({
baseURL: 'http://localhost:8000/chat/'
})
const getMessages = async() => {
let data = await chatApi.get(`MessageRead/`).then(({data})=>data);
setMessages(data);
}
I am calling this function in an onClick event of button. and displaying the messages by maping messages array.
problem is that at the time when these messages are open to the user. at that time if a new message(data) is added in database. I have to press that button again and call getMessages function again to display that message.
Is there a way to automatically get that new message(record) without calling this function again by pressing a button?

ReactJS form submit this.props.history.push('/downloads') not linking through to the new page

I am trying to Push to a new page once a user has filled out a form using this.props.history.push inside the function below.
handleSubmit = async event => {
event.preventDefault()
try {
const res = await newEnquiry(this.state.formData)
this.props.history.push('/downloads')
console.log(res)
} catch (err) {
console.log(err.response.data)
}
}
The ReactJS form is working fine on the /contacts page, and submits information to my Django back-end so I know it's working OK, however I cannot get the redirect to work and it's giving me this error message.
<form onSubmit={this.handleSubmit}> is inside my form tag and that's working fine so I am pretty sure it's not a problem with my form.
Api.js
const baseUrl = '/api'
export const newEnquiry = formData => {
return axios.post(`${baseUrl}/enquiries/`, formData)
}
Views.py
class EnquiryListView(APIView):
def get(self, _request):
enquiries = Enquiries.objects.all()
serialized_enquiries = EnquirySerializer(enquiries, many=True)
return Response(serialized_enquiries.data, status=status.HTTP_200_OK)
def post(self, request):
created_enquiry = EnquirySerializer(data=request.data)
if created_enquiry.is_valid():
created_enquiry.save()
return Response(created_enquiry.data, status=status.HTTP_201_CREATED)
return Response(created_enquiry.errors)
serializers.py
class EnquirySerializer(serializers.ModelSerializer):
class Meta:
model = Enquiries
fields = '__all__'
In your case of this problem, when the error fires off, it is unable to read the err.response.data property. If there was no error, it would redirect you. In your Django app, check what the error handler is suppose to return.
Quick review of try/catch.
try {
// if everything passes, run this block
} catch (err) {
// if something goes wrong, run this block
}
In this case, be sure to check what your full error is. It might be a 404 or something totally unexpected.

AngularJS + django REST api

I'm attempting to build an api with DRF.
Client is a cordova app backed with AngularJS.
When I try to post some user object using $resource I'm getting a 403 forbidden response from django.
Below is some code which I think is relevant for the issue:
The API Call:
$rootScope.user =
User.get({id: response.id}).$promise.then(angular.noop, function (e) {
if (e.status == 404) { //If not found, register the user.
$rootScope.user = new User();
Object.keys(response).forEach(function (key) {
$rootScope.user[key] = response[key];
});
$rootScope.user.$save(); //Fails here! 403.
}
else
console.log(JSON.stringify(e.msg));
});
The User factory:
.factory('User', function ($resource, serverConstants) {
return $resource(serverConstants.serverUrl + '/users/:id');
})
django view:
# Users
class UserSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.CharField(max_length=100,required=True)
email = serializers.EmailField(required=False,allow_blank=True)
joined = serializers.DateField(required=False,default=datetime.date.today)
class Meta:
model = models.User
fields = ('joined', 'id', 'email')
def get_validation_exclusions(self):
exclusions = super(UserSerializer, self).get_validation_exclusions()
return exclusions + ['owner']
class UserViewSet(viewsets.ModelViewSet):
queryset = models.User.objects.all()
serializer_class = UserSerializer
PS: I've configured angular to use CSRF cookie and django to allow CORS
Thanks in advance!
Your /user/:id endpoint requires authenticated requests.
You need to authenticate your client's requests using one of the methods specified on the previous link.
Given your app runs in a WebView and then has a builtin cookies handling, SessionAuthentication is the more straightforward to implement.
If you want the endpoint to not require authentication, you can set its permission_classes attribute like so:
from rest_framework.permissions import AllowAny
class UserViewSet(viewsets.ModelViewSet):
queryset = models.User.objects.all()
serializer_class = UserSerializer
permission_classes = (AllowAny, )
I guess with DRF you mean the django-rest-framework.
If yes, have a look here:
http://www.django-rest-framework.org/api-guide/authentication/
You can make the view public but using AllowAny.
from rest_framework.permissions import AllowAny
from rest_framework import generics
restapi_permission_classes = (AllowAny,)
class MyListView(generics.ListCreateAPIView):
serializer_class = MyObjectSerializer
permission_classes = restapi_permission_classes
queryset = MyObject.objects.all()
However I'd recommend you to use proper authentication once you are done with testing. I've been using the token authentication.
Have a look at this post for more details:
Django Rest Framework Token Authentication

Resources