How to use Djoser with multiple extended users? - python

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.

Related

How to connect 2 many to many fields in Django

I have 2 many to many fields in models and i want to connect them to each other i mean if i connect user in Admin Model with Counter Party i cant see that in Counter Party admin
How can i do that?
When im trying to do that it shows only in 1 model
models.py
class CustomUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, verbose_name='Пользователь')
user_counter = models.ManyToManyField('CounterParty', blank=True, verbose_name='Контрагенты пользователя')
def __str__(self):
return f'{self.user}'
class CounterParty(models.Model):
GUID = models.UUIDField(default=uuid.uuid4, editable=True, unique=True)
name = models.CharField(max_length=150, verbose_name='Наименование')
customer = models.BooleanField(default=False, verbose_name='Заказчик')
contractor = models.BooleanField(default=False, verbose_name='Подрядчик')
counter_user = models.ManyToManyField(User, blank=True, related_name='counter_user',
verbose_name='Пользователи контрагента')
class Meta:
verbose_name = 'Контрагент'
verbose_name_plural = 'Контрагенты'
def __str__(self):
return
admin.py
from django.contrib import admin
from .models import CustomUser, CounterParty, ObjectList, SectionList
from authentication.models import User
from authentication.admin import UserAdmin
class CustomUserInLine(admin.StackedInline):
model = CustomUser
can_delete = False
verbose_name_plural = 'Пользователи'
class CustomUserAdmin(UserAdmin):
inlines = (CustomUserInLine,)
#admin.register(CounterParty)
class CounterPartyAdmin(admin.ModelAdmin):
pass
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
user admin
counter party admin
You would not want to have these kinds of references with ManyToMany. Ideally you would have a one sided reference.
You can do an inline in your admin like this:
class CustomUserInLine(admin.StackedInline):
model = "CustomUser.user_counter.through"
Here are the docs for inline M2M in the admin: Django docs

How to not accept one email address for multiple registration accounts in django?

I made a registration page in django but the problem is that it should not accept one email address for multiple accounts. How to resolve this issue? If you need code then let me know.
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username} Profile'
forms.py
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username','email','password1','password2']
No need of entering email in forms , User model already contains a email column
your registration form should look like this
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class SignUpForm(UserCreationForm):
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password1', 'password2')
and you can simply use this line in models.py to make email Unique
User._meta.get_field('email')._unique = True

User Model Serializer required Validation Error

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)

How to do user registration in Django REST framework api

I have searched the whole web and cant find any satisfying answer
I have changed my user model by adding some custom fields
So now i got
'username',
'password',
'email',
'first_name',
'last_name',
'phonenumber',
'address'
instead of
'username',
'password',
'email',
'first_name',
'last_name', --- (these are default)---
This is my models.py
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
class userinformation(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phonenumber = models.CharField(max_length=100)
address = models.CharField(max_length=200)
class Meta:
verbose_name_plural = "User Information"
def __str__(self):
return str(self.user)+' - '+self.phonenumber+' - '+self.address
Im trying to make a Django REST framework api on which i can post
'username',
'password',
'email',
'first_name',
'last_name',
'phonenumber',
'address'
And register user with these details
what should i add in my veiws.py and serializers.py
Adding these other fields comes from manipulating the serializer. You could do something like this to expose those fields if you add field related_name='user_information' to your model definition:
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_information')
Then you create a serializer like:
class UserSerializer(serializers.HyperlinkedModelSerializer):
phonenumber = serializers.CharField(source='user_information.phonenumber')
address = serializers.CharField(source='user_information.address')
class Meta:
model = User
fields = ('username', 'password', 'email', 'first_name', 'last_name',
'phonenumber', 'address')
and instantiate that serializer in your view:
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
[...]

Delete related models with Django Rest Framework API

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)

Categories

Resources