i have a custom user model and i want to create a superuser from a view right, am currently using django restframework, below is my custom model and serializer with the views.
model.py
class CompanyUserManager(UserManager):
def _create_user(self, username, email, password, **extra_fields):
"""
Create and save a user with the given username, email and passsword
"""
if not username:
raise ValueError('The given username must be set')
if not email:
raise ValueError('The email must be set')
email = self.normalize_email(email)
username = self.model.normalize_username(username)
user = self.model(username=username, email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, username: str, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', False)
return self._create_user(username, email, password, **extra_fields)
def create_admin_user(self, username: str, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', False)
extra_fields.setdefault('is_admin', True)
# if extra_fields.get('is_staff') is not True:
# raise ValueError('Super user must have is_staff=True')
# if extra_fields.get('is_admin') is not True:
# raise ValueError('Super user must have is_admin=True')
# if extra_fields.get('is_superuser') is True:
# raise ValueError('Superuser must have is_superuser=False')
return self._create_user(username, email, password, **extra_fields)
def create_superuser(self, username: str, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_admin', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Super user must have is_staff=True')
if extra_fields.get('is_admin') is not True:
raise ValueError('Super user must have is_admin=True')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True')
return self._create_user(username, email, password, **extra_fields)
# Create your models here.
class CompanyUser(AbstractBaseUser, PermissionsMixin):
username_validator = UnicodeUsernameValidator()
username = models.CharField(_('username'), max_length=150, unique=True, help_text='Required, 150 characters or fewer', error_messages={'unique ': ' a User with this user name is already registered'}, validators=[username_validator])
email = models.EmailField(_('email address'), blank=False, unique=True)
phone = models.CharField(_('phone'), max_length=20, blank=True, null=True)
is_staff = models.BooleanField(_('staff status'), default=True, help_text='Designated user can login using this account')
is_active = models.BooleanField(_('active'), default=True, help_text='Designated whether this user should be treated as active')
is_superuser = models.BooleanField(_('superuser'), default=False, help_text='Designated user can login using this account')
is_admin = models.BooleanField(_('admin'), default=False, help_text='Designated user can login using this account')
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
email_verified = models.BooleanField(_('email_verified'), default=False,)
objects = CompanyUserManager()
EMAIL_FIELD = 'email'
USERNAME_FIELD: str = 'email'
REQUIRED_FIELDS = ['username', 'phone']
#property
def token(self):
token = jwt.encode({
'username': self.username,
'email': self.email,
'exp': datetime.utcnow() + timedelta(hours=24)},
settings.SECRET_KEY, algorithm='HS256')
return token
#property
def staff(self):
return self.is_staff
#property
def admin(self):
return self.is_admin
#property
def active(self):
return self.is_active
#property
def owner(self):
return self.is_superuser
serializer.py
class RegisterSerializer(serializers.ModelSerializer):
# username = serializers.CharField(max_length=100)
# email = serializers.EmailField()
# password = serializers.CharField(max_length=100)
# password2 = serializers.CharField(max_length=100)
# def validate(self, data):
# if data['password'] != data['password2']:
# raise serializers.ValidationError('Passwords must match')
# return data
password = serializers.CharField(max_length=100, write_only=True)
class Meta:
model = CompanyUser
fields = ("id", "username", "email", "password", "is_active")
extra_kwargs = {"password": {"write_only": True}}
def create(self, validated_data):
user = CompanyUser(**validated_data)
user.set_password(validated_data["password"])
user.save()
return user
def create_superuser(self, validated_data):
user = CompanyUser(**validated_data)
print(validated_data)
if "password" in validated_data:
from django.contrib.auth.hashers import make_password
validated_data["password"] = make_password(validated_data["password"])
user.set_password(validated_data["password"])
user.is_superuser = True
user.is_admin = True
user.is_staff = True
user.save()
return user
the create_superuser isnt working, it throws a keyerror password not found
view.py
class RegisterAPIView(GenericAPIView):
"""
A view that allow company owners to create an account
"""
serializer_class = RegisterSerializer
def post(self, request, *args, **kwargs):
serializers = self.serializer_class(data=request.data)
if serializers.is_valid():
serializers.save()
# self.serializer_class.create_superuser(serializers.data)
# serializers.create_superuser(serializers.data)
return Response(serializers.data, status=status.HTTP_201_CREATED)
return Response(serializers.errors, status=status.HTTP_400_BAD_REQUEST)
so this are my codes and i cant create a superuser from the endpoint, i dont want to use the django cli, any help please 😌
Related
I have Django with python-social-auth installed.
My custom user model:
class User(AbstractUser):
"""Custom User model."""
username = None
email = models.EmailField(blank=False, unique=True, verbose_name=_("Email"))
facebook_link = models.URLField(blank=True, verbose_name=_("Facebook profile link"))
contacts = models.CharField(blank=True, max_length=250, verbose_name=_("Contacts"))
hometown = models.CharField(blank=True, max_length=250, verbose_name=_("Hometown"))
start_coordinates = models.CharField(blank=True, max_length=100, verbose_name=_("Start coordinates"))
avatar = ProcessedImageField(
upload_to="avatar/",
format="JPEG",
options={"quality": 80},
default="avatar/default_avatar.jpg",
verbose_name=_("Image"),
)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = []
def __str__(self):
"""Model representation."""
return self.email
def get_absolute_url(self):
"""Get url to User's model instance."""
return reverse_lazy("public-profile", kwargs={"user_id": self.pk})
def get_full_name(self):
"""Concatenate fist and last names."""
full_name = " ".join([self.first_name, self.last_name])
return full_name.strip()
get_full_name.short_description = _("Full name")
class Meta:
verbose_name = _("User")
verbose_name_plural = _("Users")
Managers.py
class UserManager(BaseUserManager):
"""
Custom user model manager where email is the unique identifiers
for authentication instead of usernames.
"""
def create_user(self, email, password=None, **extra_fields):
"""Create and save a User with the given email and password."""
if not email:
raise ValueError(_("Email required"))
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
"""Create and save a SuperUser with the given email and password."""
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("is_active", True)
if extra_fields.get("is_staff") is not True:
raise ValueError(_("Superuser must have is_staff=True."))
if extra_fields.get("is_superuser") is not True:
raise ValueError(_("Superuser must have is_superuser=True."))
return self.create_user(email, password, **extra_fields)
I do succesfull authentication with Facebook with this code:
AUTHENTICATION_BACKENDS = (
'social_core.backends.github.GithubOAuth2',
'social_core.backends.google.GoogleOAuth2',
'social_core.backends.facebook.FacebookOAuth2',
'django.contrib.auth.backends.ModelBackend',
)
SOCIAL_AUTH_USER_MODEL = 'accounts.User'
SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = True
SOCIAL_AUTH_LOGIN_REDIRECT_URL = 'home'
SOCIAL_AUTH_LOGIN_URL = 'login'
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email', 'user_link', 'user_hometown']
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
'fields': 'id, name, email, picture.type(large), link, hometown'
}
SOCIAL_AUTH_FACEBOOK_EXTRA_DATA = [
('name', 'name'),
('email', 'email'),
('picture', 'avatar'),
('link', 'facebook_link'),
('hometown', 'hometown'),
]
As a result, I have a new user instance created in DB with the automatically populated fields:
fist_name, last_name, email.
How do I can populate the rest of fields (facebook_link, hometown) with data from response?
I am writing a test for my views to check if the POST data is validated but the test failed with this error,
self.assertTrue(form.is_valid())
AssertionError: False is not true
Am thinking the error might be coming from the form validity.
Below are my codes
tests.py
class CreateAccountTest(TestCase):
email = "example#gmail.com"
def test_signup_page_status_code(self):
response = self.client.get('/accounts/signup/')
self.assertEqual(response.status_code, 200)
def test_signup_url_by_name_and_uses_correct_template(self):
response = self.client.get(reverse ('register'))
self.assertEqual(response.status_code, 200)
self.assertTemplateUsed(response, 'registration/signup.html')
def test_signup_empty_form(self):
form = CustomUserCreationForm()
self.assertIn('first_name', form.fields)
self.assertIn('last_name', form.fields)
self.assertIn('password1', form.fields)
self.assertIn('password2', form.fields)
def test_signup__post_form(self):
request = HttpRequest()
request.POST = {
'email': self.email,
'first_name': 'Adam',
'last_name': 'Smith',
'password1': 'qazxswedcvfr',
'password2': 'qazxswedcvfr',
}
form = CustomUserCreationForm(request.POST)
self.assertTrue(form.is_valid())
form.save()
self.assertEqual(get_user_model().objects.all().count(), 1)
This is My CustomUser model
class CustomUserManager(BaseUserManager):
"""
Custom user model manger where email is the unique identifiers for authentication rather than username
"""
def create_user(self, email, password, **extra_fields):
'''
Create and save a user with the given email and password
'''
if not email:
raise ValueError(_('Email must be set'))
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password, **extra_fields):
'''
Create and save a superuser with the given email and password
'''
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('SuperUser must have is_staff=True')
if extra_fields.get('is_superuser') is not True:
raise ValueError('SuperUser must have is_superuser=True')
return self.create_user(email, password, **extra_fields)
This is the models.py for the Customusermanager
class CustomUser(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
I've been on dj_rest_auth on this project. Trying to add extra fields to the custom user model but it only saves the email and password. I think I have everything right but nothings working.
Heres my user model
class CustomUserManager(BaseUserManager):
"""
Custom user model manager where email is the unique identifiers
for authentication instead of usernames.
"""
def create_user(self, email, password, **extra_fields):
"""
Create and save a User with the given email and password.
"""
if not email:
raise ValueError('The Email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, email, password, **extra_fields):
"""
Create and save a SuperUser with the given email and password.
"""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self.create_user(email, password, **extra_fields)
class CustomUser(AbstractUser):
username = None
email = models.EmailField('email address', unique=True)
USERNAME_FIELD = 'email'
first_name = models.CharField(max_length=30, blank=True)
last_name = models.CharField(max_length=30, blank=True)
phone = models.CharField(max_length=30, blank=True)
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
serializers.py
class UserSerializer(serializers.ModelSerializer):
phone = serializers.CharField(max_length=30, allow_blank=True)
first_name = serializers.CharField(max_length=30, allow_blank=True)
last_name = serializers.CharField(max_length=30, allow_blank=True)
class Meta:
model = CustomUser
fields = ('id', 'email', 'first_name', 'last_name', 'phone')
def save(self, request):
user = super().save(request)
user.phone = self.data.get('phone')
user.first_name = self.data.get('first_name')
user.last_name = self.data.get('last_name')
user.save()
return user
settings.py
AUTH_USER_MODEL = 'users.CustomUser'
REST_AUTH_REGISTER_SERIALIZERS = {
'REGISTER_SERIALIZER': 'users.serializers.UserSerializer',
}
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
and finally in my urls.py
path('register/', RegisterView.as_view()),
From postman I send this post request
{
"email": "ahsan44411#gmail.com",
"password": "ahsan44411",
"password2": "ahsan44411",
"first_name": "ahsan",
"last_name": "mukhtar",
"phone": "64763868"
}
It only saves the email address, phone, first_name, last_name are not saved.
I have searched read nearly every problem on stackoverflow, without any luck, now I am posting here, please inform me if problem is not clear.
You can use the create function to save user data like this. Hope this answer will help you to solve your problem.
def create(self, data):
u = User(username=data["username"], email=data["email"],phone=data["phone"], first_name=data["first_name"],last_name=data["first_name"])
u.set_password(data["password"])
u.save()
return u
i tried create_user for email login as custom user model, but it's not working.
save() missing 1 required positional argument 'request'.
how can i solve this problem, help me please.
this is Traceback..
File "/Users/maxx/.local/share/virtualenvs/testauth--sM0sqjl/lib/python3.6/site-packages/rest_framework/views.py", line 480, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/maxx/Documents/workspace/python3/testauth/users/views.py", line 12, in post
user = serializer.save()
TypeError: save() missing 1 required positional argument: 'request'
models.py
class UserManger(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
if not email:
raise ValueError('You must give email address')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
return self._create_user(email, password, **extra_fields)
class User(AbstractBaseUser):
email = models.EmailField(unique=True)
nick_name = models.CharField(max_length=50)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManger()
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
serializers.py
class RegisterSerializer(serializers.Serializer):
email = serializers.EmailField(required=allauth_settings.EMAIL_REQUIRED)
password1 = serializers.CharField(write_only=True)
password2 = serializers.CharField(write_only=True)
def validate_email(self, email):
email = get_adapter().clean_email(email)
if allauth_settings.UNIQUE_EMAIL:
if email and email_address_exists(email):
raise serializers.ValidationError(
_("A user is already registered with this e-mail address."))
return email
def validate_password1(self, password):
return get_adapter().clean_password(password)
def validate(self, data):
if data['password1'] != data['password2']:
raise serializers.ValidationError(_("password fields didn't match."))
return data
def get_cleaned_data(self):
return {
'email': self.validated_data.get('email', ''),
'password1': self.validated_data.get('password1', ''),
}
def save(self, request):
adapter = get_adapter()
user = adapter.new_user(request)
self.cleaned_data = self.get_cleaned_data()
adapter.save_user(request, user, self)
setup_user_email(request, user, [])
return user
views.py
class UserCreateView(APIView):
def post(self, request):
serializer = RegisterSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
if user:
token = Token.objects.create(user=user)
json = serializer.data
json['token'] = token.key
return Response(json, status=status.HTTP_201_CREATED)
return Response(data=serializer.errors ,status=status.HTTP_400_BAD_REQUEST)
In your RegisterSerializer you have implemented a save() method that requires a positional argument named request, in UserCreateView you need to include the request in that method call.
class UserCreateView(APIView):
def post(self, request):
serializer = RegisterSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save(request) # <---- INCLUDE REQUEST
if user:
token = Token.objects.create(user=user)
json = serializer.data
json['token'] = token.key
return Response(json, status=status.HTTP_201_CREATED)
return Response(data=serializer.errors ,status=status.HTTP_400_BAD_REQUEST)
I created a custom user model for my Django project so that the user could login in with their email. However, the authentication wouldn't work.
Here is my code:
Views:
def login_view(request):
if request.method == "POST":
form = LoginForm(request.POST)
if form.is_valid():
email = form.cleaned_data.get('email')
password = form.cleaned_data.get('password')
user = authenticate(usename=email, password=password)
if user:
print(True)
login(request, user)
return redirect('/account/')
else:
print(str(password)+" "+str(email))
print(False)
else:
form = LoginForm()
return render(request, 'users/login.html',{'form': form})
my backend:
def authenticate(self, username=None, password=None,):
try:
user = User.objects.get(email=username)
if user.check_password(password):
return True
except User.DoesNotExist:
return True
def get_user(self, user_id):
try:
user = User.objects.get(pk=user_id)
if user.is_active:
return user
return None
except User.DoesNotExist:
return None
My User Model:
class UserManager(BaseUserManager):
def _create_user(self, first_name, last_name, username, email, is_admin, password=None, **extra_fields):
"""
creates a User with first name, last name, username, email, password
"""
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(
first_name=first_name,
last_name=last_name,
username=username,
email=email,
is_admin=is_admin,
is_active=True,
**extra_fields,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, first_name, last_name, username, email, password, **extra_fields):
return self._create_user(
first_name,
last_name,
username,
email,
False,
password,
**extra_fields
)
def create_superuser(self, first_name, last_name, username, email, password=None, **extra_fields):
return self._create_user(
first_name,
last_name,
username,
email,
True,
password,
**extra_fields
)
class User(AbstractBaseUser):
first_name = models.CharField(
max_length=256,
unique=False,
verbose_name='first name',
)
last_name = models.CharField(
verbose_name='last name',
max_length=256,
unique=False,
)
username = models.CharField(
verbose_name='username',
max_length=256,
unique=False,
)
email = models.EmailField(
verbose_name='email',
max_length=256,
unique=True,
)
is_active = models.BooleanField(
default=True,
)
is_admin = models.BooleanField(
default=False,
)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = [
'first_name',
'last_name',
'username',
]
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def get_full_name(self):
full_name = "{} {}".format(self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
return self.first_name
def __str__(self): # __unicode__ on Python 2
return self.email
def email_user(self, subject, message, from_email):
send_mail(subject, message, from_email, [self.email])
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
def has_perm(self, perm, obj=None):
return self.is_admin
#property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
My settings:
AUTH_USER_MODEL = 'custom_user.User'
AUTHENTICATION_BACKENDS = ('custom_user.backends.UserAuth', )
My Forms:
email = forms.CharField(
widget=forms.TextInput(attrs={'class': 'registerforms', 'placeholder': 'Email'}),
label='',
)
password = forms.CharField(
widget=forms.PasswordInput(attrs={'class': 'registerforms', 'placeholder': 'Password'}),
label='',
)
I do not get an error however it doesn't log the user in