Record exists or not in DB? Django Api generic Views - django-rest-framework

I want to write a class based API view to check if the record exists in DB or not then return True else False by using rest_framework. How could I create CBV to check it? Please help me with this context.
here is my serializer class
class EmployeeSerializer(ModelSerializer):
class Meta:
model = Employee
fields = '__all__'
here is my url
path('employee/<name>/<code>/',views.EmployeeExist.as_view(),name = 'employee_exits')

Here is how you can create simple view:
from rest_framework import status, response
from rest_framework import generics
class EmployeeExistView(generics.GenericAPIView):
serializer_class = None
def get(self, request, *args, **kwargs):
employee = Employee.objects.filter(id=kwargs.get('id'))
if employee.exists():
return response.Response(status=status.HTTP_200_OK)
return response.Response(status=status.HTTP_404_NOT_FOUND)

Related

Django REST error when serializing uploaded image

I'm getting a serializer error:
"Upload a valid image. The file you uploaded was either not an image
or a corrupted image"
When trying to serialize an uploaded image
My code:
Models:
class Post(models.Model):
text = models.TextField(max_length=10000)
class Image(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
image = models.ImageField(blank=False, null=False, upload_to='test')
View:
class CreateNewPostAPIView(generics.CreateAPIView):
serializer_class = serializers.NewPostSerializer
def get_serializer_context(self):
context = super().get_serializer_context()
if self.request.data.get('image', None):
context['image'] = self.request.data.pop('image', None)
return context
Serializers:
class NewPostSerializer(serializers.ModelSerializer):
def create(self, validated_data):
post = Post.objects.create(**validated_data)
image = self.context['image'][0] # working with only one image for now
# image is of type <class'django.core.files.uploadedfile.InMemoryUploadedFile'>
serializer = ImageSerializer(data={'post': post.pk, 'image': image})
is_valid = serializer.is_valid() # it's always False!
return post
class ImageSerializer(serializers.ModelSerializer):
class Meta:
model = Image
fields = ('post', 'image')
I already tried doing that without a serializer and it's working with this code:
class NewPostSerializer(serializers.ModelSerializer):
def create(self, validated_data):
post = Post.objects.create(**validated_data)
image = self.context['image']
Image.objects.create(post=post.pk, image=image)
return post
But I need to do it using a serializer.
The easy way for this would be like:
Models:
from django.db import models
# Create your models here.
class Post(models.Model):
text = models.TextField()
def __str__(self):
return self.text[:50]
class Image(models.Model):
post = models.ForeignKey(
Post, on_delete=models.CASCADE,
related_name='images', editable=False
)
image = models.ImageField(upload_to='images/')
def __str__(self):
return self.image.name
def delete(self, *args, **kwargs):
self.image.delete()
super().delete(*args, **kwargs)
Serializer:
from rest_framework import serializers
from .models import Post, Image
class ImageSerializer(serializers.ModelSerializer):
class Meta:
model = Image
fields = "__all__"
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = "__all__"
class PostWithImageSerializer(serializers.ModelSerializer):
image = serializers.ImageField(write_only=True)
# This is for the GET request or the response of the POST request
# We can also work with a separate serializer for such cases
images = ImageSerializer(many=True, read_only=True)
class Meta:
model = Post
fields = "__all__"
def create(self, validated_data):
image_data = validated_data.pop('image')
post = Post.objects.create(**validated_data)
Image.objects.create(post=post, image=image_data)
return post
Views as:
from rest_framework.response import Response
from rest_framework import status
from .serializers import *
# Create your views here.
class AddPostWithAnImageView(APIView):
serializer_class = PostWithImageSerializer
def post(self, request):
serializer = self.serializer_class(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)
For testing purposes, please use Postman where you can upload images with so much ease. The request form should only require the text and the image fields.
Thanks to #pKiran, who gave me an idea, now I have a working code for saving one or more images. It's, also, quite concise and readable. There's quite a lot going on here with so little of code. Django REST is quite confusing.
class ImageSerializer(serializers.ModelSerializer):
class Meta:
model = Image
fields = ('image', 'thumb')
class NewPostSerializer(serializers.ModelSerializer):
image = serializers.ListField(child=serializers.ImageField(), write_only=True, required=False)
def create(self, validated_data):
images = validated_data.pop('image', None)
post = Post.objects.create(**validated_data)
if images:
img_models = [Image(post=post,
image=image, thumb=make_thumb(image))
for image in images]
Image.objects.bulk_create(img_models)
return post

Rename field in Serializer.data

I am currently implementing an API client for which I want to validate the request sent using serializers.
To do so, I create my serializer like this:
class TransactionRequestSerializer(serializers.Serializer):
counterparty = serializers.UUIDField(required=False)
from_datetime = serializers.DateTimeField(required=False, source='from')
to_datetime = serializers.DateTimeField(required=False, source='to')
transaction_type = serializers.CharField(required=False, source='type')
Issue is that source doesn't fit my usage, because when I do serializer.data, I get:
{'from_datetime': '2020-07-07T16:08:00.313236+02:00'}
Instead of
{'from': '2020-07-07T16:08:00.313236+02:00'}
Those data are then passed as params for my request, like requests.get('', params=params)
Of course, I cannot name the field "from" as it is reserved. Any idea about how can I get "from" in my serializer.data?
I tink this has already been answered.
Please take a look at this question: How to change field name in Django REST Framework
I think the same solution will work for you.
I think it's not possible, so I switched to Serializer.validated_data instead so I can use source.
this example as same the question :
model:
from django.db import models
class ReceiveCallbackUrl(models.Model):
From = models.CharField(max_length=14)
to = models.CharField(max_length=14)
message = models.CharField(max_length=255)
messageid = models.IntegerField()
serializer:
from rest_framework.serializers import ModelSerializer,SerializerMethodField
from .models import ReceiveCallbackUrl
class ReceiveCallbackUrlModelSerializer(ModelSerializer):
From = SerializerMethodField('from')
class Meta:
model = ReceiveCallbackUrl
fields = ['From', 'to', 'message', 'messageid']
view:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .serializer import ReceiveCallbackUrlModelSerializer
class ReceiveCallbackUrlAPIView(APIView):
def post(self, request):
serializer = ReceiveCallbackUrlModelSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(request.POST, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_406_NOT_ACCEPTABLE)

DRF Filter PrimaryKeyField Based on Current User

I have a view set up to return a list of books to a user, which is retrieved from a simple book model based on the currently logged-in user. However, I also have ReadingSession model which has a foreign key relationship to both the Book, and the User.
When I'm retrieving the books for the user, I'd like to, at the very least, return a list of primary keys that I can use to get the length of in my client.
The following code will get the full set of readingsessions in my BookSerializer:
from rest_framework import serializers
from books.models import Book
class BookSerializer(serializers.ModelSerializer):
readingsession_set = serializers.PrimaryKeyRelatedField(
many=True, read_only=True)
class Meta:
model = Book
fields = ["id", "title", "author", "publisher",
"publish_date", "description", "category",
"language", "small_thumbnail", "thumbnail",
"readingsession_set"]
However, the problem with this is that it will return all of the readingsessions, regardless of whether or not the session belongs to that user.
I'd like to be able to filter that so that it will only return the readingsessions for the current user. Something along the lines of:
readingsession_set = serializers.PrimaryKeyRelatedField(queryset=ReadingSession.objects.filter(user=user), read_only=True)
But I've tried various ways of trying to pass the user (self.request.user) from the APIView but none seem to work. I've tried passing a context, and tried passing extra **kwargs in __init__ but none seem to work.
Is there a way of achieving this? Or am I taking the wrong approach?
Thanks
The user is not present on the serializer's declaration but during its instantiation.
Therefore, you can filter querysets by user within the __init__ method.
from rest_framework import serializers
from bar.models import Foo
class RandomSerializer(serializers.Serializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
user_foos = Foo.objects.filter(user=self._user)
self.fields['foo_ids'] = serializers.PrimaryKeyRelatedField(
required=False,
many=True,
read_only=False,
queryset=user_foos,
default=user_foos)
#property
def _user(self):
request = self.context.get('request', None)
if request:
return request.user
Don't forget to pass the request object to the serializer in the context (if necessary, e.g., using a simple APIView.
from rest_framework import views
class RandomView(views.APIView):
serializer_class = RandomSerializer
def post(self, request):
serializer = self.serializer_class(
data=request.data, context={'request': request})
# ...
serializer = RandomSerializer(data=request.data, context={'request': request}
You can access the user of the request on the serializer by means of the context.
As mentioned in the documentation, you can always do:
serializer = AccountSerializer(account, context={'request': request})
Thus, you will be able to use self.context['request'].user inside your serializer.
Hope that's what you're after.

How to update records in a Postgres table with Django rest framework

I have basic django app that returns data from Postgres tables in an AWS RDS instance.
I have a few endpoint which relate to few tables in the RDS.
What I want to do is update records in table. If the record exists it should be updated, if it does not exist then nothing should happen Orit should throw an error.
This is my models.py file -
from django.db import models
class Campaigns(models.Model):
id_campaign = models.CharField(max_length=250, blank=True, null=True)
status = models.CharField(max_length=250, blank=True, null=True)
id_taste_cluster = models.CharField(max_length=250, blank=True, null=True)
I want to update the status field in this table where status = ' '.
This is my serialiser file -
from rest_framework import serializers
from .models import Campaigns
class Campaigns_1_Serializer(serializers.ModelSerializer):
class Meta:
model = Campaigns
fields = ('id_campaign', 'status', 'id_taste_cluster')
This is my views file -
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import generics
from .models import Campaigns
from .serializers import Campaigns_1_Serializer
class UpdateView(viewsets.ModelViewSet):
def update(self, request, *args, **kwargs):
data = request.DATA
queryset = Campaigns.objects.filter(status='')
serializer = Campaigns_1_Serializer(queryset, data=data, many=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
I want to give the users the option to update only those campaigns for which the status is ' '(blank).
How can I do that ?
You need to change your update method :
#your imports
from rest_framework import serializers
class YourModelViewset(ModelViewSet):
#your code
def update(self, request, *args, **kwargs):
instance = self.get_object()
# checks if the object staus is empty
If object.status == "" or object.status is None :
raise serializers.ValidationError("your error message")
return super(YourModelViewset, self).update(request, *args, **kwargs)

How to create view from External http request json and Internal Database using Django Rest Framework

I need to combine external json using request and Internal Database, But the condition is when someone call API we need to get empidlong from Model for call external API from specific URL, Then external API will return JSON and i need to merge this JSON with my json that create by Django REST API Framework
Here is my code
models.py :
from django.db import models
import requests
from django.core.files import File
from urllib import request
import os
# Create your models here.
class getData(models.Model):
company = models.CharField(max_length=150)
description = models.CharField(max_length=150)
period = models.CharField(max_length=150)
plate_no = models.CharField(max_length=150, primary_key=True)
project_code = models.CharField(max_length=150)
costcenter = models.CharField(max_length=150)
empidlong = models.CharField(max_length=150)
class Meta:
db_table = 'car_information'
serializers.py
from rest_framework import serializers
from .models import getData
class CarSerializer(serializers.ModelSerializer):
class Meta:
model = getData
fields = "__all__"
views.py
from django.shortcuts import render
from rest_framework import viewsets, filters
from .models import getData
from .serializers import CarSerializer
import requests
class CarViewSet(viewsets.ModelViewSet):
queryset = getData.objects.all()
serializer_class = CarSerializer
filter_backends = (filters.SearchFilter,)
#search_fields = ('plate_no')
__basic_fields = ('plate_no',)
search_fields = __basic_fields
serializer = CarSerializer(queryset, many=True)
data = serializer.data
for a in data:
empid= a['empidlong']
r = requests.get('http://192.168.10.32/Employees/'+empid)
def get_queryset(self):
queryset = getData.objects.all()
emp = self.request.query_params.get('emp', None)
if emp is not None:
queryset = queryset.filter(empidlong=emp)
return queryset
I have no idea how to do it. I stuck this for week.
Thank in advance.
Where are you expecting the json from? if from a user, you can access the json from the request. Then you can use it in your orm query. You CarViewSet seem to be doing way more than it should be. What is your goal exactly?

Resources