I have a viewset like this:
class MyViewSet(CreateAPIView, RetrieveModelMixin, ListModelMixin, GenericViewSet):
queryset = MyModel.objects.all()
serializer_class = MySerializer
def post(self, request, *args, **kwargs):
import pdb; pdb.set_trace()
class MySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = MyModel
fields = ['id', 'field1', 'field2'] #only field1 is required in the model
The GET requests for list, and retrieve works perfectly. When I make a POST request, sending the field1 I get a status 201 and a new record is added to the database, so it works too.
But my method MyViewSet.post() that should overwrite the same one from generics.CreateAPIView never gets called.
Not only that, but I've tried to add the pdb.set_trace(), literally inside the generics.CreateAPIView.post() and in the CreateModelMixin.create() functions and neither stopped once I made the POST request.
So something else is handling this POST request and inserting into the DB, I just don't know what. And how can I overwrite it, so I can customize what should be done with a post request?
PS.: Also, I don't think it's a routing problem, my urls.py:
from rest_framework import routers
from myapp.views import MyViewSet, AnotherViewSet
router = routers.DefaultRouter()
router.register(r'route_one', MyViewSet)
router.register(r'route_two', AnotherViewSet)
I think you need to use the exact class in order to use POST api.
class MyView(CreateModelMixin, ListModelMixin, generics.GenericAPIView):
queryset = MyModel.objects.all()
serializer_class = MySerializer
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
In urls.py
from django.urls import path
from .views import MyView
urlpatterns = [
path('route_one', MyView.as_view(), name="my_view_detail")
]
Related
I have two user types a and b i need to write the below fbv into class based Logoutview(auth.view) how do i write the below fbv to cbv
views.py
#login_required
def logout(request):
if request.user.usertype_a:
logout(request)
return redirect(reverse('user_a_login'))
else:
logout(request)
return redirect(reverse('user_b_login'))
Give this a try
from django.views import View
class LogOutView(View):
def get(self, request, *args, **kwargs):
logout(request)
if request.user.usertype_a:
return redirect(reverse('user_a_login'))
return redirect(reverse('user_b_login'))
Or you can Use LogoutView and override its dispatch method for custom redirections
Try to add this to your urls.py:
from django.contrib.auth import views as auth_views
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
I am using rest_framework_simplejwt for authentication. My user/urls.py looks like this:
from django.contrib import admin
from . import views as user_views
from user.security.jwt_auth import GetToken
admin.autodiscover()
# Setup the URLs and include login URLs for the browsable API.
urlpatterns = [
path('login', GetToken.as_view(), name='login'),
]
This route works well and it returns the access_token and the refresh_token.
Now this is my client/urls.py
from django.urls import path, include
from django.contrib import admin
from client import views as client_views
admin.autodiscover()
urlpatterns = [
path('client', client_views.ClientList.as_view()),
path('client/<int:pk>', client_views.ClientDetail.as_view()),
path('create_client', client_views.create_client)
]
Here I am trying to use a decorator for the class. The decorator works well, the problem is that inside the decorator function the request.user does not exist, instead I have to do request.request.user. And when I do that the user is AnonymousUser. I already tried this decorator on the function based view by sending the access_token in the Authorization header and I am able to get the correct user, in other words the JWT Auth works automatically. Then Why it is not working in this scenario?
user/security/decorators.py
def authentication_for_class(function):
def wrap(request, *args, **kwargs):
# todo: Finish permissions
print(request.request.user)
if request.request.user.is_anonymous:
return JsonResponse({"detail": "You do not have permission to perform this action."}, status=403)
return function(request, *args, **kwargs)
wrap.__doc__ = function.__doc__
wrap.__name__ = function.__name__
return wrap
And this is my client/view.py
from user.security.decorators import authentication_for_class
class ClientList(APIView):
#authentication_for_class
def dispatch(self, request, *args, **kwargs):
return super(ClientList, self).dispatch(request, *args, **kwargs)
views.py
from paitent.mixini import HttpResponseMixin,SerializeMixin
from paitent.models import Paitent_Details
class PaitentCRUDCBV(View, HttpResponseMixin, SerializeMixin):
def get(self, id, *args, **kwargs):
paitent = Paitent_Details.objects.get(id=id)
json_data = self.render_to_serialize([paitent,])
return self.render_to_http_response(json_data)
urls.py
urlpatterns = [
url(r'^api/json',views.PaitentCRUDCBV.as_view()),
]
My requirement is based on id i have to fetch particular row form data base,from Frontend side i am passing id in url like:(url: "http://127.0.0.1:8000/api/json/?id=2").But i am not finding id inside my class ,don't know where i am doing wrong. please help me.
You can use query_params in view:
def get(self, request):
id = self.request.query_params.get('id')
....
You can get more information from documentation
1)I have edited your following code, you have to pass *request* in your function,
2)Inside the function calling request.query_params.get, you will get parameters value from the url
from paitent.mixini import HttpResponseMixin,SerializeMixin
from paitent.models import Paitent_Details
class PaitentCRUDCBV(View, HttpResponseMixin, SerializeMixin):
def get(self, request, *args, **kwargs):
id=self.request.query_params.get('id')
paitent = Paitent_Details.objects.get(id=id)
json_data = self.render_to_serialize([paitent,])
return self.render_to_http_response(json_data)
How to write a Django View with two slugs?
Each slug is from different Models.
I want to get www.example.com/category/slug1/slug2
Please provide an example code.
Views.py
class SubjectDetailView(generic.DetailView, SingleObjectMixin):
model = Programmesearch
template_name = 'mnsdirectory/subject_detail.html'
slug_field = 'subjectslug'
slug_url_kwarg = 'subjectslug'
Urls.py
app_name = 'mnsdirectory'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'), #views.indexSubjectDetailView(View)
path('study/<slug:subjectslug>/', views.SubjectDetailView.as_view(), name='subject-detail'),
path('study-abroad/<slug:studylevelslug>/', views.StudylevelDetailView.as_view(), name='studylevel-list'),
]
Models.py:
class Programmesearch(models.Model):
full_subject_name = models.CharField(max_length=100, blank=False, null=False)
subjectslug = models.SlugField(unique=True, editable=False, max_length=100)
class StudyLevel(models.Model):
study_level = models.CharField(max_length=100, blank=False, null=False)
studylevelslug = models.SlugField(unique=True, editable=False, max_length=100)
good first that my advice personally is that you have to have a good base of POO PYTHON and know well the MVT architecture, Django works a very similar architecture the MVC model view controller, now in View it goes all the logical part of python and there is where we will declare or whether we are going to end in which Template we are going to paint data processed by VIEW-Server.
Well, first of all how you want to work with those 2 models what we will do is the following:
We import the following methods
from django.shortcuts import render
from django.http import HttpResponse
from django.views.generic import View
class SubjectDetailView(View):
def get(self, request, *args, **kwargs):
queryset = Programmesearch.objects.all()
return render(request, 'mnsdirectory/subject_detail.html', {'element':queryset})
finally simply in the url you place this:
path('study/slug1/slug2/', views.SubjectDetailView.as_view(), name='subject-detail'),
perfect then send to the temple a dictionary a little more complex with 2 keys:
class SubjectDetailView(View):
def get(self, request, *args, **kwargs):
queryset = Programmesearch.objects.all()
queryset2 = StudyLevel.objects.all()
return render(request, 'mnsdirectory/subject_detail.html', {'element':queryset,'element2':queryset2})
#ulvi-damirli. You can use your urls.py like this:
Urls.py
re_path(r'^(?P<slug>[\w_-]+)/(?P<studylevel>[\w_-]+)/$',
views.SubjectDetailView.as_view(), name='subject-detail'),
and in your views.py, you can catch these slugs like this:
Views.py
class SubjectDetailView(generic.DetailView, SingleObjectMixin):
model = Programmesearch
template_name = 'mnsdirectory/subject_detail.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# subjectslug = self.object.slug # Not necessary since It's a DetailView
studyLevel = StudyLevel.objects.filter(
study_level=self.kwargs.get('studylevel', None))
Hope I helped you, let me know if It worked
I am having trouble creating a customizable swagger schema in the Django Rest Framework. I have read pages of documentation, but have not found a clear cut example on how to generate swagger annotations in python.
I am aware that swagger/schema documentation is readily generated when using ViewSets in Django. However, I am solely using APIViews and want to write a customized schema. I have tried creating a CoreAPI schema but am unaware of how to implement it. I am enclosing some of my sample code and some screenshots as well. The screen shots go from what I have to what I want.
Sample code:
urls.py
from django.conf.urls import url, include
from rest_framework.urlpatterns import format_suffix_patterns
from Views import SampleView as sv
from rest_framework_swagger.views import get_swagger_view
from rest_framework.documentation import include_docs_urls
from rest_framework.renderers import CoreJSONRenderer
from rest_framework.schemas import get_schema_view
schema_view enter code here= get_swagger_view(
title='Sample API')
urlpatterns = [
url(r'^sample/$', pv.SampleList.as_view()),
url(r'^sample/(?P<id>[a-f\d]{24})/$', sv.SampleDetail.as_view()),
url('^schema/$', schema_view),
]
urlpatterns = format_suffix_patterns(urlpatterns)
views.py
from rest_framework.views import APIView
from Manager.SampleManager import SampleManager as sm
_sampleManager = sm()
class SampleList(APIView):
"""
get:
Return a list of all the existing samples.
post:
Create a new sample.
"""
def get(self, request, format=None):
return _sampleManager.getAll()
def post(self, request, format=None):
return _sampleManager.create( request)
class SampleDetail(APIView):
"""
get:
Get a sample.
put:
Update a sample.
delete:
Delete a sample.
"""
def get(self, request, id, format =None):
return _sampleManager.getById( id)
def put(self, request, id, format =None):
return _sampleManager.update( request, id)
def delete(self, request, id, format =None):
return _sampleManager.deleteById( id)
Serializers.py
from rest_framework_mongoengine.serializers import DocumentSerializer
from .modles import Sample, SampleInner
from Serializers.SampleInnerSerializer import SampleInnerSerializer
class SampleSerializer(DocumentSerializer):
other = SampleInnerSerializer(many=True)
class Meta:
model = Sample
fields = '__all__'
def create(self, validated_data):
samples = validated_data.pop('other')
created_instance = super(SampleSerializer, self).create(validated_data)
for sample_data in samples:
created_instance.other.append(SampleInner(**sample_data))
created_instance.save()
return created_instance
def update(self, instance, validated_data):
samples = validated_data.pop('other')
updated_instance = super(SampleSerializer, self).update(instance, validated_data)
for sample_data in samples:
updated_instance.other.append(SampleInner(**sample_data))
updated_instance.save()
return updated_instance
Schema.py
import coreapi
from rest_framework.decorators import api_view, renderer_classes
from rest_framework import renderers, response
schema = coreapi.Document(
title='Sample API',
content={
'sample': coreapi.Link(
url='/sample/',
action='post',
fields=[
coreapi.Field(
name='from',
required=True,
location='query',
description='City name or airport code.'
),
coreapi.Field(
name='to',
required=True,
location='query',
description='City name or airport code.'
),
coreapi.Field(
name='date',
required=True,
location='query',
description='Flight date in "YYYY-MM-DD" format.'
)
],
description='Create partner'
)
}
)
#api_view()
#renderer_classes([renderers.CoreJSONRenderer])
def schema_view(request):
return response.Response(schema)
There is two solution for you in this senario, One "go with the GenricApiView" Two "Create Custom row Schema"
let's go with
-- >solution one.
urls.py
schema_view = get_swagger_view(title='Test All API')
urlpatterns = [
path('swagger2/', schema_view),
]
view.py
class LoginAPIView(generics.GenericAPIView):
serializer_class = LoginSerializer
permission_classes = [permissions.AllowAny]
def post(self, request):
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
return Response(serializer.data, status=status.HTTP_200_OK)
Result
--> Solution two:
urls.py
configuration is same as before
views.py
class BlacklistTokenAdding(APIView):
permission_classes = [permissions.AllowAny]
schema = ManualSchema(fields=[
coreapi.Field(
"first_field",
required=True,
location="body",
schema=coreschema.String()
),
coreapi.Field(
"second_field",
required=True,
location="body",
schema=coreschema.String()
),
])
def post(self, request, format='json'):
try:
refresh_token = request.data["refresh_token"]
token = RefreshToken(refresh_token)
token.blacklist()
return Response(status=status.HTTP_200_OK)
except Exception as e:
return Response(status=status.HTTP_400_BAD_REQUEST)
//Note the first_field & second_field is to demonstration you can add here as much field as you want.
Result