I am new in Django and python. Now I am trying to do web API with Django and python. I can get the get request but when I request the post method, this error is shown
"non_field_errors": [
"No data provided"
]
View.py=>
from rest_framework.generics import get_object_or_404
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Allowance
from .serializers import AllowanceSerializer
# Create your views here.
class AllowanceAPIView(APIView):
def get(self,request,pk=None):
if pk:
allowance=get_object_or_404(Allowance.objects.all(),pk=pk)
serializer = AllowanceSerializer(allowance)
return Response({serializer.data})
allowance=Allowance.objects.all()
serializer = AllowanceSerializer(allowance,many=True)
return Response({"allowance":serializer.data})
def post(self,request):
allowance = request.data.get('allowance')
serializer = AllowanceSerializer(data=allowance)
if serializer.is_valid(raise_exception=True):
allowance_saved=serializer.save()
return Response({"success":"Allowance '{}' created successfully".format(allowance_saved.AllowID)})
def put(self,request,pk):
save_allowance = get_object_or_404(Allowance.objects.all(),pk=pk)
data = request.data.get('allowance')
serializer = AllowanceSerializer(instance=save_allowance,data=data,partial=True)
if serializer.is_valid(raise_exception = True):
allowance_saved=serializer.save()
return Response({"sucess": "Allowance '{}' updated successfully".format(allowance_saved.AllowID)})
def delete(self,request,pk):
#Get object with this pk
allowance = get_object_or_404(Allowance.objects.all(),pk=pk)
allowance.delete()
return Response({"message":"Allowance with id '{}' has been deleted.".format(pk)},status=204)
urls.py inside app =>
from django.conf.urls import url
from .views import AllowanceAPIView
urlpatterns = [
url(r'^$', AllowanceAPIView.as_view(), name='post-listcreate'),
url(r'^(?P<pk>\d+)/$', AllowanceAPIView.as_view(), name='post-listcreate')
]
urls.py inside project =>
from django.conf.urls import url, include
from django.contrib import admin
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
url(r'^admin/', admin.site.urls),
# url(r'^api/auth/login/$', obtain_jwt_token, name='api-login'),
url(r'^api/allowances_mas/', include('tmswebapi.urls')),
]
sample API request=>
{
"AllowID": "Allow1",
"AllowDesc": "Allow1 Description",
"AllowAmt": "11.00",
"AllowType": "MEAL",
"Created_DT": "2019-06-18T18:09:00Z",
"Created_Usr": "Admin",
"LastModified_Usr": "",
"LastModified_DT": "2019-06-18T18:09:00Z"
}
Serializer =>
from rest_framework import serializers
import datetime
from .models import Allowance
class AllowanceSerializer(serializers.ModelSerializer):
class Meta:
model=Allowance
fields = "__all__"
def create(self,validated_data):
return Allowance.objects.create(**validated_data)
def update(self,instance,calidated_data):
instance.AllowDesc = validated_data.get('AllowDesc',instance.AllowDesc)
instance.AllowAmt = validated_data.get('AllowAmt',instance.AllowAmt)
instance.AllowType = validated_data.get('AllowType',instance.AllowType)
instance.LastModified_Usr = "Admin"
instance.LastModified_DT = datetime.datetime.now()
instance.save()
return instance
Is it because of urls or because of data format?
It's returning error from on of if serializer.is_valid(raise_exception = True): lines.
It means data is None somewhere.
Debug your code to make sure data variable has data
def post(self,request):
allowance = request.data
serializer = AllowanceSerializer(data=allowance)
if serializer.is_valid(raise_exception=True):
allowance_saved=serializer.save()
return Response({"success":"Allowance '{}' created successfully".format(allowance_saved.AllowID)})
Now try this
Related
Models.py
from django.db import models
# Create your models here.
class reviewData(models.Model):
building_name = models.CharField(max_length=50)
review_content = models.TextField()
star_num = models.FloatField()
class buildingData(models.Model):
building_name = models.CharField(max_length=50)
building_loc = models.CharField(max_length=50)
building_call = models.CharField(max_length=20)
views.py
# Create your views here.
from django.shortcuts import render
from rest_framework.response import Response
from .models import reviewData
from .models import buildingData
from rest_framework.views import APIView
from .serializers import ReviewSerializer
class BuildingInfoAPI(APIView):
def get(request):
queryset = buildingData.objects.all()
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
class ReviewListAPI(APIView):
def get(request):
queryset = reviewData.objects.all()
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
urls.py
from django.contrib import admin
from django.urls import path
from crawling_data.views import ReviewListAPI
from crawling_data.views import BuildingInfoAPI
urlpatterns = [
path('admin/', admin.site.urls),
path('api/buildingdata/', BuildingInfoAPI.as_view()),
#path('api/buildingdata/(I want to put building name here)', ReviewListAPI.as_view())
]
I am making review api.
I want to use building name as url path to bring reviews for specific buildings
For example, there are a, b, c reviews
a, b reviews are for aaabuilding
c reviews are for xxxbuilding
api/buildingdata/aaabuilding (only shows aaabuilding review)
{
building_name = aaabuilding
review_content = a
star_num = 5
building_name = aaabuilding
review_content = b
star_num = 3
}
api/buildingdata/xxxbuilding (only shows xxxbuilding review)
{
building_name = xxxbuilding
review_content = c
star_num = 4
}
I've searched some dynamic url posts, but they were not that i want.
Is there any way to bring building name into url from db?
In urls.py
path('api/buildingdata/<str:building>/', BuildingInfoAPI.as_view()),
And in views.py
class BuildingInfoAPI(APIView):
def get(request, building):
queryset = buildingData.objects.filter(building_name__contains=building)
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
Hope this will solve the issue
I suggets you take a look at the django documentation, this is pretty well explained there, here is a useful link
In your urls.py, you should put:
from django.contrib import admin
from django.urls import path
from crawling_data.views import ReviewListAPI
from crawling_data.views import BuildingInfoAPI
urlpatterns = [
path('admin/', admin.site.urls),
path('api/buildingdata/', BuildingInfoAPI.as_view()),
# added <str:building> to url
path('api/buildingdata/<str:building>', ReviewListAPI.as_view())
]
And in your views.py:
# Create your views here.
from django.shortcuts import render
from rest_framework.response import Response
from .models import reviewData
from .models import buildingData
from rest_framework.views import APIView
from .serializers import ReviewSerializer
class BuildingInfoAPI(APIView):
def get(request):
queryset = buildingData.objects.all()
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
class ReviewListAPI(APIView):
# added another argument, retrieved from url
def get(request, building):
# changed .all() to .filter()
queryset = reviewData.objects.filter(building_name = building)
serializer = ReviewSerializer(queryset, many=True)
return Response(serializer.data)
I'm trying the RetrieveUpdateDeleteAPIView and my update method gives me a key error every time I update a course object
THE UPDATE METHOD WORKS
api_views.py
from rest_framework.generics import (
RetrieveUpdateDestroyAPIView
)
from .serializers import CourseSerializer
from .models import Course
from django.core import cache
class CourseRetrieveUpdateDestroy(RetrieveUpdateDestroyAPIView):
queryset = Course.objects.all()
lookup_field = 'id'
serializer_class = CourseSerializer
def delete(self, request, *args, **kwargs):
course_id = request.data.get('id')
response = super().delete(request, *args, **kwargs)
if response.status_code == 204:
cache.delete('course_data_{}'.format(course_id))
return response
def update(self, request, *args, **kwargs):
response = super().update(request, *args, **kwargs)
if response.status_code == 200:
from django.core.cache import cache
course = response.data
cache.set('course_data_{}'.format(course['id']), {
'title' : course['title'],
'description': course['description'],
'featured': course['featured'],
})
return response
serializers.py
from rest_framework import serializers
from .models import Course
class CourseSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = ('title', 'description', 'issued_at', )
def to_representation(self, instance):
data = super().to_representation(instance)
data['time_passed'] = instance.time_passed()
data['is_fresh'] = instance.is_fresh
return data
urls.py
from django.urls import include, path
from django.conf import settings
from django.conf.urls.static import static
from .views import (
CourseListView,
CourseDetailView
)
from .api_views import (
#CourseList,
#CourseCreate,
CourseRetrieveUpdateDestroy
)
app_name = 'courses'
urlpatterns = [
path('', CourseListView.as_view(), name="course_list"),
path('course/<int:pk>/', CourseDetailView.as_view(), name="course_detail"),
#api-views
path('api/course/<int:id>/', CourseRetrieveUpdateDestroy.as_view(), name="course_rud_api"),
#path('api/list/', CourseList.as_view(), name="course_list_api"),
#path('api/create/', CourseCreate.as_view(), name="course_create_api"),
]
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
**Whenever I try to update an object of given id and hit enter, a KeyError at /courses/api/course/2/ is returned (id=2 as an example)
'id' being the key.
Why does it give me a key error for fields that I have not requested to serialize in the serializers.py? The model updates even after it redirects me to the error page.
How do i resolve this error or avoid this error page?
You didnt include the id field in your serializer fields, so it will not be in the response data. Try this:
class CourseSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = ('id', 'title', 'description', 'issued_at', )
id will by default be a read-only field. So the user cannot override it when sending data, but it will be in the sent response data.
I have a Django 2.2 that has two apps - status and updates:
django_api
|
status
|
api
|
updates
In django_api/urls.py:
from django.contrib import admin
from django.urls import include, path
from updates.views import (
json_example_view,
JsonCBV,
JsonCBV2,
SerializedListView,
SerializedDetailView
)
from status.api.views import
StatusListSearchAPIView
urlpatterns = [
path('admin/', admin.site.urls),
path('api/status/', status.api.urls),
path('api/updates/', updates.api.urls),
In django_api/status/api/views.py:
from rest_framework import generics
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import StatusSerializer
from status.models import Status
class StatusListSearchAPIView(APIView):
permission_classes = []
authentication_classes = []
def get(self, request, format = None):
qs = Status.objects.all()
serializer = StatusSeralizer(qs, many = True)
return Response(serializer.data)
def post(self, request, format=None):
qs = Status.objects.all()
serializer = StatusSeralizer(qs, many = True)
return Response(serializer.data)
class StatusAPIView(generics.ListAPIView):
permission_classes = []
authentication_classes = []
queryset = Status.objects.all()
serializer_class = StatusSeralizer
def get_queryset(self):
qs = Status.objects.all()
query = self.request.GET.get('q')
if query is not None:
qs = qs.filter(content_icontains = query)
return qs
In django_api/status/api/serializers.py:
from rest_framework import serializers
from django import forms
from status.models import Status
class StatusSerializer(serializers.ModelSerializer):
class Meta:
model = Status
fields = [
'user',
'content',
'image']
def validate_content(self, value):
if len(value) > 10000:
raise serializers.ValidationError("This is way too long.")
return value
def validate(self, data):
content = data.get("content", None)
if content == "":
content = None
image = data.get("image", None)
if content is None and image is None:
raise serializers.ValidationError("content or image is required.")
return data
When I run python manage.py runserver, I am getting an error:
File "...\status\api\views.py", line 26, in StatusAPIView
serializer_class = StatusSeralizer
NameError: name 'StatusSeralizer' is not defined
Updated: as indicated, this was a spelling error. However, after I imported status and from status.api imported urls, I am getting this error:
...\urls.py", line 39, in <module>
path('api/status/', status.api.urls),
...File "C:\Users\fbagi\AppData\Roaming\Python\Python37\site-
packages\django\urls\conf.py", line 73, in _path
raise TypeError('view must be a callable or a list/tuple in the case of
include().')
TypeError: view must be a callable or a list/tuple in the case of
include().
This is my status/api/urls.py:
from django.contrib import admin
from django.urls import path
from .views import StatusAPIView, StatusCreateAPIView
urlpatterns = [
path('/', StatusAPIView.as_view()),
path('create/', StatusCreateAPIView.as_view()),
]
Why am I getting this error?
It's a typo:
You are calling: StatusSeralizer but it is: StatusSerializer
I dont see StatusCreateAPIView in you views file. Have you created this view?
Try just commenting or removing path('create/', StatusCreateAPIView.as_view()), and see If you still get an error.
Try it bro:
from rest_framework import status.
Tell me if you have sucess!
1.I am trying to develop a simple blog using django 2.0.3. in the view.py when i was trying to redirect to page from edit.html or create.html it is redirecting to it self when i was giving the url manually it is still loading to same page i don't know why.
views.py
from django.shortcuts import render,get_object_or_404,redirect
from django.http import HttpResponseRedirect,HttpResponse
from posts.models import Post
from posts.forms import PostForm
from django.contrib import messages
from django.urls import reverse
def post_create(request):
form = PostForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
HttpResponseRedirect(instance.get_absolute_url())
context = {"title":"Create Blog","form":form}
return render(request,"create.html",context)
def post_detail(request,id):
instance = get_object_or_404(Post,id=id)
context = {
"title": instance.title,
"instance":instance
}
return render(request,"detail.html",context)
def post_update(request,id):
instance = get_object_or_404(Post,id=id)
form = PostForm(request.POST or None,instance=instance)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
messages.success(request,"Saved")
HttpResponseRedirect(instance.get_absolute_url())
context = {
"title": "Edit Blog",
"instance":instance,
"form":form
}
return render(request,"edit.html",context)
def post_delete(request):
context = {"title":"Delete"}
return HttpResponse("<h1>delete</h1>")
def post_list(request):
queryset = Post.objects.all().order_by('-timestamp')
context = {
"title":"List",
"object_list":queryset
}
return render(request,"index.html",context)
2.this my urls.py
urls.py
from django.contrib import admin
from django.urls import path,include,re_path
from . import views
app_name = 'posts'
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^$',views.post_list,name="list"),
re_path(r'^create/$',views.post_create,name="create"),
re_path(r'^(?P<id>\d+)/$',views.post_detail,name="detail"),
re_path(r'^(?P<id>\d+)/edit/$',views.post_update,name="update"),
re_path(r'^delete$',views.post_delete),
]
3.this my models.py
model.py
from django.db import models
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=120)
content = models.TextField()
timestamp = models.DateTimeField(auto_now=False,auto_now_add=True)
updated = models.DateTimeField(auto_now=True,auto_now_add=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("posts:detail", kwargs={"id":self.id})
I have a django model that looks like this:
class AcademicProgramsManager(models.Manager):
def get_by_natural_key(self, acad_program_id, program_title, required_credits):
return self.get(acad_program_id = acad_program_id, program_title = program_title, required_credits = required_credits)
class AcademicPrograms(models.Model):
objects = AcademicProgramsManager()
acad_program_id = models.IntegerField(primary_key=True)
acad_program_category = models.ForeignKey(AcademicProgramCategories)
acad_program_type = models.ForeignKey(AcademicProgramTypes)
acad_program_code = models.CharField(max_length=25)
program_title = models.CharField(max_length=64)
required_credits = models.IntegerField()
min_gpa = models.FloatField()
description = models.CharField(max_length=1000)
def natural_key(self):
return (self.acad_program_id, self.program_title, self.required_credits)
class StudentAcademicPrograms(models.Model):
student = models.ForeignKey(Students)
academic_program = models.ForeignKey(AcademicPrograms)
credits_completed = models.IntegerField()
academic_program_gpa = models.FloatField()
primary_program = models.BooleanField()
This is my serializers.py file:
from studentapp.models import AcademicPrograms, AcademicProgramsManager, StudentAcademicPrograms
from rest_framework import serializers
class StudentAcademicProgramsSerializer(serializers.ModelSerializer):
class Meta:
model = StudentAcademicPrograms
fields = ('credits_completed','academic_program_gpa','primary_program')
class AcademicProgramsSerializer(serializers.ModelSerializer):
studentacademicprograms = StudentAcademicProgramsSerializer(many = True)
class Meta:
model = AcademicPrograms
fields = ('acad_program_id','program_title','required_credits','studentacademicprograms')
My api.py file looks like this:
from studentapp.models import AcademicPrograms, AcademicProgramsManager, StudentAcademicPrograms
from studentapp.serializers import StudentAcademicProgramsSerializer, AcademicProgramsSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
class AcademicProgramsList(APIView):
def get(self, request, format=None):
academicprograms = AcademicPrograms.objects.all()
serialized_academicprograms = AcademicProgramsSerializer(academicprograms, many=True)
return Response(serialized_academicprograms.data)
class AcademicProgramsDetail(APIView):
def get_onjects(self, pk):
try:
return AcademicPrograms.object.get(pk=pk)
except AcademicPrograms.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
academicprogram = self.get_object(pk)
serialized_academicprogram = AcademicProgramsSerializer(academicprogram)
return Response(serialized_academicprogram.data)
and finally my urls:
from django.conf.urls import patterns, include, url
from rest_framework.urlpatterns import format_suffix_patterns
from studentapp import api
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Examples:
# url(r'^$', 'texascompletes.views.home', name='home'),
# url(r'^blog/', include('blog.urls')),
#API:
url(r'^api/studentacademicprograms/$', api.AcademicProgramsList.as_view()),
url(r'^api/studentacademicprograms/(?P<pk>[0-9]+)/$', api.AcademicProgramsDetail.as_view()),
url(r'^admin/', include(admin.site.urls)),
)
urlpatterns = format_suffix_patterns(urlpatterns)
I am getting the following error when i give my api/studentacademicprograms
'AcademicPrograms' object has no attribute 'studentacademicprograms'
Where am i going wrong?
Try setting the source to the attribute/method name on the model. For example:
studentacademicprograms = StudentAcademicProgramsSerializer(
many=True,
source='studentacademicprograms_set')
The example given in the Django Rest Framework Serializer relations docs sets a related name on the models which matches the attribute name in the serializer (the default). If the names don't match you need to specify them model's source method/attribute to use.