Can't figure out what to do to solve this problem. I am trying to create a custom user model but when i try to migrate it throws this error.
Here is managers.py:
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import gettext_lazy as _
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 or Phone numvber 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)
Here is models.py:
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from .managers import CustomUserManager
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.CharField(_('email or phone number'), max_length=175, unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
Thanks in advance, please explain what went wrong
Try this steps
settings.py
AUTH_USER_MODEL = 'your_app_name.CustomUser'
Steps
--- Delete `migrations` folder
--- also delete `db.sqlite3` (database file)
--- run command `python manage.py makemigrations your_app_name`
--- then run `python manage.py migrate`
Related
I want to create the custom user model with the email and/or the phone number as a login. I understood how make them separately but how to combine them together?
For instance, should i do the same like this but instead of the email the phone number?
Managers.py :
rom django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _
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)
Models.py:
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import ugettext_lazy as _
from .managers import CustomUserManager
class CustomUser(AbstractUser):
username = None
email = models.EmailField(_('email address'), unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
spouse_name = models.CharField(blank=True, max_length=100)
date_of_birth = models.DateField(blank=True, null=True)
def __str__(self):
return self.email
settings.py:
ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
ACCOUNT_CONFIRM_EMAIL_ON_GET = True
ACCOUNT_EMAIL_CONFIRMATION_ANONYMOUS_REDIRECT_URL = '/?verification=1'
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = '/?verification=1'
Thanks in advance, when you write an answer if you don't mind add a link to a useful material
i am creating api endpoints for user management using Djoser and i want to use a custom model to create user and login i only want to use email.
the user entity given to me does not have a username field
below i will share the various settings i have set up for my apps
#accounts/model.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class CustomUser(AbstractUser):
username = None
email = models.EmailField(unique=True)
REQUIRED_FIELDS = ['first_name', 'last_name']
USERNAME_FIELD = 'email'
def __str__(self):
return self.email
My serializer file
#accounts/serializers.py
from djoser.serializers import UserCreateSerializer, UserSerializer
from rest_framework import serializers
from rest_framework.fields import CurrentUserDefault
from .models import CustomUser
class UserCreateSerializer(UserCreateSerializer):
class Meta:
model = CustomUser
fields = ['id', 'email', 'first_name', 'last_name']
#settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
# 'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSIONS_CLASSES': (
'rest_framework.permissions.IsAuthenticated'
)
}
AUTH_USER_MODEL = 'accounts.CustomUser'
DJOSER = {
'LOGIN_FIELD': 'email',
'USER_CREATE_PASSWORD_RETYPE': True,
'SERIALIZERS': {
'user_create': 'accounts.serializers.UserCreateSerializer',
'user': 'accounts.serializers.UserCreateSerializer',
# 'current_user': 'accounts.serializers.CurrentUserSerializer'
}
when i try to register user i get
TypeError at /auth/users/
create_user() missing 1 required positional argument: 'username'
Request Method: POST
Request URL: http://127.0.0.1:8000/auth/users/
Django Version: 3.1
Exception Type: TypeError
Exception Value:
create_user() missing 1 required positional argument: 'username'
Exception Location: /home/femiir/.virtualenvs/codegarage/lib/python3.8/site-packages/djoser/serializers.py, line 73, in perform_create
Python Executable: /home/femiir/.virtualenvs/codegarage/bin/python
Python Version: 3.8.5
please what i my doing wrong ?
You need to have a custom user manager, probably something like this:
from django.contrib.auth.base_user import BaseUserManager
class MyUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
"""
Creates and saves a User with the given email, first name,
last name and password.
"""
if not email:
raise ValueError("Users must have an email address")
user = self.model(
email=self.normalize_email(email),
**extra_fields,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password=None, **extra_fields):
"""
Creates and saves a superuser with the given email, first name,
last name and password.
"""
user = self.create_user(
email,
password=password,
**extra_fields,
)
user.is_admin = True
user.save(using=self._db)
return user
And in your custom user model:
class CustomUser(AbstractBaseUser):
# [...]
objects = MyUserManager()
# [...]
I've taken the code from the django documentation about customizing the User model. They provide an example using the email as the username field (which is what you want).
You may keep the inheritance from AbstractUser but if you do not need most of the things that are in that model, you can also inherit your model from AbstractBaseUser, as in the example.
I am new to Django and am building a database-driven website using PyCharm.
I am having an issue with users registering/logging in. What is happening is, when a user registers, I check the "Database" tab to the right, and the information will be passed into a table named "SavBlock_user", which will have the users name, password, etc.. Then, when I try to log in, it won't allow me to login due to incorrect username/password. However, if I try to login using a username/password from a different table named "auth_user" (like username: admin / password: admin), then I can successfully login. I'm not sure how to fix this.
Ideally, what I would like to do is completely remove the "SavBlock_user" table and strictly use "auth_user" for all of my users, but I'm not sure how to do this. I may have created a 'custom' user model back when I was learning the system, but I can't remember.
My files:
Project\register\forms.py
from django import forms
from SavBlock.models import * # <--- Contains User
''' Form for users to register '''
class RegisterForm(forms.ModelForm):
email = forms.EmailField(
initial='myemail#savagez.com'
)
uso_validate = forms.BooleanField(
label='Are you a PSMC member? (Chief, Uso, Anak)',
initial=False
)
class Meta:
model = User
widgets = {
'password': forms.PasswordInput(),
}
fields = '__all__'
Project\register\views.py
from django.http import request
from django.shortcuts import render, redirect
from .forms import RegisterForm
# Create your views here.
def register(response):
if response.method == "POST":
form = RegisterForm(response.POST or None)
if form.is_valid():
form.save()
return redirect('/dashboard/')
else:
form = RegisterForm()
return render(response, 'register/register.html', {'form': form})
Project\SavBlock\models.py
from django.db import models
class User(models.Model):
username = models.CharField("user name", max_length=50, default='')
email = models.EmailField("email address", unique=True, default='DEFAULT VALUE')
first_name = models.CharField("first name", max_length=50)
last_name = models.CharField("last name", max_length=50)
password = models.CharField("password", unique=True, max_length=50, default='')
rank = {
0: 'Supporter',
1: 'Anak',
2: 'Uso',
3: 'Chief'
}
#TODO: FIT __INIT__
'''
def __init__(self, first_name, last_name, *args, **kwargs):
super().__init__(*args, **kwargs)
self.first_name = first_name.title()
self.last_name = last_name.title()
'''
# Magic method returns string of self
def __str__(self):
return f"User {self.first_name} {self.last_name} rank {self.rank}".strip()
#property
def get_full_name(self):
return f"{self.first_name} {self.last_name}".strip()
class Anak(User):
def __init__(self, first_name, last_name, tribe):
super().__init__(first_name, last_name)
self.tribe = tribe.title()
self.rank = User.rank[1]
class Uso(User):
def __init__(self, first_name, last_name, tribe):
super().__init__(first_name, last_name)
self.tribe = tribe.title()
self.rank = User.rank[2]
----EDIT----
I fixed the different user tables and basically reset the migrations. Now, all users are showing up under a single user table SavBlock_user. However, the login issue is still there.
Admin was created using the terminal manage.py createsuperuser command. I am able to login on the webpage using this account.
testing123 was created using the registration form. It pulls up a message that says "Please enter a correct username and password".
Anyone have any ideas?
Hi guys,
I'm a total noob regarding Python and Flaks. As part of my school project, I need to create user registration/login functionality with Flask and PyMongo.
So basically register a user with the username, email, and user password.
Login user with email and password.
Retrieve from MongoDb user default profile image following with profile date created, user username, and user email.
The way we need to do this is to create a User class.
When a user is successfully login they should see displayed on the front-end their username, email, default profile image, and date when the user profile was created.
Then the user needs to have an option to upload their profile image, username, and email.
Unfortunately, it has to be MongoDB for the database.
My current code is not uploading the User class blueprint to MongoDB and I don't know how to upload the default image and retrieve user info in the profile.html
Can you help me with this, please?
Any useful advice is welcome and if you can fix my code that would be great.
If you need more info let me know.
MY CODE SO FAR:
routes.py
import os
import json
from flask import Flask, flash, render_template, redirect, request, session, url_for
from flask_sqlalchemy import SQLAlchemy
from mongoengine import *
from datetime import datetime
from flask_pymongo import PyMongo
from bson.objectid import ObjectId
from werkzeug.urls import url_parse
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import LoginManager
from flask_login import current_user, login_user, logout_user, login_required
from forms import RegisterForm, LoginForm, AddTip, UpdateProfile
if os.path.exists("env.py"):
import env
app = Flask(__name__)
app.config["MONGO_DBNAME"] = os.environ.get("MONGO_DBNAME")
app.config["MONGO_URI"] = os.environ.get("MONGO_URI")
connect("MONGO_DBNAME", host=app.config["MONGO_URI"])
app.secret_key = os.environ.get("SECRET_KEY")
mongo = PyMongo(app)
login = LoginManager(app)
login.login_view = 'login'
login.login_message = "To access your profile, pleas log in!"
login.login_message_category = "log-info"
class User(Document):
username = StringField(unique=True, required=True)
email = EmailField(unique=True)
password = BinaryField(required=True)
age = IntField()
profile_image = ImageField()
registered = BooleanField(default=False)
date_created = DateTimeField(default=datetime.utcnow)
def __init__(self, username, email, date_created):
self.username = username
self.email = email
self.date_created = date_created
#staticmethod
def is_authenticated():
return True
#staticmethod
def is_active():
return True
#staticmethod
def is_anonymous():
return False
def get_id(self):
return self.username
#staticmethod
def check_password(password_hash, password):
return check_password_hash(password_hash, password)
#login.user_loader
def load_user(username):
user = mongo.db.users.find_one({"username": username})
if not user:
return None
return User(user["username"], user["email"], user["date_created"])
THEN MY REGISTER ROUTE:
#app.route("/registration", methods=["GET", "POST"])
def registration():
form = RegisterForm()
if form.validate_on_submit():
user = {
"username" : request.form.get("username").lower(),
"email" : request.form.get("email"),
"password" : generate_password_hash(request.form.get("password"))
}
mongo.db.users.insert_one(user)
session["user"] = request.form.get("username").lower()
flash("Welcome to your new profile", "reg-success")
return redirect(url_for("profile", username=session["user"]))
return render_template("registration.html", title="| Register", form=form)
LOG IN ROUTE:
#app.route("/login", methods=["GET", "POST"])
def login():
if current_user.is_authenticated:
return redirect(url_for("home"))
form = LoginForm()
if form.validate_on_submit():
user = mongo.db.users.find_one({"email": form.email.data})
if user and User.check_password(user["password"], form.password.data):
user_obj = User(username=user["username"])
login_user(user_obj)
next_page = request.args.get("next")
return redirect(next_page) if next_page else redirect(url_for("profile"))
else:
flash("Invalid username or password", "reg-danger")
return render_template("login.html", title="| Login", form=form)
PROFILE ROUTE:
#app.route("/profile", methods=["GET", "POST"])
#login_required
def profile():
form = UpdateProfile()
if form.validate_on_submit():
flash("Your details are updated", "reg-success")
else:
flash("Pleas check your details", "reg-danger")
return render_template('profile.html', title='| Profile', form=form)
I have the below code for Custom Users Model.
Can anyone help me out me with a Solution to restrict Access to Admin Site for Super Users only . Thanks in advance
# UserManager is for Custom User Model to override Django's Default Model
class UserManager(BaseUserManager):
def _create_user(self, email, password, is_superuser, **extra_fields):
if not email or not password:
raise ValueError("The given username or password must not be null")
user = self.model(
email=email,
password=password,
is_superuser=is_superuser,
last_login=now,
**extra_fields
)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email, password=None, **extra_fields):
return self._create_user(email, password, False, **extra_fields)
def create_superuser(self, email, password=None, **extra_fields):
return self._create_user(email, password, True, **extra_fields)
class Users(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
created_at_utc = models.DateTimeField(auto_now_add=True)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['password']
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return self.is_admin
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
class Meta:
db_table = "users"
I have the above code for Users, and following Code for Admin Panel to create and update User's
Can anyone help me out me with a Solution to restrict Access to Admin Site for Super Users only . Thanks in advance
class UserCreateForm(UserCreationForm):
class Meta:
model = Users
fields = (
"email","is_admin","is_superuser",
)
class UserChangeForm(BaseUserChangeForm):
class Meta:
model = Users
fields = (
"email","is_admin",
)
class UserAdmin(BaseAdmin):
form = UserChangeForm
add_form = UserCreateForm
fieldsets = (
(None, {"fields": ("email", "password","is_active","is_admin","is_superuser")}),
)
add_fieldsets = (
(None, {
"classes": ("wide",),
"fields": ("email", "password1", "password2","is_active","is_admin","is_superuser")}
),
)
filter_horizontal = ()
list_display = ("email","is_active", )
list_filter = ("is_active", )
search_fields = ("email",)
ordering = ("email",)
# Register your models here.
admin.site.register(Users, UserAdmin)
I have tried many solutions to restrict only SuperUser's to access the Admin Page when Login details are given. Can anyone help me out me with a Solution to restrict Access to Admin Site for Super Users only . Thanks in advance
I think what you are looking for field is is_staff which is there in
class AbstractUser(AbstractBaseUser, PermissionsMixin):
you can import this user from
from django.contrib.auth.models import AbstractUser
and you will find that it has field named as is_staff, so this is basically boolean field which determines if user has access to login to admin site or not, for more info do google search or find the article below
https://www.webforefront.com/django/adminpermissions.html
I see that you have created function as def is_staff(self): but you are not using field is_staff
Had the same issue. Instead of password=None, change it to password. And pass password=password into the create_user function as you see below, together with username=username:
class MyAccountManager(BaseUserManager):
def create_user(self, email, username, password):
if not email:
raise ValueError('Please add an email address')
if not username:
raise ValueError('Please add an username')
user = self.model(email=self.normalize_email(
email), username=username, password=password)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password):
user = self.create_user(email=self.normalize_email(
email), username=username, password=password)
user.is_active = True
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
Hope it works for you