I want to create a registration app for my project.
Here is my serializer:
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from django.contrib.auth.models import User
from rest_framework import serializers
from django.contrib.auth import get_user_model # If used custom user model
UserModel = get_user_model()
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
def create(self, validated_data):
user = UserModel.objects.create(
username=validated_data['username'],
email=validated_data['email'],
first_name=validated_data['first_name'],
last_name=validated_data['last_name']
)
user.set_password(validated_data['password'])
return user
class Meta:
model = User
fields = ('id', 'username', 'password','email','first_name','last_name')
write_only_fields = ('password',)
read_only_fields = ('id',)
As you see, I use UserModel which is one of the default models of rest_framework. I want to make first_name field required for my registration serializer.
Waiting for your help.
You need to specify required=True attrubute for first_name field:
class UserSerializer(serializers.ModelSerializer):
first_name = serializers.CharField(required=True)
password = serializers.CharField(write_only=True)
Related
Hello I am new to django django rest framework and djoser I was just wondering. How do I use djoser with multiple extended users. Below is my model, serializers and views. I can't really find anything in the internet. And the Djoser documentation doesn't have anything on multiple users. Should I just use the build in token authentication of Django Rest Framework?
Model:
I am trying to inherit user with the student model and teacher model (as seen below). I want djoser to use these two model to create the users.
from django.db import models
from django.contrib.auth.models import User
from django.conf import settings
# Create your models here.
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, related_name='student')
age = models.IntegerField()
address = models.CharField(max_length=200)
def __str__(self):
return self.user.username
class Teacher(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, related_name='teacher')
description = models.TextField()
def __str__(self):
return self.user.username
class Course(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
price = models.FloatField(default=25.00)
def __str__(self):
return self.name
Serializer:
My serializer is not finished yet I still have to override the create and update methods.
from rest_framework import serializers
from api.models import *
from django.contrib.auth.models import User
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = ('age', 'address')
class StudentUserSerializer(serializers.ModelSerializer):
student = StudentSerializer()
class Meta:
model = User
fields = ('id', 'username', 'email', 'password', 'first_name', 'last_name', 'student')
extra_kwargs = {'password': {'write_only': True, 'required': True}}
class TeacherSerializer(serializers.ModelSerializer):
class Meta:
model = Teacher
fields = ('description', )
class TeacherUserSerializer(serializers.ModelSerializer):
teacher = TeacherSerializer()
class Meta:
model = User
fields = ('id', 'username', 'email', 'password', 'first_name', 'last_name', 'teacher')
extra_kwargs = {'password': {'write_only': True, 'required': True}}
class CourseSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = '__all__'
Views:
As well as my views I still have to setup permissions for the views.
from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet
from api.serializers import *
from api.models import *
from django.contrib.auth.models import User
# Create your views here.
class CourseView(ModelViewSet):
serializer_class = CourseSerializer
queryset = Course.objects.all()
class StudentView(ModelViewSet):
serializer_class = StudentUserSerializer
queryset = User.objects.all()
class TeacherView(ModelViewSet):
serializer_class = TeacherUserSerializer
queryset = User.objects.all()
Override the ModelViewset's perform_create() methods of TeacherView and StudentView to also create a user object.
I am new to Django, I tried to create a new models forms but while running my server i got this error:
(The form should add a "number" to the Profile database) Thanks for helping
(The form should add a "number" to the Profile database) Thanks for helping
File "C:\Users\xxx\PycharmProjects\web_lead_app\venv\lib\site-packages\django\forms\models.py", line 266, in __new__
raise FieldError(message)
django.core.exceptions.FieldError: Unknown field(s) (number) specified for User
views.py
from .forms import UserRegisterForm, ProfileUpdateForm, UserUpdateForm
from django.contrib.auth.decorators import login_required
#login_required()
def profile(request):
u_form = UserUpdateForm()
p_form = ProfileUpdateForm()
context = {
"u_form": u_form,
"p_form": p_form
}
return render(request, "users/profile.html", context)
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = User
fields = ["email", "number"]
class ProfileUpdateForm(forms.ModelForm):
number = forms.CharField(max_length=100)
class Meta:
model = Profile
fields = ["number"]
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
number = models.CharField(max_length=100)
def __str__(self):
return f"{self.user.username} Profile"
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = User
fields = ["email"]
Their is no number field in User model. So remove from form.
I am using rest-auth registration api for user registration. I have some extra fields in the UserProfile model.
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
org_id = models.CharField(max_length=100, default='')
is_teacher = models.BooleanField(blank=True, default=False)
def __str__(self):
return self.user.username
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
The UserProfile model is shown above. How can I add these fields to rest-auth regestration api endpoint and save the data to database.
I found an answer for myself
The serializers can be written as
from rest_framework import serializers
from rest_auth.registration.serializers import RegisterSerializer
from .models import UserProfile
class RegistrationSerializer(RegisterSerializer):
first_name = serializers.CharField(required=False)
last_name = serializers.CharField(required=False)
personal_id = serializers.CharField(required=True)
def custom_signup(self, request, user):
user.first_name = self.validated_data.get('first_name', '')
user.last_name = self.validated_data.get('last_name', '')
user.userprofile.personal_id = self.validated_data.get(
'personal_id', '')
user.save(update_fields=['first_name', 'last_name'])
user.userprofile.save(update_fields=['org_id'])
I didnt add the is_teacher because its optional.
In views.py extend the RegisterView of the rest_auth.regeistration.views to pass this data and its done.
class RegistrationView(RegisterView):
serializer_class = RegistrationSerializer
And finally add a url and pass RegisterView.as_view().
I'm trying to add user registration functionality to my Django REST application.
Here is my serializer:
from django.contrib.auth.models import User
from rest_framework import serializers
class UserSerializer(serializers.HyperlinkedModelSerializer):
snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True)
class Meta:
model = User
fields = ('url', 'id', 'username', 'password', 'email', 'snippets')
Here is my views:
from snippets.serializers import UserSerializer
from django.contrib.auth.models import User
from rest_framework import viewsets
class UserViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list` and `detail` actions.
"""
queryset = User.objects.all()
serializer_class = UserSerializer
Right now it's storing the password in plain text. How can I encode the password?
I would prefer to continue using the ViewSet classes as they're very clean and convenient.
class UserCreateSerializer(ModelSerializer):
def create(self, validated_data):
instance = User.objects.create_user(**validated_data)
return instance
class Meta:
model = User
fields = ('username', 'email', 'password')
class UserViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserCreateSerializer
permission_classes = (IsAuthenticated)
def get_permissions(self):
if self.action in ('create',):
self.permission_classes = [AllowAny, ]
return super(self.__class__, self).get_permissions()
def create(self, request, *args, **kwargs):
serializer = UserCreateSerializer(data=request.data)
if serializer.is_valid():
user = serializer.create(serializer.validated_data)
return Response('success')
else:
return Response(serializer.errors)
User.objects.create_user() will encode your password with django default encryption algorithm(PBKDF2).And you can use make_password to change your origin password to encoded one,or you can use user.set_password(request.data['pwd_new'])
from django.contrib.auth.hashers import make_password
more info here
When I use the Django Rest Framework to delete a User, the associated UserProfile object also gets deleted. I would like for the reverse relationship to also be true. How can I do this?
I have a Django model that represents a User's profile.
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
preferred_name = models.CharField(max_lengths=100)
#other fields here
Here are my Views:
class UserDetail(generics.RetrieveUpdateDestroyAPIView):
"""
API endpoint that represents a single user.
"""
model = User
serializer_class = UserSerializer
class UserProfileDetail(generics.RetrieveUpdateDestroyAPIView):
"""
API endpoint that represents a single UserProfile
"""
model = UserProfile
serializer_class = UserProfileSerializer
And the serializers:
class UserSerializer(serializers.HyperlinkedModelSerializer):
profile = serializers.HyperlinkedRelatedField(view_name = 'userprofile-detail')
class Meta:
model = User
fields = ('url', 'username', 'email', 'profile')
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = UserProfile
fields = ('url', 'preferred_name', 'user')
You could overwrite the delete method at your UserProfile class, like this:
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
preferred_name = models.CharField(max_lengths=100)
#other fields here
def delete(self, *args, **kwargs):
self.user.delete()
super(UserProfile, self).delete(*args, **kwargs)