How do you Serialize the User model in Django Rest Framework - python

Am trying to familiarize myself with the Django Rest Framework. Tried an experiment to list the users I created but the serializer always returns blank objects. Here's my code:
serializers.py
from rest_framework import serializers
from django.contrib.auth.models import User
class CurrentUserSerializer(serializers.Serializer):
class Meta:
model = User
fields = ('username', 'email', 'id')
urls.py
from django.urls import include, path
from administration import views
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'admin', views.CurrentUserViewSet)
urlpatterns = [
path('', include(router.urls)),
]
views.py
from django.shortcuts import render
from django.contrib.auth.models import User
from administration.serializers import CurrentUserSerializer
from rest_framework import viewsets
# Create your views here.
class CurrentUserViewSet(viewsets.ReadOnlyModelViewSet):
queryset = User.objects.all()
serializer_class = CurrentUserSerializer
Rest of the code is pretty much boilerplate based on the DRF tutorial.
The result I'm getting is blank objects for every user. The number of blanks grows and shrinks if I add/remove a user, which tells me I'm at least partially hooked up to the User model. Example below:
[{},{},{}]
What I'm expecting is something like:
[{"username": "jimjones", "email": "jim&jones.com", "id": 0},{...}]
Any help appreciated.

Solved. Was a typo. In serializers.py the class should be using "serializers.ModelSerializer" and not "serializers.Serializer".

Related

How to add some cutom code to post method in django rest framework

I am new to django rest framework. I was trying to build a API where I want to edit the POST method so that I could execute some actions and change some data from the POST body.
I tried to follow some documentations and Guide from django rest framework website but didnt followed any. Please help me.
Here I need to set some values for some fields that are going to be saved in the database.
views.py
from .models import LoginActivity
from .serializers import LoginActivitySerializers
class LoginActivity(viewsets.ModelViewSet):
queryset = LoginActivity.objects.all()
serializer_class = LoginActivitySerializers
urls.py
from django.urls import path, include
from rest_framework import routers
from . import views
router = routers.DefaultRouter()
router.register(r'LoginActivity', views.LoginActivity, basename='LoginActivity')
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
appname='api'
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
serializers.py
from rest_framework import serializers
from .models import LoginActivity
class LoginActivitySerializers(serializers.HyperlinkedModelSerializer):
class Meta:
model = LoginActivity
fields = ('id', 'user_id', 'datetimelog', 'device_os', 'device_token', 'device_model')
Please Help me.
you can override rest framework create method which come from viewsets.ModelViewSet and update request data or perform some other actions.
from .models import LoginActivity
from .serializers import LoginActivitySerializers
class LoginActivity(viewsets.ModelViewSet):
queryset = LoginActivity.objects.all()
serializer_class = LoginActivitySerializers
def create(self, request, *args, **kwargs):
# here you have your post data in request.data
data = request.data
# you can do some action here just before create action
# after that you can call super method or return your response
serializer = self.get_serializer(data=data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
return Response(status=status.HTTP_201_CREATED)

How to make a signup view using Class based views in Django?

When I started to use Django, I was using FBVs ( Function Based Views ) for pretty much everything including signing up for new users.
But as I delved deep more into projects, I realized that Class-Based Views are usually better for large projects as they are more clean and maintainable but this is not to say that FBVs aren't.
Anyway, I migrated most of my whole project's views to Class-Based Views except for one that was a little confusing, the SignUpView.
In order to make SignUpView in Django, you need to utilize CreateView and SuccessMessageMixin for creating new users as well as displaying a success message that confirms the account was created successfully.
Here's the code :
views.py:
from .forms import UserRegisterForm
from django.views.generic.edit import CreateView
class SignUpView(SuccessMessageMixin, CreateView):
template_name = 'users/register.html'
success_url = reverse_lazy('login')
form_class = UserRegisterForm
success_message = "Your profile was created successfully"
and, the forms.py:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email', 'first_name']
You can use Django's CreateView for creating a new user object.
# accounts/views.py
from django.contrib.auth.forms import UserCreationForm
from django.urls import reverse_lazy
from django.views import generic
class SignUp(generic.CreateView):
form_class = UserCreationForm
success_url = reverse_lazy('login')
template_name = 'signup.html'
For more info, check https://learndjango.com/tutorials/django-signup-tutorial

How to handle login + FB login at the same time with django-allauth module?

Well.. I started to create simple app. Following official doc of Django, I created auth logic in separate app with name users, like this:
users/urls.py:
from django.urls import path, re_path, include
from . import views
urlpatterns = [
path('', include('django.contrib.auth.urls')),
path('profile/', views.redirect_to_user_profile, name='redirect-user-profile'),
re_path('profile/(?P<pk>\d+)/', views.UserProfileView.as_view(), name='user-profile'),
path('register/', views.UserRegisterView.as_view(), name='user-register'),
users/views.py:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.views import generic
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
# Create your views here.
def redirect_to_user_profile(request):
url = f'/users/profile/{request.user.id}'
return HttpResponseRedirect(redirect_to=url)
class UserProfileView(generic.DetailView):
model = User
template_name = 'user_profile.html'
class UserRegisterView(generic.CreateView):
form_class = UserCreationForm
template_name = 'register.html'
success_url = '/users/login'
Everything was fine, so I decided to extent basic Django user, to add profile image for example (and more fields later) like this:
users/models.py:
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
# Create your models here.
class ProfileUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_image = models.URLField()
#receiver(post_save, sender=User) # Still don't know how, but next rows create ProfileUser when User is created
def create_user_profile(sender, instance, created, **kwargs):
if created:
ProfileUser.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profileuser.save()
def __str__(self):
return f"{self.user}"
Still working fine. Then I decided to add FB login, after some researh I found django-allauth module, following it documentation and add one row in users/urls.py:
path('fb/', include('allauth.urls')),
It also working, But here comes the problem currently I have two separate modules for authorization:
Basic django User auth logic:
And django-allauth auth logic:
How to handle this (best way):
What I think: To use only Django-allauth, but is there a way to extend it with additional ProfileUser, like extend it now with Django User?
Using only Django-allauth is a good assumption.
The way to extend Django User is by something like that:
class ProfileUser(AbstractUser):
profile_image = models.URLField()
REQUIRED_FIELDS = ['email']
class Meta:
managed = True
db_table = 'profile_user'
However, change like that could enforce to make migrations from the beginning. Or trying to fix them manually. This is because of auth app migrations are done as a second just after contenttypes.
Okay, based on #artusiep answer and a lot of research, I found that the best way is to use one of them, but not both at the same time. Also found very good tutorial about both implementation here

Trying to pass a string for querying through Django Rest Framework urls

I have a django project and I am using Django Rest Frameowkr. I setup up a model, serializer, view, and url for a users model. I have the urls file. I want to passing in something like a username when the api url is called. I currently have it setup to have a primary key so when I enter a primary key it works. I want to switch it to username. I also want the serializer query to return the user object iwth the usename I pass in.
I am using Djangos standard User object from django.contrib.auth.models
Here is the code I have
Urls.py
from django.urls import path
from django.contrib.auth.models import User
from .views import UserListView, UserDetailsView
from .views import ProfileListView, ProfileDetailsView
from .views import RoleListView, RoleDetailsView
urlpatterns = [
path('user/', UserListView.as_view()),
path('user/<pk>', UserDetailsView.as_view()),
]
serializer.py file
from rest_framework import serializers
from django.contrib.auth.models import User
from users.models import Profile, Role
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'is_staff', 'last_login')
Views.py file
from rest_framework.generics import ListAPIView, RetrieveAPIView
from django.contrib.auth.models import User
from users.models import Profile, Role
from .serializers import UserSerializer, ProfileSerializer, RoleSerializer
class UserListView(ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
class UserDetailsView(RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
Specify the lookup_field in UserDetailsView and change the urls pattern in urls.py as below
# urls.py
urlpatterns = [
path('user/', UserListView.as_view()),
path('user/<username>', UserDetailsView.as_view()),
]
# views.py
class UserDetailsView(RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
lookup_field = 'username'

How to return html or json from ViewSets depending on client django rest framework

I've created an APIs endpoints for mobile developers with all of the logic there. Now I need to create a web version of this app. Is it possible to not write the views specifically for this, but use already existing one in APIs?
In API I am using Django Rest Framework ViewSets.
Assume that this is my models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=20)
description = models.CharField(max_length=100, blank=True, null=True)
Then this is going to be my serializers.py:
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ('id', 'title', 'description')
read_only_fields = ('id',)
viewsets.py:
from rest_framework import viewsets
from .serializers import PostSerializer
from .models import Post
class PostViewSet(viewsets.ModelViewSet):
model = Post
queryset = Post.objects.all()
serializer_class = PostSerializer
urls.py
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'posts', viewsets.Post, base_name='post')
urlpatterns = router.urls
I've seen this HTML & Forms in docs, but if I put renderer_classes and template_name it just renders html with the parameters that I want, but I want to have a separate endpoints for just returning json for mobile developers and rendering a user-friendly html for web version. Is it possible to do this and if it is, how do I handle this?
I think you will have to manually create a separate endpoint to handle HTML requests, but you can easily achieve this using Template Renderers

Categories

Resources