Django Rest Framework Browsable API [No Renderers Found] - django-rest-framework

Any advice on why this happens?
This is my view. Note that I do specify the render_classes as JSONRenderer.
class RetailCustomerGetView(generics.RetrieveAPIView):
"""
API endpoint that allows users to be viewed or edited.
"""
render_classes = [JSONRenderer]
queryset = RetailCustomer.objects.all()
serializer_class = RetailCustomerSerializer
def get(self,request,format=None):
customer_count = RetailCustomer.objects.count()
content = {'customer_count':customer_count}
return Response(content)

I had to add the renderer in the DEFAULT_RENDERER_CLASSES in my projects settings.py file:
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10,
'TEST_REQUEST_DEFAULT_FORMAT': 'json',
'DEFAULT_RENDERER_CLASSES': ['rest_framework.renderers.JSONRenderer','rest_framework.renderers.BrowsableAPIRenderer'] # added JSONRenderer here
}

Related

How to differentiate my views in DRF swagger (yasg)?

I have an api made with djangorestframework and I want to add a swagger. It works well. In my api I have some views that require authentication with Basic or JWT so I set this up in my settings. The problem is that in my swagger gui I do not manage to tell which view is not requiring authentication. Do you know how to do that.
#api/urls.py
from drf_yasg import openapi
schema_view = get_schema_view(
openapi.Info(
title="Snippets API",
default_version='v1',
description="Test description",
terms_of_service="https://www.google.com/policies/terms/",
contact=openapi.Contact(email="contact#snippets.local"),
license=openapi.License(name="BSD License"),
),
public=True,
permission_classes=[permissions.AllowAny],
)
urlpatterns = [
path('mesures/', views.get_all),
path('mesure-add/', views.add_mesure),
path('token/', TokenObtainPairView.as_view(), name='obtain_tokens'),
path('token/refresh/', TokenRefreshView.as_view(), name='refresh_token'),
path('api-auth/', include('rest_framework.urls')),
path('register/', views.register_user),
path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]
In my settings.py
# in my settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
]
}
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(days=int(os.getenv("TOKEN_DAYS_LIFE"))),
}
SWAGGER_SETTINGS = {
'SECURITY_DEFINITIONS': {
'Basic': {
'type': 'basic'
},
'Bearer': {
'type': 'apiKey',
'name': 'Authorization',
'in': 'header'
}
}
}
In my views.py
#views.py
#swagger_auto_schema(methods=['post'], request_body=MesureSerializer)
#api_view(['POST'])
#permission_classes([IsAuthenticated])
def add_mesure(request):
serializer = MesureSerializer(data=request.data, context={'request':request})
# this is to provide the user automatically from token auth
# no need to provide it from the post request
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
else:
return Response(serializer._errors)
#swagger_auto_schema(methods=['post'], request_body=UserSerializer)
#api_view(['POST'])
def register_user(request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
as you can see my view register_user should not show a authentication in my swagger but this is not the case.
It is ok, I just needed to use the security=[] in #swagger_auto_schema for the specific view I want to tell there is no authentication required.
#swagger_auto_schema(methods=['post'], request_body=UserSerializer, security=[])

cannot set new password using django-graphql-auth

Graphene sends the email, but the url doesn't exist. How should I set up the token url for this?
I can't find docs on how to configure urls.py so that the link that it sends through the email works.
http://127.0.0.1:8090/activate/eyJ1c2VybmFtZSI6ImtkZWVuZXl6eiIsImFjdGlvbiI6ImFjdGl2YXRpb24ifQ:1m2a0v:04V3Ho0msVn7nHuFW469DC9GBYuUz2czfsFai09EOyM
settings.py
GRAPHQL_JWT = {
'JWT_VERIFY_EXPIRATION': True,
'JWT_LONG_RUNNING_REFRESH_TOKEN': True,
'ALLOW_LOGIN_NOT_VERIFIED': True,
'JWT_ALLOW_ARGUMENT': True,
"JWT_ALLOW_ANY_CLASSES": [
"graphql_auth.mutations.Register",
"graphql_auth.mutations.VerifyAccount",
"graphql_auth.mutations.ResendActivationEmail",
"graphql_auth.mutations.SendPasswordResetEmail",
"graphql_auth.mutations.PasswordReset",
"graphql_auth.mutations.ObtainJSONWebToken",
"graphql_auth.mutations.VerifyToken",
"graphql_auth.mutations.RefreshToken",
"graphql_auth.mutations.RevokeToken",
"graphql_auth.mutations.VerifySecondaryEmail",
],
}
schema.py
class AuthMutation(graphene.ObjectType):
register = mutations.Register.Field()
verify_account = mutations.VerifyAccount.Field()
token_auth = mutations.ObtainJSONWebToken.Field()
update_account = mutations.UpdateAccount.Field()
resend_activation_email = mutations.ResendActivationEmail.Field()
send_password_reset_email = mutations.SendPasswordResetEmail.Field()
password_reset = mutations.PasswordReset.Field()
password_change = mutations.PasswordChange.Field()
You need to create a view to handle this url.
from django.http import HttpResponseRedirect
from django.views import View
from graphql_auth.models import UserStatus
class ActivateView(View):
def get(self, request, **kwargs):
try:
token = kwargs.get("token")
UserStatus.verify(token)
except Exception:
return HttpResponseRedirect(f"/some/error/url")
return HttpResponseRedirect(f"/activate/thankyou")
And in your urls.py
urlpatterns = [
....
path("activate/<str:token>", ActivateView.as_view()),
...
]

Add documentation to generics.RetrieveAPIView 'retrieve' method's query param

I have a simple view which takes 'email' as a query param and I would like to have it documented in the OpenAPI autogenerated schema. So far I tried applying method_decorator together with swagger_auto_schema on the API View class definition, but without success:
from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi
from django.utils.decorators import method_decorator
#method_decorator(name='retrieve', decorator=swagger_auto_schema(manual_parameters=[
openapi.Parameter('email', openapi.IN_QUERY, description="Email to be checked", type=openapi.TYPE_STRING)]))
class EmailCheckView(generics.RetrieveAPIView):
serializer_class = EmailCheckSerializer
def get_queryset(self):
email = self.request.query_params.get('email', None)
if not email:
raise Http404
return User.objects.filter(email=self.kwargs['email'])
the auto generated models contains only information on the body coming from the serializer. Any ideas what's wrong?
DRF: 3.12.2
drf-yasg: 1.20.0
My swagger schema is added in urls.py with:
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
schema_view = get_schema_view(
openapi.Info(
title="My API",
default_version='v1',
description="",
),
public=True,
permission_classes=[permissions.AllowAny],
)
urlpatterns = [
...
path('docs/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
...
]
Change
name='retrieve'
to
name='get'
#method_decorator(
name="get", # change is here
decorator=swagger_auto_schema(
manual_parameters=[
openapi.Parameter(
"email",
openapi.IN_QUERY,
description="Email to be checked",
type=openapi.TYPE_STRING,
)
]
),
)
class EmailCheckView(generics.RetrieveAPIView):
serializer_class = EmailCheckSerializer
def get_queryset(self):
email = self.request.query_params.get("email", None)
if not email:
raise Http404
return User.objects.filter(email=self.kwargs["email"])
Note: I am not sure whether the issue belongs to method_decorator(...) or drf-yasg itself

Authentication credentials were not provided - Django

I'm having trouble with this error. Tried almost all available solutions but nothing working for me. At frontend side I am using Angular 6 and I am pretty sure it's not error from it. Hoping for a response soon and thanks in advance guys.
register/url.py
from django.urls import path, include
from rest_framework import routers
from . import views
from rest_framework.authtoken.views import ObtainAuthToken
router = routers.DefaultRouter()
router.register('users', views.UserViewSet)
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
path('', include(router.urls)),
#path('auth/', include('rest_framework.urls', namespace='rest_framework')),
path('auth/', ObtainAuthToken.as_view()),
]
serialier.py
from django.contrib.auth.models import User
from rest_framework import serializers
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email', 'password')
extra_kwargs = { 'password' : { 'write_only' : True , 'required':True } }
def create(self, validated_data):
user = User.objects.create_user(**validated_data)
return user
view.py
from django.contrib.auth.models import User
from rest_framework import viewsets
from .serializers import UserSerializer
from rest_framework.permissions import IsAuthenticated
class UserViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
authentication_classes = (TokenAuthentication, SessionAuthentication, BasicAuthentication)
permission_classes = (IsAuthenticated,)
setting.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework.authtoken',
'register',
'corsheaders',
]
The following error is displayed in the browser's console:
{“detail”:“Authentication credentials were not provided.”}
Your viewset has the IsAuthenticated permission class. In other words, an user must be authenticated in order to retrieve, update or even create an instance. Make sure that the appropriate headers are included in your requests.
For example, for a token authentication, as stated by Django Rest Framework documentation
For clients to authenticate, the token key should be included in the
Authorization HTTP header. The key should be prefixed by the string literal
"Token", with whitespace separating the two strings. For example:
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
In the particular case of an account creation, I'm not sure that it is intended for your application to require an user authentication.

Django Rest Framework: serializer.data show {} in the shell

serializer.data show {} in the python shell. But there are four instances with some value. And when I run django project it shows [{}, {}, {}, {}]. why?
I will follow this tutorial and I am running my project in ubuntu 16.04
Here is my code.
tutorial/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'snippets.apps.SnippetsConfig',
]
snippets/models.py
from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles
LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted((item, item) for item in get_all_styles())
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
class Meta:
ordering = ('created',)
serializer.py
from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
class SnippetSerializer(serializers.Serializer):
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
def create(self, validated_data):
"""
Create and return a new `Snippet` instance, given the validated data.
"""
return Snippet.objects.create(**validated_data)
def update(self, instance, validated_data):
"""
Update and return an existing `Snippet` instance, given the validated data.
"""
instance.title = validated_data.get('title', instance.title)
instance.code = validated_data.get('code', instance.code)
instance.linenos = validated_data.get('linenos', instance.linenos)
instance.language = validated_data.get('language', instance.language)
instance.style = validated_data.get('style', instance.style)
instance.save()
return instance
snippets/urls.py
from django.conf.urls import url
from snippets import views
urlpatterns = [
url(r'^snippets/$', views.snippet_list),
url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
]

Resources