In creating Django REST framework, i'll get all the data using this code
views.py
#api_view(['GET', ])
def api_detail_educationlevel(request):
if request.method == 'GET':
educationlevel = EducationLevel.objects.all()
serializer = EducationLevelSerializer(educationlevel, many=True)
return Response(serializer.data)
urls.py
path('api/', views.api_detail_educationlevel),
but when i add in my views.py like this
#api_view(['PUT', ])
def api_update_educationlevel(request, pk):
try:
educationlevel = EducationLevel.objects.get(pk=pk)
except EducationLevel.DoesNotExist:
return HttpResponse(status=404)
if request.method == 'PUT':
serializer = EducationLevelSerializer(educationlevel, data=request.data)
data = {}
if serializer.is_valid():
serializer.save()
data["success"] = "update successfull"
return Response(data=data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
#api_view(['DELETE', ])
def api_delete_educationlevel(request, pk):
try:
educationlevel = EducationLevel.objects.get(pk=pk)
except EducationLevel.DoesNotExist:
return HttpResponse(status=404)
if request.method == 'DELETE':
operation = educationlevel.delete()
data ={}
if operation:
data["success"] = "delete successfull"
else:
data["failure"] = "delete failed"
return Response(data=data)
#api_view(['POST', ])
def api_create_blog_view(request):
authentication_classes = [SessionAuthentication, BasicAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request, format=None):
content = {
'user': unicode(request.user), # `django.contrib.auth.User` instance.
'auth': unicode(request.auth), # None
}
return Response(content)
and in my urls.py
urlpatterns = [
path('api/', views.api_detail_educationlevel),
path('api/update/', views.api_update_educationlevel),
path('api/delete/', views.api_delete_educationlevel),
path('api/create/', views.api_create_blog_view),
]
urlpatterns = format_suffix_patterns(urlpatterns)
I dont know why i am getting this message,
in my path('api/update/', views.api_update_educationlevel),
in my path('api/delete/', views.api_delete_educationlevel),
in my path('api/create/', views.api_create_blog_view),
any idea why i am getting this message? i just want functional rest framework that can update/delete/insert data using user auth account
For each of these views (views.api_detail_educationlevel, views.api_update_educationlevel, views.api_delete_educationlevel, views.api_create_blog_view), you define #api_view(['*api method*', ]).
Only the views.api_detail_educationlevel has #api_view(['GET', ]) therefore allowing a GET method. The others don't. Either add a GET method to the other views or, like the documentation you follow, create a class containing each method.
Related
can anyone help please, with DRF
according to POST request, I want to create(if not exists) or update() table
belows are my codes
model.py
class User1(models.Model):
user = models.CharField(max_length=10)
full_name = models.CharField(max_length=20)
logon_data = models.DateTimeField(blank=True, null=True)
serializer.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User1
fields = '__all__'
views.py
from .models import User1
from .serializers import UserSerializer
from rest_framework.response import Response
from rest_framework.decorators import api_view
#api_view(['GET', 'POST'])
def UserView(request):
if request.method == 'GET':
users = User1.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
elif request.method == 'POST':
users = User1.objects.all()
serializer = UserSerializer(data=request.data, many=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('users/', views.UserView),
]
when POST request, I want to check like this:
if user exists:
if user.full_name == request.fullname
update (user.logon_data)
save()
else:
update (user.full_name)
update (user.logon_data)
save()
else:
create(
user = request.user,
full_name = request.full_name,
logon_data = request.logon_date)
save()
POST request for JSON like this:
[
{
"user": "testuser1",
"full_name": "test user1",
"logon_data": "2022-10-19 09:37:26"
},
{
"user": "testuser2",
"full_name": "test user2",
"logon_data": "2022-10-20 07:02:06"
}
]
#api_view(['GET', 'POST'])
def UserView(request):
if request.method == 'GET':
users = User1.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = UserSerializer(data=request.data, many=True)
# if serializer validation fails, raises error by itself
serializer.is_valid(raise_exception=True)
for data in serializer.validated_data:
# checking if data exists else creating an object in User1 model
# user = data['user'] --> filter to check if that user exist
# defaults={'full_name': data['full_name'], 'logon_data': #data['logon_data']} --> value provided in defaults is used to update data in #model once the condition is met.
User1.objects.update_or_create(user=data['user'], defaults={'full_name': data['full_name'], 'logon_data': data['logon_data']})
return Response(serializer.data, status=201)
Try this update_or_create it will check based on request.user whether it exists in table or not
Also ensure that request.user is checked to user object if you want to check specific field then it should be request.user.user
User.objects.update_or_create(user=request.user.user, defaults={"full_name": request.full_name, "logon_date":request.logon_date})
I'm trying to use custom permissions in my class based views.
When I try to run one of my views, I get a WrappedAttributeError : 'UserViewPermissionClass' object has no attribute 'authenticate'
Here are my custom permissions :
class UserViewPermissionClass(BasePermission):
def has_permission(self, request, view):
if request.method == 'GET':
return request.user.is_admin
elif request.method == 'POST':
return True
# default logic
class UserView(APIView):
authentication_classes = ( UserViewPermissionClass,)
This is the class based view that I'm trying to run :
class HandleUsers(UserView):
def get(self, request):
"""Only for admin"""
try:
users = User.objects.all()
except User.DoesNotExist():
return HttpResponse(status=404)
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
def post(self, request):
"""For everyone"""
serializer = RegistrationSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.error)
Here are my settings for rest framework :
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
],
}
After doing some research I saw that my error could be due to my DEFAULT_PERMISSION_CLASSES. However I cannot see what could be blocking.
Thank you in advance for your help.
change authentication_classes=(UserViewPermissionClass,) to permission_classes=(UserViewPermissionClass,)
I'm using #action in my ViewSet.
#action(detail=True, methods=('get', 'post', 'put', 'patch'))
def crontab(self, request, pk=None):
template_obj = self.get_object()
app_name = template_obj.application.name
template_name = template_obj.name
periodic_task_name = '%s:%s' % (app_name, template_name)
if request.method == 'GET':
periodic_task = PeriodicTask.objects.filter(
name=periodic_task_name)
if periodic_task.exists():
crontab_obj = periodic_task.get().crontab
serializer = serializers.CrontabScheduleSerializer(crontab_obj)
return Response(serializer.data)
return Response({'crontab': 'crontab does not exist'})
When condition if periodic_task.exists(): is True and return Response(serializer.data) executes I get this error related with TemplateSerializer. This serializer is used in ViewSet, not in my crontab action, and the 'application' field I do not touch in any way.
Any suggestions?
Solution. Put the logic from #action into a separate view with the same URL + '/your_action_name/'.
Also. Can do something like this in your #action, but this is not entirely correct:
if periodic_task.exists():
crontab_obj = periodic_task.get().crontab
serializer = serializers.CrontabScheduleSerializer(crontab_obj)
res_data = {**serializer.data}
return Response(res_data)
I'm trying to learn DJango Rest so I made a litte test to see if I could obtain some things from the database, but I'm getting some problems.
Here's my models.py:
from django.db import models
# Create your models here.
class Stock(models.Model):
ticker = models.CharField(max_length=10)
open = models.FloatField()
close = models.FloatField()
volume = models.IntegerField()
def __str__(self):
return self.ticker
Here's my serializers.py:
from rest_framework import serializers
from .models import Stock
class StockSerializer(serializers.ModelSerializer):
ticker = serializers.CharField()
open = serializers.FloatField()
close = serializers.FloatField()
volume = serializers.IntegerField()
def create(self, validated_data):
return Stock.objects.check(**validated_data)
def update(self, instance, validated_data):
instance.ticker = validated_data.get('ticker', instance.ticket)
instance.open = validated_data.get('open', instance.open)
instance.close = validated_data.get('close', instance.close)
instance.volume = validated_data.get('volume', instance.volume)
instance.save()
return instance
class Meta:
model = Stock
fields = '__all__'
Here's my views.py:
from django.http import Http404
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Stock
from .serializers import StockSerializer
# List all stocks or create a new one
# stocks/
#api_view(['GET', 'POST'])
def stock_list(request, format=None):
if request.method == 'GET':
stocks = Stock.objects.all()
serializer = StockSerializer(stocks, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = StockSerializer(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)
#api_view(['GET', 'POST', 'DELETE'])
def stock_detail(request, pk, format=None):
try:
stock = Stock.objects.get(pk=pk)
except Stock.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = StockSerializer(stock)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = StockSerializer(stock, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
stock.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
And finally, here's my url.py:
from django.conf.urls import url
from django.contrib import admin
from rest_framework.urlpatterns import format_suffix_patterns
from companies import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^stocks/', views.stock_list),
url(r'^stocks/(?P<pk>[0-9]+)$', views.stock_detail),
]
urlpatterns = format_suffix_patterns(urlpatterns)
I've been following this tutorial, but when it comes to the moment of making some requests (for this example I use this one: http http://127.0.0.1:8000/stocks/
I get this error message:
TypeError at /stocks/ stock_list() missing 1 required positional
argument: 'request'
I think that the problem is with the urls, but I'm not sure how to fix it.
Any ideas and some examples?
UPDATE: The problem was with the methods in view (they had an attibute self)
The general Get method works, but when I try to use POST
POST ERROR:
When I try this request: http --form POST http://127.0.0.1:8000/stocks/ ticker='SAM'
I get this error:
AttributeError at /stocks/ Got AttributeError when attempting to get a
value for field ticker on serializer StockSerializer. The
serializer field might be named incorrectly and not match any
attribute or key on the list instance. Original exception text was:
'list' object has no attribute 'ticker'.
You need to remove self.
Remember you are using functions not clases.
#api_view(['GET', 'POST'])
def stock_list(request, format=None):
if request.method == 'GET':
stocks = Stock.objects.all()
serializer = StockSerializer(stocks, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = StockSerializer(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)
Try views.stock_list.as_view() in urls.py
I have a simple filtering in my get function which needs to be paginated. I tried different ways of solving this issue , but I am not able to figure out what exactly needs to be done. The following is my code
class UserInfoViewSets(viewsets.ViewSet):
def UserInfo_post(self,request, format=None):
if request.method == 'POST':
serializer = UserInfoSerializer(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)
def UserInfo_get(self,request,user_token):
if request.method == 'GET':
queryset = UserInfo.objects.filter(user_token=user_token)
serializer = UserInfoSerializer(queryset,many=True)
I need to paginate the get results. I dont want to write a customized pagination class, but just set the parameter to limit the no of results per page. I have tried setting the following in the setting.py file
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 2,
}
In my views file , I added ListAPIView
class UserInfoListView(generics.ListAPIView):
model = UserInfo
serializer_class = UserInfoSerializer
paginate_by_param = 'limit'
clearly I am overlooking some minor detail. I tried scouting thought the documentation. But it seems to be geared towards people who are well versed with django.
That is what I do for pagination, filtering, ordering etc... First you need to pip install django-filter (https://github.com/alex/django-filter)
settings.py
REST_FRAMEWORK = {
. . .
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'DEFAULT_FILTER_BACKENDS': (
'rest_framework.filters.DjangoFilterBackend',
),
'PAGE_SIZE': 1000
. . .
}
views.py
class UserViewSet(viewsets.ModelViewSet):
lookup_field = 'id'
queryset = Users.objects.order_by('id')
serializer_class = AccountSerializer
filter_backends = (SearchFilter, OrderingFilter)
search_fields = ('^id', '^first_name', '^last_name', '^email', ^username',)
I am using AngularJS,
function getUserList(limit, pageNumber, search, ordering) {
var def = $q.defer();
offset = (pageNumber -1) * limit;
$http.get(API_URL +
'?limit=' +limit +
'&offset=' + offset +
'&search=' + search +
'&ordering=' + ordering)
.success(function(data){
def.resolve(data);
})
.error(function(data){
def.resolve(data);
});
return def.promise;
}
Example query:
http://127.0.0.1:8000/user/?limit=10&offset=0&search=%20&ordering=id
Thanks #umut and #prashant. I am sharing my version plainly using DRF. Hopefully, others new to drf will find this easier.
def Users_get(self,request,user_token):
if request.method == 'GET':
queryset = Users.objects.filter(user_token=user_token)
paginator = PageNumberPagination()
result_page = paginator.paginate_queryset(queryset, request)
serializer = UsersSerializer(result_page,many=True)
return paginator.get_paginated_response(serializer.data)
This gave me response with next and previous url links.
In code below entire viewset is designed GET POST PUT DELETE also your query regarding pagination over filtered query is also handled.
Pagination is done using Paginator its a built-in in django
For docs cover most of the part go to django docs for that. DRF docs can be confusing sometimes but django docs are finely descriptive and easy to implement
views.py
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
#api_view(['GET', 'POST'])
def product_list(request):
if request.method == 'GET':
products = Product.objects.all()
product_make_up = Product.objects.filter(item_category__exact='Make Up')[:3]
product_skincare = Product.objects.filter(item_category__exact='Skin Care')[:3]
product_fragrance = Product.objects.filter(item_category__exact='Fragrance')[:3]
product_personal_care = Product.objects.filter(item_category__exact='Personal Care')[:3]
product_hair_care = Product.objects.filter(item_category__exact='Hair Care')[:3]
product_item_category = QuerySetChain(product_make_up,
product_skincare,
product_fragrance,
product_personal_care,
product_hair_care)
item_cates = request.query_params.get('item_category',None)
if item_cates is not None:
product = products.filter(item_category=item_cates)
paginator = Paginator(product,5)
page = request.query_params.get('page')
product = paginator.page(page)
try:
product = paginator.page(page)
except PageNotAnInteger:
product = paginator.page(1)
except EmptyPage:
product = pagintor.page(paginator.num_pages)
serializer = ProductSerializer(product, many=True)
else:
paginator = Paginator(product_item_category,15)
page = request.query_params.get('page')
product_item_category = paginator.page(page)
try:
product_item_category = paginator.page(page)
except PageNotAnInteger:
product_item_category = paginator.page(1)
except EmptyPage:
product_item_category = pagintor.page(paginator.num_pages)
serializer = ProductSerializer(product_item_category, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ProductSerializer( data=request.data)
# data.encode("base64")
if serializer.is_valid():
serializer.save()
res_msg = {'Success_Message' : 'Successful','Success_Code' : 200}
return Response(res_msg)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
#api_view(['GET', 'PUT', 'DELETE'])
def product_detail(request, pk):
"""
Get, udpate, or delete a specific task
"""
try:
product = Product.objects.get(pk=pk)
except Product.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = ProductSerializer(product)
return Response(serializer.data , status=status.HTTP_201_CREATED)
elif request.method == 'PUT':
serializer = ProductSerializer(product, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(
serilizer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
product.delete()
return Response(status=status.HTTP_204_NO_CONTENT)