I am writting an application in Django that uses the Django Rest framework. A GET request to the API URL works, but when I add a query to it, such as '?id=1845' it does not actually perform a query, it still returns the full list of results.
In the below code, I am trying to query the 'Indicator List'
views.py
from django.shortcuts import render
from django.http import JsonResponse
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .serializers import IndicatorSerializer
from data_platform.models import Indicator
#api_view(['GET'])
def apiOverview(request):
api_urls = {
'Indicator List':'/indicator-list/',
'Indicator Detail':'/indicator-detail/<str:pk>/',
}
return Response(api_urls)
#api_view(['GET'])
def indicatorList(request):
indicators = Indicator.objects.all()
serializer = IndicatorSerializer(indicators, many=True)
#filterset_fields = ('id')
#filter_backends = [DjangoFilterBackend]
return Response(serializer.data)
#api_view(['GET'])
def indicatorDetail(request, pk):
indicators = Indicator.objects.get(id=pk)
serializer = IndicatorSerializer(indicators, many=False)
return Response(serializer.data)
urls.py
from django.urls import include, path
from . import views
urlpatterns = [
path('', views.apiOverview, name="api-overview"),
path('indicator-list/', views.indicatorList, name="indicator-list"),
path('indicator-detail/<str:pk>/', views.indicatorDetail, name="indicator-detail"),
]
serializers.py
from rest_framework import serializers
from data_platform.models import Indicator
class IndicatorSerializer(serializers.ModelSerializer):
class Meta:
model = Indicator
fields = '__all__'
I figured it out! I had to use a class view rather then a function view
class indicatorList(generics.ListAPIView):
queryset = Indicator.objects.all()
serializer_class = IndicatorSerializer
filter_backends = [django_filters.rest_framework.DjangoFilterBackend]
filter_fields = ('id',)
and add 'django_filters', to INSTALLED_APPS
Related
In my views, queryset is returning all the users when I want it to be only returning the user that is currently logged. I have a get self method which has the serializer set to the user but it is not being used. When I tried get_queryset, self.request.user still doesn't return the user.
views.py:
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from rest_framework import status
from rsm_app.api.v1 import serializer as serializers
from rsm_app.users.models import User
class CurrentUserView(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
serializer_class = serializers.UserSerializer
#queryset = User.objects.filter(name=request.user.name)
def get_queryset(self):
return self.request.user
def put(self, request):
serializer = serializers.UserSerializer(
request.user, data=request.data)
if request.data and serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response({}, status=status.HTTP_400_BAD_REQUEST)
Url.py:
from rest_framework import routers
from django.urls import path, re_path, include
from graphene_django.views import GraphQLView
from rsm_app.api.v1 import views
app_name = "api.v1"
# Routers provide an easy way of automatically determining the URL conf.
router = routers.DefaultRouter()
router.register(r"user", views.CurrentUserView, basename="user")
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
path("graphql", GraphQLView.as_view(graphiql=True)),
re_path(r"^", include(router.urls)),
re_path(r"user/", views.CurrentUserView, name='user'),
re_path(r"^api-auth/", include("rest_framework.urls",
namespace="rest_framework")),
]
Edit FIXED: It was a session token not being saved issue.
They mentioned in the docs that you could access the current user by user = self.get_object()
You could see the full example from the official docs.
Can you try with:
queryset = User.objects.filter(name=request.user.name).first()
or
queryset = User.objects.get(name=request.user.name)
I am trying to make a crud API using Django rest_framework the get request seems to work fine
for me but the post request is not working at all when I try to print the request.data it gives an empty dictionary
Please help me to resolve this issue
views.py file
from rest_framework import serializers
from . models import freelancerJob
from django.http import JsonResponse
from .serializers import jobPostSerializer
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from rest_framework.status import HTTP_200_OK,HTTP_400_BAD_REQUEST
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.decorators import parser_classes
from rest_framework.parsers import JSONParser
from rest_framework import viewsets
#csrf_exempt
#api_view(['GET', 'POST','DELETE'])
#parser_classes([JSONParser])
def jobPostView(request,format=None):
if request.method == "POST":
print("data",request.data)
serializer = jobPostSerializer(data=request.data)
print(serializer.initial_data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return JsonResponse({'data':serializer.data},status = HTTP_200_OK )
else:
return Response({'status':'error','data':serializer.data},status = HTTP_400_BAD_REQUEST)
if request.method == "GET":
data = freelancerJob.objects.all().order_by('id')
serializer = jobPostSerializer(data ,many = True)
return Response({"status":'success','data':serializer.data},status = HTTP_200_OK)
My serializers.py file
from rest_framework import serializers
from . models import freelancerJob
class jobPostSerializer(serializers.HyperlinkedModelSerializer):
def create(self,validated_data):
return freelancerJob.object.create(**validated_data)
class Meta:
model = freelancerJob
fields = ['title','description','skill','duration','budget','types']
my models.py file
from operator import truediv
from django.db import models
class freelancerJob(models.Model):
Job_duration = (
('1','Less than 1 month'),
('3','1 to 3 months'),
('6','3 to 6 month'),
('12','More than 6 months')
)
Job_type=(("Individual",'Individual freelancer'),
('Team','Team')
)
title = models.CharField(max_length=250,null=True,blank=False)
description = models.CharField(max_length=2000,blank=False)
skill= models.CharField(max_length=250)
duration = models.CharField(max_length=50 ,blank=False,choices=Job_duration)
budget = models.IntegerField(blank=False)
types = models.CharField(max_length=50,blank=False,choices=Job_type)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
When I try to print the request.data that is coming from the post request it gives an empty dictionary
I am using Django 3.0 djangorestframework==3.11.0. I have created a task update view and passing the pk to url. The problem is - Although I have set the serializer instance to the model object I want to update. The serializer instance is not showing up.
models.py
from django.db import models
# Create your models here.
class Task(models.Model):
title = models.CharField(max_length=200)
completed = models.BooleanField(default=False, blank=True, null=True)
def __str__(self):
return self.title
serializers.py
from rest_framework import serializers
from .models import Task
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = '__all__'
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.apiOverview, name='api-overview'),
path('task-list/', views.taskList, name='task-list'),
path('task-detail/<str:pk>/', views.taskDetail, name='task-detail'),
path('task-create/', views.taskCreate, name='task-create'),
path('task-update/<str:pk>/', views.taskUpdate, name='task-update'),
]
views.py
from django.shortcuts import render
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Task
from .serializers import TaskSerializer
#api_view(['POST'])
def taskUpdate(request, pk):
task = Task.objects.get(id=pk)
serializer = TaskSerializer(instance=task, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
expected behavior on url http://localhost:8000/api/task-update/4/
actual behaviour on http://localhost:8000/api/task-update/4/
as you can see the content field is empty but I want the already associated json to be shown there with pk = 4.
This question is based on the one here. I am setting up a Django REST Framework for my web app and am trying to set up User accounts. Based on the REST documentation, they put all of their account code in their example in the main project directory and a separate application so did that as well. Here is what I have:
urls.py
from django.contrib import admin
from django.urls import include, path
from django.conf.urls import url
from rest_framework import routers
from . import views
router = routers.DefaultRouter()
router.register('users', views.UserViewSet)
urlpatterns = [
path('admin/', admin.site.urls),
url('', include(router.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]
serializers.py
from django.contrib.auth.models import User
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
def create(self, validated_data):
user = User.objects.create(
username=validated_data['username']
)
user.set_password(validated_data['password'])
user.save()
return user
class Meta:
model = User
# Tuple of serialized model fields (see link [2])
fields = ( "id", "username", "password", )
views.py
from rest_framework import viewsets, permissions
from rest_framework.generics import CreateAPIView
from django.contrib.auth.models import User
from .serializers import UserSerializer
# Create your views here.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated]
class CreateUserView(CreateAPIView):
model = User
permission_classes = [
permissions.AllowAny
]
serializer_class = UserSerializer
I have tried using the Boomerang REST Client in Chrome to POST data to this API, but it always returns a 403 Error saying "Invalid username/password." Specifically I am POSTing to http://127.0.0.1:8000/users/create/ with a Query String and 2 parameters: username and password. I also tried sending it as JSON and it returned the same. Any help would be appreciated.
It doesn't look like CreateUserView was registered in your urls.py. You should be able to register it and access it normally. I think this should work for you:
urlpatterns = [
...
url(r'^users/create/', views.CreateUserView.as_view()),
]
That said, I'd like to suggest adding an extra action for your UserViewSet instead:
# Create your views here.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated
#action(methods=['post'], detail=False, permission_classes=[permissions.AllowAny])
def register(self, request, *args, **kwargs):
# This logic was taken from the `create` on `ModelViewSet`. Alter as needed.
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
Then you should be able to post via /users/register/. You can also specify your own url name and path on the decorator.
Maybe you are posting in the wrong url, try POST the same on http://127.0.0.1:8000/users/,
because ModelViewSet adds POST, PATCH, PUT, DELETE and GET methods automatically.
Also because you are asking for authentication (permission_classes = [permissions.IsAuthenticated]), you should send the headers for this in the request. There is a tutorial for this in the DRF site (https://www.django-rest-framework.org/tutorial/4-authentication-and-permissions/)
based on django-rest-framework documents it's better to use viewset for create user api. therefor you need to send a POST request to http://127.0.0.1:8000/api-auth/users and no need to CreateUserView function.
But if you want to have a custom user create api do you need something like below:
class UserViewSet(viewsets.ModelViewSet):
"""
A viewset that provides the standard actions
"""
queryset = User.objects.all()
serializer_class = UserSerializer
#action(detail=True, methods=['post'], permission_classes=[permissions.AllowAny])
def create_user(self, request, pk=None):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
To have custom serializers in your ViewSet you can specify them in get_serializer_class function in your ViewSet like this:
class UserViewSet(viewsets.ModelViewSet):
# example viewset
def get_serializer_class(self):
if self.action == 'list':
return ListUserSerializer
elif self.action == 'create':
return CreateUserSerializer
elif self.action == 'update':
return UpdateUserSerializer
return DetailUserSerializer
I got an error,
AttributeError at /app/api/get
Got AttributeError when attempting to get a value for field task_name on serializer TaskSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the Color instance.
Original exception text was: 'Color' object has no attribute 'task_name'.
Now I wanna make a page that shows model's content in json format.
models.py is
from django.db import models
# Create your models here.
class Color(models.Model):
name = models.CharField(max_length=255)
background_color = models.CharField(max_length=255)
h1_color = models.CharField(max_length=255)
p_color = models.CharField(max_length=255)
def __str__(self):
return self.name
serializers.py is
from .models import Color
from rest_framework import serializers
class TaskSerializer(serializers.Serializer):
task_name = serializers.CharField(max_length=100)
status = serializers.SerializerMethodField('get_task_status')
def get_task_status(self, instance):
return instance.status.status
class Meta:
model = Color
fields = ('name',
'background_color',
'h1_color',
'p_color',
'task_name')
urls.py is
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'api/get',views.TaskGet.as_view(),name='task-get')
]
views.py is
from django.shortcuts import render
from .models import Color
from .forms import ColorForm
from .serializers import TaskSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
# Create your views here.
def index(request):
d = {
'colors': Color.objects.all(),
'form': ColorForm(),
}
return render(request, 'index.html', d)
class TaskGet(APIView):
def get(self, request, format=None):
obj = Color.objects.all()
serializers = TaskSerializer(obj, many=True)
return Response(serializers.data, status.HTTP_200_OK)
I wrote url(r'api/get',views.TaskGet.as_view(),name='task-get') in urls.py,so I really cannot understand why this error happens.I already run commands of migration of model. How can I fix this?
My ideal web page is like
You try get status by foreign key instance.status.status but in your model class Color i don't see any foreign keys or methods for it.
And for task_name did you want to see the model field name try to add source params
task_name = serializers.CharField(max_length=100, source='name')
# ^^^^^^^^^
are you sure you want serialize Task for model Color?
new edit
in your get_task_status the 'instanceis instance of serializer model, so if your modelColorhas no property or methodstatus` you will catch an error