rename `key` to `access_token` in django-rest-auth? - django

My django-rest-auth on authentication sends the following response
{"key":"XXXXXXXXXXXXXX"}
Now i am using ember-simple-auth specifically oauth2-password-grant for authentication which expects access_token in response body. After looking at source code of ember js here, i found out that the value access_token is defined as string and cannot be changed. My question is how can i implement authentication using the two stack. Is there any way that i can rename key to access_token in django ?

You can create your own MyLoginView which subclasses the original LoginView from django-rest-auth and create custom Serializer that returns the access_token field.
Something like this:
my_app/serializers.py
from rest_auth.models import TokenModel
from rest_framework import serializers
class MyTokenSerializer(serializers.ModelSerializer):
"""
Serializer for Token model.
"""
access_token = serializers.SerializerMethodField()
class Meta:
model = TokenModel
fields = ('access_token',)
def get_access_token(self, obj):
return object.key
my_app/views.py
from rest_auth.views import LoginView
from my_app.serializers import MyTokenSerializer
class MyLoginView(LoginView):
def get_response_serializer(self):
return MyTokenSerializer
urls.py
from my_app.views import MyLoginView
url(r'^login/$', MyLoginView.as_view(), name='my_login'),

Related

Set some views which use Django Rest Framework API

I have a very basic Django Rest API.
I don't know how to have some HTML views, in the same django project, which uses API (finally keeping API returning JSON only).
I followed this, but it seems to change the API View (in this case, curl will retrieve HTML and not JSON) :
https://www.django-rest-framework.org/api-guide/renderers/#templatehtmlrenderer
Do I need another Django App ? Another Django project ? Some JS ?
EDIT :
Ok, I've seen it's possible, thanks to rrebase.
But I can't retrieve the JSON with Curl, here my views.py
from rest_framework import generics
from rest_framework.renderers import TemplateHTMLRenderer, JSONRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.permissions import IsAdminUser
from . import models
from . import serializers
class UserListView(generics.ListAPIView):
renderer_classes = [JSONRenderer, TemplateHTMLRenderer]
template_name = 'profile_list.html'
def get(self, request):
queryset = models.CustomUser.objects.all()
serializer_class = serializers.UserSerializer
return Response({'profiles': queryset})
My models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
def __str__(self):
return self.email
I get an error "Object of type 'CustomUser' is not JSON serializable" when I request the API (http://127.0.0.1:8000/api/v1/users/)
Sorry, it's some different that initial question...
Yes, you can have both. The link you provided to docs has the following:
You can use TemplateHTMLRenderer either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint.
When making an API request, set the ACCEPT request-header accordingly to html or json.
Finally I made some conditions in my view, and it's working
class UserListView(generics.ListAPIView):
renderer_classes = [JSONRenderer, TemplateHTMLRenderer]
permission_classes = (IsAdminUser,)
def get(self, request):
queryset = CustomUser.objects.all()
if request.accepted_renderer.format == 'html':
data = {'profiles': queryset}
return Response(data, template_name='profile_list.html')
else:
serializer = UserSerializer(queryset, many=True)
data = serializer.data
return Response(data)

How do i also get user data with token "Key" in http response to django rest_auth login endpoint?

I am very new to working with django. i have developed an API for user Registration, Login and Logout with Django Rest-Auth Using Custom User Model extending AbstractUser.
When i call POST on Login API endpoint using credential, i get token in response, Please check below screenshot.
POST on Login API Endpoint
I also need to get Logged in User data. how do i do that!?
Any help would do.
TIA.
You can override the default TokenSerializer with a custom serializer that will include users.
in a file say yourapp/model.py
from django.conf import settings
from rest_framework import serializers
from rest_auth.models import TokenModel
from rest_auth.utils import import_callable
from rest_auth.serializers import UserDetailsSerializer as DefaultUserDetailsSerializer
# This is to allow you to override the UserDetailsSerializer at any time.
# If you're sure you won't, you can skip this and use DefaultUserDetailsSerializer directly
rest_auth_serializers = getattr(settings, 'REST_AUTH_SERIALIZERS', {})
UserDetailsSerializer = import_callable(
rest_auth_serializers.get('USER_DETAILS_SERIALIZER', DefaultUserDetailsSerializer)
)
class CustomTokenSerializer(serializers.ModelSerializer):
user = UserDetailsSerializer(read_only=True)
class Meta:
model = TokenModel
fields = ('key', 'user', )
and in your app settings use rest-auth configuration to override the default class
yourapp/settings.py
.
.
.
.
REST_AUTH_SERIALIZERS = {
'TOKEN_SERIALIZER': 'yourapp.models.CustomTokenSerializer' # import path to CustomTokenSerializer defined above.
}
You need to implement your custom view and serializer to do that.
First, you create your serializer for response with key and user data.
Since we don't have info on your model, this is just basic example:
class MySerializer(serializes.ModelSerializer):
key = serializers.SerializerMethodField()
def get_key(self, obj):
return create_token(obj)
class Meta:
model= User
fields = ( 'id', 'username', 'key', )
here the get_key can generate your token ( obj will be instance of your user model )
Then, I would suggest to look at how django-rest-auth implements LoginView which you use to get the token now.
And you create new view and take inspiration from LoginView implementation to understand how to obtain the token. And you use the serializer to create response you want.

Returning objects using JSONRESPONSE

I'm trying to return an object using Jsonresponse, Sorry im newb
This is my script:
setInterval(function()
{
$.ajax({
url: '/check_notification/',
type: "POST",
dataType: 'json',
success: function (data) {}
});
}, 2000);
in my django views.py:
def check_notification(request):
user = request.user
profile = Person.objects.get(profile=user)
notification = NotificationRecipient.objects.filter(profile=profile)
return JsonResponse(model_to_dict(notification))
You can make a model Serializers for models you want to pass as response. for more information read django rest framework tutorial about serializers an learn how to make json response. Or if you have a simple dictionary you can make json response with this code snippet at the end of your check_notification function. return HttpResponse(json.dumps(your dictionary))
I would recommend you use Django Rest Framework for returning Responses in JSON format as the Serialization of models can be don easily. You can start from here. There you will find something known as a ModelSerializer. Basically you create a serializer.py in your app folder with the following content:
from rest_framework import serializers
from .models import Person, NotificationRecipient
class PersonSerializers(serializers.ModelSerializer):
class Meta:
model = Person
fields = '__all__'
class NotificationRecipientSerializers(serializers.ModelSerializer):
class Meta:
model = NotificationRecipient
fields = '__all__'
The above code will serialize your models which means will be converted to json format.
Than in a file named as views_api.py, you can create a class that will be called using by the URL and will have your queryset defined. In your case the class will be defined as:
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Person, NotificationRecipient
from .serializers import NotificationRecipientSerializers
class NotificationAPIView(APIView):
def get(self,request):
user = request.user
profile = Person.objects.get(profile=user)
notification = NotificationRecipient.objects.filter(profile=profile)
return Response(notification)
This will return the response in JSON format. In your urls.py file call the NotificationAPIView as follows:
from django.urls import path
from .import views_api
urlpatterns = [
path('check/notification/', views_api.NotificationAPIView.as_view(), name='notification'),
]
Hope you get a basic understanding of what is going on there. For better understanding go through Django Rest Framework docs.

Django, TastyPie, Authentication, and custom middleware headache

I have a Django web application which requires authentication across the whole site. I've accomplished that with custom middleware which basically test if request.user.is_anonymous and, if they are, redirects them to the login page. It looks like this:
from django.contrib.auth.views import login
from django.contrib.auth import authenticate
from django.http import HttpResponseRedirect, HttpResponse
from django.utils import simplejson
from django.core import serializers
class SiteLogin:
"This middleware requires a login for every view"
def process_request(self, request):
if request.path != '/accounts/login/' and request.user.is_anonymous():
if request.POST:
return login(request)
else:
return HttpResponseRedirect('/accounts/login/?next=%s' % request.path)
Now I'm making an iOS app which, for now, will just do GET requests off the Django server. I am trying to use TastyPie to do this but I can't get the the authentication working. I am using ApiKeyAuthentication and, I believe, have set it up properly. However, it just redirects me to the login page. I'm wondering if I need to edit this middleware to handle TastyPie requests, but I thought TastyPie could to auth for me...
I feel like my situation is very similar to this question, but I wonder if my custom middleware is getting in the way.
Here's my api.py:
from django.contrib.auth.models import User
from django.db import models
from tastypie.resources import ModelResource
from cpm.systems.models import System
from cpm.products.models import Product
from tastypie.models import create_api_key
from tastypie.authentication import ApiKeyAuthentication
from tastypie.authorization import DjangoAuthorization, Authorization
models.signals.post_save.connect(create_api_key, sender=User)
class SystemResource(ModelResource):
class Meta:
queryset = System.objects.all()
resource_name = 'system'
authentication = ApiKeyAuthentication()
authorization = DjangoAuthorization()
class ProductResource(ModelResource):
class Meta:
queryset = Product.objects.all()
resource_name = 'product'
authentication = ApiKeyAuthentication()
authorization = DjangoAuthorization()
And a portion of my urls.py:
from cpm.ios.api import SystemResource, ProductResource
from tastypie.api import Api
v1_api = Api(api_name='v1')
v1_api.register(SystemResource())
v1_api.register(ProductResource())
admin.autodiscover()
urlpatterns = patterns('',
# iOS TastyPie related:
(r'^ios/', include(v1_api.urls)),
# .... more urls....
The URL I try to navigate to is:
http://192.168.1.130:8080/ios/v1/system/C0156/?username=garfonzo&api_key=12345?format=json
But I'm just redirected to my login page. I've followed the tutorial to a tee, created an api key on my Admin panel, and added WSGIPassAuthorization On to my apache config.
Any ideas?
EDIT I just removed that middleware altogether and now all I receive are 401 AUTHENTICATION errors...
EDIT 2
I should point out that if I remove the ?format=json then I get a response of: Sorry, not implemented yet. Please append "?format=json" to your URL.. So it's like it does authenticate, but then fails because I'm not specifying the format.
So my URL looks like this: http://192.168.1.130:8080/ios/v1/system/C0156/?username=garfonzo&api_key=12345 but as soon as I add the ?format=JSON then it goes to a 401 error.
TastyPie requests go through the same stack of middlewares as any typical django request. So, it's definitely your middleware. You have to rethink it, or just drop to the basics and use #login_required.
The api key doesn't work after you disabled the middleware because your URL is malformed. You can't use a ? in a querystring after you used it once. Try this url:
http://192.168.1.130:8080/ios/v1/system/C0156/?username=garfonzo&api_key=12345&format=JSON

How to remove username from Django registration 1.0

I have customize Django 1.5 (from djangoproject docs) authentication to login with email instead of username and its working perfect, but I am using Django-registration 1.0 to register users.
How do I remove the username field from django registration so users will only need to enter e-mail & password when registering.
Thank you all in advance.
Yaniv M
This should get you started.
Create your own form that is a subclass of RegistrationForm.
In forms.py
from registration.forms import RegistrationForm
class MyRegistrationForm(RegistrationForm):
# Override RegistrationForm
def __init__(self, *args, **kwargs):
super(RegistrationForm, self).__init__(*args, **kwargs)
self.fields.pop('username')
In views.py
from registration.views import RegistrationView
from yourapp.forms import MyRegistrationForm
class MyRegistrationView(RegistrationView):
form_class = MyRegistrationForm
In urls.py
url(r'^accounts/register/$', MyRegistrationView.as_view(),
name='registration'),
You can create a custom form class based on default RegistrationForm and use that class in the RegistrationView view.
As-is, it's complicated. You need to:
apply this patch because in d-r-1.0, models.py assumes your User model has a "username" field
create your own "backend" by copy/pasting/editing registration/backends/default/views.py
copy/paste/edit the registration form as well from registration/forms.py
most of the time you can use the registration views without modification