I used Django restframework to implement api server.
Also I used djangorestframework-jwt for token authentication.
[urls.py]
from django.contrib import admin
from django.urls import path, include
from rest_framework_jwt.views import refresh_jwt_token
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('rest_auth.urls')),
path('registration/', include('rest_auth.registration.urls')),
path('refresh-token/', refresh_jwt_token),
]
Everything works fine. But I want to know that How can I extract payload from token?
For example, There is article table.
[/article/serializers.py]
from rest_framework import serializers
from . import models
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = models.Article
fields = '__all__'
[models.py]
from django.db import models
class Article(models.Model):
subject = models.CharField(max_length=20)
content = models.CharField(max_length=100)
[views.py]
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from . import models, serializers
class Article(APIView):
def get(self, request, format=None):
all_article = models.Article.objects.all()
serializer = serializers.ArticleSerializer(all_article, many=True)
return Response(data=serializer.data, status=status.HTTP_200_OK)
In this case, I want to return correct response only payload['userid'] == article's userid.
How can I extract username from jwt token?
Previous, I just use jwt not djangorestframework-jwt, So just decode request data and use it.
But now I use djangorestframework-jwt, I confused How can I do it.
Is there any solution about this?
Thanks.
I solved this issue after checking the library's documentation here
https://jpadilla.github.io/django-rest-framework-jwt/
I needed to Override all the functions to return custom response as required in my application.
Also any additional settings we need to specify in JWT_AUTH in settings.py of my application.
i.e.
JWT_AUTH = {
'JWT_RESPONSE_PAYLOAD_HANDLER':
'myapp.utils.jwt_response_payload_handler',
}
And needed to define jwt_response_payload_handler function in a util folder in my app to override the default function.
Related
I'm beginner in Django.I get stuck from last 3 days by doing this task.I have try on google, Youtube but unfortunately failed to complete.Actually, I want to design a Api in which I filter data against title from jobs model that is in working.but the problem is that I want to first filter data from jobs model then store it against a unique id(string that is xyz) in storage, storage could be any like Redis or database and also return the same string(xyz) in response Api.Id will be use later on for result Api.
Please, help me I shall be very thankful to you
#My Jobs view
View.py
from rest_framework import viewsets, mixins
from .models import Job
from .serializers import JobSerializer
from rest_framework import filters,fields, serializers
from rest_framework import filters
class JobViewSet(
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet,
):
"""
Updates and retrieves user accounts
"""
queryset = Job.objects.all()I want
serializer_class = JobSerializer
filter_backends = [filters.SearchFilter]
search_fields = ['title']
I have a Django REST Framework project which uses a ModelViewSet to create APIs for a model containing a FileField.
I've shared a full example of a Django project demonstrating this issue here. But to summarise the key components:
models.py
from django.db import models
class Profile(models.Model):
image = models.FileField(upload_to='uploads/%Y/%m/%d/')
views.py
from rest_framework import (
viewsets,
serializers,
parsers,
)
from sample import models
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = models.Profile
fields = ['id', 'image']
read_only_fields = ['id']
class ProfileViewSet(viewsets.ModelViewSet):
serializer_class = ProfileSerializer
queryset = models.Profile.objects.all()
urls.py
from drf_spectacular.views import (
SpectacularAPIView,
SpectacularSwaggerView,
)
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings
from rest_framework.routers import DefaultRouter
from sample import views
router = DefaultRouter()
router.register('profile', views.ProfileViewSet)
urlpatterns = [
path('admin/', admin.site.urls),
path('api/schema/', SpectacularAPIView.as_view(), name='api-schema'),
path(
'api/docs/',
SpectacularSwaggerView.as_view(url_name='api-schema'),
name='api-docs',
),
path('', include(router.urls)),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py (REST_FRAMEWORK configuration only):
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}
requirements.txt
Django==3.2.3
djangorestframework==3.12.4
drf-spectacular==0.16.0
I am generating browsable Swagger-UI docs using drf-spectacular to document the API.
The problem is that the FileField input in Swagger-UI is a string input, and doesn't give the option to set a file:
I would like to have a file input where I can choose a file which will be sent to the API.
My question is: How can I configure DRF or drf-spectacular to show this field?
After some digging through the drf-spectacular docs and GitHub issues, I found that the FileField can be set to binary by adding the following to in settings.py:
SPECTACULAR_SETTINGS = {
'COMPONENT_SPLIT_REQUEST': True
}
Also in Swagger UI, make sure you change the content-type from application/json to multipart/form-data and click Try it out. The upload button will apppear.
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)
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?
I am trying to query from django i.e http://localhost:8000/search/Tesco/apples to get a query of json list, the one below.
[
{
"id": 12,
"Date": "2018-08-02",
"Title": "Rosedene Farms Small Sweet Apple 520G",
"Price": 0.96,
"PricePerWeight": "1.85/kg",
"FinalOffer": "undefined undefined",
"ProductID": 292249576
},
My urls.py:
from django.conf.urls import url, include
from . import views
from rest_framework import routers
router = routers.DefaultRouter()
router.register('Tesco', views.TescoView)
urlpatterns = [
url('', include(router.urls), name='search'),
url(r'^search/', include(router.urls), name='searchTwo')
my views.py
from __future__ import unicode_literals
from django.shortcuts import render
from rest_framework import viewsets
from .models import Tesco
from .serializers import TescoSerializers
from django.core.urlresolvers import reverse_lazy, reverse
class TescoView(viewsets.ModelViewSet):
queryset = Tesco.objects.filter(Title__icontains='apple')
serializer_class = TescoSerializers
how would I get the URL http://localhost:8000/search/tesco/ to query through the database for the list of json?
I don't think searching like:
http://localhost:8000/search/Tesco/apples
is a normal pattern in Django Rest Framework (DRF), so I think you're going to hit a lot of resistance trying to make this pattern work with DRF. If I may suggest, I believe you're in the X-Y Problem space - "That is, you are trying to solve problem X, and you think solution Y would work, but instead of asking about X when you run into trouble, you ask about Y."
Normally, filtering parameters are specified on the listing view of the model. For your model, your complete Tesco instance listing can be found at:
http://localhost:8000/Tesco/
If you want to filter this down, you append query parameters after a ? like:
http://localhost:8000/Tesco/?title__icontains=apple
or
http://localhost:8000/Tesco/?ProductID=292249576
or multiple searching filters like:
http://localhost:8000/Tesco/?ProductID=292249576&title__icontains=apple
To use this pattern, you need to modify your viewset and add a FilterSet. This is what your views.py file would look like:
from __future__ import unicode_literals
from django.shortcuts import render
from rest_framework import viewsets
from .models import Tesco
from .serializers import TescoSerializers
from django.core.urlresolvers import reverse_lazy, reverse
# Import filtering libraries
import django_filters
from rest_framework import filters
class TescoFilterSet(django_filter.FilterSet):
title__icontains = django_filter.Filter('Title', lookup_expr='icontains')
class Meta:
model = Tesco
fields = ('title__icontains', 'ProductID')
class TescoView(viewsets.ModelViewSet):
queryset = Tesco.objects.filter(Title__icontains='apple')
serializer_class = TescoSerializers
# Hook up filterset
filter_backends = (django_filters.rest_framework.DjangoFilterBackend, filters.OrderingFilter,)
filter_class = TescoFilterSet
# allow ordering on any field
ordering_fields = '__all__'
In my experience the nginx and apache webservers seem to work well with this pattern when you get to content caching.
For more on filtering, see the DRF guide on Filtering.
Ordering
Per your comment, you can order by specifying order_fields as seen above. Then you can add the ordering parameter.
vvvvvvvvvvvvvv
http://localhost:8000/Tesco/?title__icontains=apple&ordering=price
This will be ascending price.
Add a - before price and the order is reversed or descending:
http://localhost:8000/Tesco/?title__icontains=apple&ordering=-price
^