I have a application that allows me to login a user, which I create on the backend, and then I want to post a file to my backend from the frontend. I am using the Django user model which allows me to post the profile info to login. Once im logged in I get a error 405, I believe this means my views.py isnt working properly. Can someone explain how to make this post request correctly? Is there any standard model I can incorporate to make this work like the user model? Maybe CreateApiView?
Here is my backend:
Views.py
from rest_framework.response import Response
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
from base.serializer import *
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
token['username'] = user.username
return token
class MyTokenObtainPairView(TokenObtainPairView):
serializer_class = MyTokenObtainPairSerializer
@api_view(['GET'])
def getRoutes(request):
routes = [
'/api/token/',
'/api/register/',
'/api/token/refresh/',
'/api/prediction/'
'api/uploads/',
'api/upload/<int:pk>/',
'api/upload/<int:pk>/update/',
'api/upload/<int:pk>/delete/',
'api/upload/myuploads/',
'api/upload/create/',
'api/profile/',
'api/profile/update/',
'api/users/<int:pk>/upload',
]
return Response(routes)
#############################ADD THIS############################################
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def getUploads(request):
public_upload = Upload.objects.filter(is_public=True).order_by('-updated')[:10]
user_upload = request.user.uploads.all().order_by('-updated')[:10]
uploads = public_upload | user_upload
serializer = uploadsSerializer(uploads, many=True)
return Response(serializer.data)
#api/upload/<int:pk>
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def getUpload(request, pk):
upload = request.user.upload.get(id=pk)
serializer = uploadSerializer(upload, many=False)
return Response(serializer.data)
#api/upload/<int:pk>/update
@api_view(['PATCH'])
@permission_classes([IsAuthenticated])
def updateUpload(request, pk):
upload = request.user.upload.get(id=pk)
serializer = uploadSerializer(instance=upload, data=request.data, context={'request': request})
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
#api/upload/<int:pk>/delete
@api_view(['DELETE'])
@permission_classes([IsAuthenticated])
def deleteUpload(request, pk):
upload = request.user.upload.get(id=pk)
upload.delete()
return Response('File was deleted')
#api/upload/create
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def createUpload(request):
user = request.user
data = request.data
upload = Upload.objects.create(
user=user,
photo=data['photo']
)
serializer = upploadSerializer(upload, many=False)
return Response(serializer.data)
#api/upload/user/<int:pk>/myuploads
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def getUserUpload(request, pk):
user = Profile.objects.get(id=pk)
uploads = Upload.objects.filter(user=user)
serializer = uploadSerializer(uploads, many=True)
return Response(serializer.data)
##################################################################################
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_profile(request):
user = request.user
profile = user.profile
serializer = ProfileSerializer(profile, many=False)
return Response(serializer.data)
urls.py
from django.urls import path
from . import views
from .views import MyTokenObtainPairView
from rest_framework_simplejwt.views import (
TokenRefreshView,
)
urlpatterns = [
path('upload/', views.getUploads, name="uploads"),
path('upload/<int:pk>/', views.getUpload, name="upload"),
path('upload/<int:pk>/update/', views.updateUpload, name="update-upload"),
path('upload/<int:pk>/delete/', views.deleteUpload, name="delete-upload"),
path('users/<int:pk>/uploads',views.getUserUpload, name="my-uploads"),
path('upload/create/', views.createUpload, name="create-upload"),
##############################################
#path('upload/create/', views.createUpload, name="create-upload"),
#path('upload/', views.getUpload),
path('profile/', views.get_profile),
path('token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
models.py
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
from django.contrib.auth.models import AbstractUser
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField()
def __str__(self):
return self.user.username
class Upload(models.Model):
user = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True, blank=True, related_name='upload')
#title = models.CharField(max_length=100, null=True, blank=True)###safe as default or have user change
photo = models.FileField(upload_to="upload")
created=models.DateField(default=timezone.now)
updated = models.DateTimeField(auto_now=True)
is_public = models.BooleanField(default=False)
#This is the string representation of the object
def __str__(self):
return str(self.created)
Here is my frontend for fileUpload.
import React, { useState, useEffect, useContext } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import AuthContext from '../context/AuthContext';
function FileUpload({ setUploads = () => {} }) {
const navigate = useNavigate();
const { id } = useParams();
const [photo, setPhoto] = useState(null);
const { authTokens, logoutUser } = useContext(AuthContext);
const accessToken = String(authTokens.access);
useEffect(() => {
if (id) {
fetch(`http://xxxxxxx:8000/api/upload/${id}/`, {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + accessToken,
},
})
.then(response => response.json())
.then(data => {
setPhoto(data.photo.name);
})
.catch(error => {
console.error('Error fetching photo:', error);
});
}
}, [id, accessToken]);
const handleSubmit = async (e) => {
e.preventDefault();
const formData = new FormData();
formData.append('photo', photo);
try {
let response;
if (id) {
response = await fetch(`http//xxxxxxxx:8000/api/upload/${id}/`, {
method: 'PATCH',
headers: {
'Authorization': 'Bearer ' + accessToken,
},
body: formData,
});
} else {
response = await fetch('http://xxxxxxx:8000/api/upload/', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + accessToken,
},
body: formData,
});
}
const data = await response.json();
if (!response.ok) {
throw new Error(data.message || 'Something went wrong');
}
if (id) {
setUploads((prevUploads) =>
prevUploads.map((upload) => (upload.id === data.id ? data : upload))
);
alert('File updated successfully!');
navigate(`/upload/${data.id}`);
} else {
setUploads((prevUploads) => [data, ...prevUploads]);
alert('Upload created successfully!');
navigate('/');
}
setPhoto(null);
} catch (error) {
console.error('Error uploading photo:', error);
}
};
return (
<div className="container mx-auto px-4">
<form onSubmit={handleSubmit}>
<div className="mb-4">
<label htmlFor="photo" className="block font-medium text-gray-700">
Photo/File
</label>
<input
type="file"
name="photo"
id="photo"
onChange={(e) => setPhoto(e.target.files[0])}
className="border border-gray-400 rounded w-full px-3 py-2 mt-1 text-gray-900"
/>
</div>
<div className="mt-6">
<button
type="submit"
className="bg-blue-500 text-white font-medium py-2 px-4 rounded hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-600 focus:ring-offset-2"
>
{id ? 'Update Upload' : 'Create Upload'}
</button>
</div>
</form>
</div>
);
}
export default FileUpload;
I rewrote my frontend fileupload, I added server to whitelist, I added a proxy on the frontend.
Now I am thinking of how to rewrite the views so that post request can be made.
Here are the specific errors:
-405 Method Not Allowed
Referrer Policy:
strict-origin-when-cross-origin
Error uploading photo: Error: Something went wrong
Backend:
Method Not Allowed: /api/upload/
[19/May/2024 20:50:21] "POST /api/upload/ HTTP/1.1" 405 41
user25043725 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.