Delete Django model with AJAX call - django

I am writing a photogallery app, which is using Django Rest Framework API.
I fill the data in Django models (images and descriptions) with said API using AJAX (specifically axios).
The question is - is it possible not only to POST data, but to delete it from my frontend app and I mean model instance - like it's done in the admin interface or even delete all model instances.

Yes, you can for example add a .delete(..) implementation as well:
class SomeModelDetail(APIView):
def get_object(self, pk):
try:
return SomeModel.objects.get(pk=pk)
except SomeModel.DoesNotExist:
raise Http404
# ...
def delete(self, request, pk, format=None):
self.get_object(pk).delete()
return Response(status=status.HTTP_204_NO_CONTENT)
The HTTP_204_NO_CONTENT response is thus a status code that is sometimes used to indicate that the corresponding object is now removed.
If we then add this view to the URL:
from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from app import views
urlpatterns = [
url(r'^somemodel/(?P<pk>[0-9]+)/$', views.SomeModelDetail.as_view()),
]
format_suffix_patterns(urlpatterns)
We can then make a DELETE AJAX call:
# JavaScript (Ajax request)
$.ajax({
url: 'http://localhost:8080/someapp/somemodel/123/',
type: 'DELETE',
data: {},
contentType:'application/json',
dataType: 'text',
error: function(result){},
success: function(result) {}
});
We thus perform a DELETE method request, for a specific somemodel instance (here with primary key 123, although you have to fill that in yourself with a sensical one).

Related

How to handle MethodNotallowed exception in django rest framework by creating seperate file for exceptions

In my Django RestApi project I want to apply Exceptions errors. I create a separate file (common.py) for all my exceptions file is located out side the project where our manage.py file located. this is in my file:
HTTP_STRING = {
'get': 'get',
'post': 'post',
'put': 'put',
'patch': 'patch',
'delete': 'delete',
}
Also I set it in settings.py:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
Now In my view I create a modelviewset. In modelviewset we get all built in functions to perform oprations like (put, patch, delete, create, update) but in this view I don't need put, patch, and delete. So I want to block this and want to give exception on it I tried this :
from rest_framework import viewsets
from common_strings import HTTP_STRING
class DemoModelViewSet(viewsets.ModelViewSet):
queryset = DemoModel.objects.all()
serializer_class = DemoModelSerializer
def update(self, request, pk=None):
raise MethodNotAllowed(method=HTTP_STRING['put'])
def partial_update(self, request, pk=None):
raise MethodNotAllowed(method=HTTP_STRING['patch'])
def destroy(self, request, pk=None):
raise MethodNotAllowed(method=HTTP_STRING['delete'])
But giving error on MethodNotAllowed is not defined. Why this is happenning?
I was having a similar issue.
According to the exceptions page on Django REST framework website, I think you have to import the exceptions module.
Importing the exceptions module would look something like:
from rest_framework import exceptions
and then raising the exceptions would look like,
exceptions.MethodNotAllowed(method=HTTP_STRING['put'])
exceptions.MethodNotAllowed(method=HTTP_STRING['delete'])
exceptions.MethodNotAllowed(method=HTTP_STRING['patch'])

Django/drf - delete method

I want to delete likes from my Likes table. for which I am making an axios call from the front end with
axios({
method: "delete",
url:http://127.0.0.1:8000/api/delete/,
params: { companyid: xyz }
})
It is supposed to delete a like that has company_id = xyz in it.
The Url looks like this
path('delete/', DeleteLikesView.as_view()),
(/api/ is included in the project's urls.py. So taken care of...)
and the DeleteLikesView -
class DeleteLikesView(DestroyAPIView):
queryset = Likes.objects.all()
serializer_class = LikesSerializer
def perform_destroy(self, request):
print(self.kwargs['companyid'])
companyid = self.kwargs['companyid']
instance = Likes.objects.get(
company_id=companyid, user_id=request.user.id)
instance.delete()
I am either being stuck with errors 403 (csrf_token error. Although I tried using csrf_exempt, no luck) or 405 method not allowed(for which I refered this. the solution in this question puts me back with 403 error)
Any help is appreciated. Thank!
Set xsrfHeaderName in request as below:
// ...
xsrfHeaderName: "X-CSRFToken",
// ...
Add CSRF_COOKIE_NAME in settings.py
CSRF_COOKIE_NAME = "XSRF-TOKEN"
You can use token authentication,instead of basicauth, if you use token auth, then csrf error will not come.
You have written
instance = Likes.objects.get(company_id=companyid, user_id=request.user.id)
in above code, user_id = request.user.id will not work cause you are not logged in the session.You are using api ,u need to provide a token to tell which user is accessing the api.
You have to use decorating the class.
To decorate every instance of a class-based view, you need to decorate the class definition itself. To do this you apply the decorator to the dispatch() method of the class.
from django.views.decorators.csrf import csrf_exempt
class DeleteLikesView(DestroyAPIView):
...
#method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
def perform_destroy(self, request):
...
See more info:
https://docs.djangoproject.com/en/2.2/topics/class-based-views/intro/#decorating-the-class

Returning objects using JSONRESPONSE

I'm trying to return an object using Jsonresponse, Sorry im newb
This is my script:
setInterval(function()
{
$.ajax({
url: '/check_notification/',
type: "POST",
dataType: 'json',
success: function (data) {}
});
}, 2000);
in my django views.py:
def check_notification(request):
user = request.user
profile = Person.objects.get(profile=user)
notification = NotificationRecipient.objects.filter(profile=profile)
return JsonResponse(model_to_dict(notification))
You can make a model Serializers for models you want to pass as response. for more information read django rest framework tutorial about serializers an learn how to make json response. Or if you have a simple dictionary you can make json response with this code snippet at the end of your check_notification function. return HttpResponse(json.dumps(your dictionary))
I would recommend you use Django Rest Framework for returning Responses in JSON format as the Serialization of models can be don easily. You can start from here. There you will find something known as a ModelSerializer. Basically you create a serializer.py in your app folder with the following content:
from rest_framework import serializers
from .models import Person, NotificationRecipient
class PersonSerializers(serializers.ModelSerializer):
class Meta:
model = Person
fields = '__all__'
class NotificationRecipientSerializers(serializers.ModelSerializer):
class Meta:
model = NotificationRecipient
fields = '__all__'
The above code will serialize your models which means will be converted to json format.
Than in a file named as views_api.py, you can create a class that will be called using by the URL and will have your queryset defined. In your case the class will be defined as:
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Person, NotificationRecipient
from .serializers import NotificationRecipientSerializers
class NotificationAPIView(APIView):
def get(self,request):
user = request.user
profile = Person.objects.get(profile=user)
notification = NotificationRecipient.objects.filter(profile=profile)
return Response(notification)
This will return the response in JSON format. In your urls.py file call the NotificationAPIView as follows:
from django.urls import path
from .import views_api
urlpatterns = [
path('check/notification/', views_api.NotificationAPIView.as_view(), name='notification'),
]
Hope you get a basic understanding of what is going on there. For better understanding go through Django Rest Framework docs.

allow post requests in django REST framework

I am creating a simple rest api using django REST framework. I have successfully got the response by sending GET request to the api but since I want to send POST request, the django rest framework doesn't allow POST request by default.
As in image(below) only GET,HEAD, OPTIONS are allowed but not the POST request
The GET and POST methods inside of views.py
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from profiles_api import serializers
from rest_framework import status
# Create your views here.
class HelloApiView(APIView):
"""Test APIView"""
#Here we are telling django that the serializer class for this apiViewClass is serializer.HelloSerializer class
serializer_class = serializers.HelloSerializer
def get(self, request, format=None):
"""Retruns a list of APIViews features."""
an_apiview = [
'Uses HTTP methods as fucntion (get, post, patch, put, delete)',
'It is similar to a traditional Django view',
'Gives you the most of the control over your logic',
'Is mapped manually to URLs'
]
#The response must be as dictionary which will be shown in json as response
return Response({'message': 'Hello!', 'an_apiview': an_apiview})
def post(self,request):
"""Create a hello message with our name"""
serializer = serializer.HelloSerializer(data=request.data)
if serializer.is_valid():
name = serializer.data.get('name')
message = 'Hello! {0}'.format(name)
return Response({'message':message})
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
How to allow POST requests in django REST framework?
The problem with the code was, you have added the def post() after the return statement.
To solve, just correct your indentation level as below,
class HelloApiView(APIView):
def get(self, request, format=None):
return Response()
def post(self, request):
return Response()

Django Forms with ReactJS

I have Django forms rendered using Django templates. Now I want to add a React component to one of the form fields (and perhaps to more than one field in the long term).
Based on what I have read so far, its seem best not to mix Django templating with React rendering and have Django serve only as backend API sending JSON data to React, while React takes over the entire form rendering. So I am now trying to re-render my forms entirely through React.
Instead of forms.py, I have now created serializers.py to define what data is to be sent to React and have Django Rest Framework setup in my environment. Now I am trying to figure out how to send this data across. There are some good online tutorials (and SO posts) that talk about integrating Django/DRF with React but havent found a single example of end-to-end form rendering through React and DRF.
Specifically, can anyone let me know what do I really write in my view that can then be useful for the GET request from React that tries to fetch the form data? A web reference or just the broad steps needed should be enough for me to get started (and to dig in more into the docs).
Update:
Also adding a simplified version of the serializers.py code here:
from .models import Entity
from rest_framework import serializers
class EntitySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Entity
fields = ['name', 'role', 'location']
First, i think you need to check related React documentation about forms with multiple inputs. It gives you base idea about how things should be structured in React side.
About fetching data from server, you can try something like this in componentDidMount:
componentDidMount() {
// Assuming you are using jQuery,
// if not, try fetch().
// Note that 2 is hardcoded, get your user id from
// URL or session or somewhere else.
$.get('/api/profile/2/', (data) => {
this.setState({
formFields: data.fields // fields is an array
});
});
}
Then you can create your html input elements in render method with something like this:
render () {
let fields = this.state.formFields.map((field) => {
return (
<input type="text" value={field.value} onChange={(newValue) => {/* update your state here with new value */ }} name={field.name}/>
)
});
return (
<div className="container">
<form action="">
{fields}
<button onClick={this.submitForm.bind(this)}>Save</button>
</form>
</div>
)
}
And here is your submitForm method:
submitForm() {
$.post('/api/profile/2/', {/* put your updated fields' data here */}, (response) => {
// check if things done successfully.
});
}
Update:
Here is an untested-but-should-work example for your DRF view:
from rest_framework.decorators import api_view
from django.http import JsonResponse
from rest_framework.views import APIView
class ProfileFormView(APIView):
# Assume you have a model named UserProfile
# And a serializer for that model named UserSerializer
# This is the view to let users update their profile info.
# Like E-Mail, Birth Date etc.
def get_object(self, pk):
try:
return UserProfile.objects.get(pk=pk)
except:
return None
# this method will be called when your request is GET
# we will use this to fetch field names and values while creating our form on React side
def get(self, request, pk, format=None):
user = self.get_object(pk)
if not user:
return JsonResponse({'status': 0, 'message': 'User with this id not found'})
# You have a serializer that you specified which fields should be available in fo
serializer = UserSerializer(user)
# And here we send it those fields to our react component as json
# Check this json data on React side, parse it, render it as form.
return JsonResponse(serializer.data, safe=False)
# this method will be used when user try to update or save their profile
# for POST requests.
def post(self, request, pk, format=None):
try:
user = self.get_object(pk)
except:
return JsonResponse({'status': 0, 'message': 'User with this id not found'})
e_mail = request.data.get("email", None)
birth_date = request.data.get('birth_date', None)
job = request.data.get('job', None)
user.email = e_mail
user.birth_date = birth_date
user.job = job
try:
user.save()
return JsonResponse({'status': 1, 'message': 'Your profile updated successfully!'})
except:
return JsonResponse({'status': 0, 'message': 'There was something wrong while updating your profile.'})
And this is related url for this view:
urlpatterns = [
url(r'^api/profile/(?P<pk>[0-9]+)/$', ProfileFormView.as_view()),
]