This is my User class:
class User(TimeStampedModel, AbstractBaseUser):
name = models.CharField(null=False, max_length=255)
username = models.CharField(null=False, unique=True, max_length=255)
email = models.EmailField(null=True)
mobile_number = models.CharField(null=True, max_length=255)
bio = models.CharField(null=True, max_length=255)
title = models.CharField(null=True, max_length=255)
posts = models.IntegerField(default=0)
views = models.IntegerField(default=0)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
last_active_on = models.DateTimeField(auto_now=True)
objects = CustomUserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['name']
When I try to update the user from admin dashboard I get 'field cannot be empty error' for the following fields: mobile_number, email, bio, title
Any idea on how to resolve this?
Specify blank=True in your model for those fields.
class User(TimeStampedModel, AbstractBaseUser):
name = models.CharField(null=False, max_length=255)
username = models.CharField(null=False, unique=True, max_length=255)
email = models.EmailField(null=True, blank=True) # add 'blank' argument
mobile_number = models.CharField(null=True, max_length=255, blank=True) # add 'blank' argument
bio = models.CharField(null=True, max_length=255, blank=True) # add 'blank' argument
title = models.CharField(null=True, max_length=255, blank=True) # add 'blank' argument
posts = models.IntegerField(default=0)
views = models.IntegerField(default=0)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
last_active_on = models.DateTimeField(auto_now=True)
objects = CustomUserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['name']
If a field has blank=True, form validation will allow entry of an empty value. Default value for blank argument is False.
Note: null is purely database-related, whereas blank is validation-related.
If a field has blank=True, form validation will allow entry of an empty value.
If a field has null=True, Django will store empty values as NULL in the database.
Related
I get such an error while migrating to a database:
return Database.Cursor.execute(self, query)
django.db.utils.OperationalError: foreign key mismatch - "user_auth_customer"
referencing "user_auth_profile"
I have checked Foreign_Keys of my models and they look good.
I have no idea why I receive that error :(
Please, help me out here.
class Customer(AbstractUser):
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
id = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=True, editable=False)
profile = models.OneToOneField("Profile", related_name="user_profile",
on_delete=models.CASCADE, null=True)
first_name = models.CharField(max_length=50, null=True, blank=True)
last_name = models.CharField(max_length=50, null=True, blank=True)
username = models.CharField(max_length=30, null=True, blank=True)
phone = models.CharField(max_length=10, default='', null=True, blank=True)
email = models.EmailField(validators=[validators.EmailValidator()],
unique=True)
password = models.CharField(max_length=100, null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True)
#staticmethod
def get_customer_by_email(email):
try:
return Customer.objects.get(email=email)
except:
return False
def isExists(self):
if Customer.objects.filter(email=self.email):
return True
return False
class Meta:
verbose_name = 'Customer'
verbose_name_plural = 'Customers'
class Profile(models.Model):
first_name = models.CharField(max_length=50, null=True, blank=True)
last_name = models.CharField(max_length=50, null=True, blank=True)
phone = models.CharField(max_length=10, default='', null=True, blank=True)
email = models.EmailField(primary_key=True, unique=True, validators=[validators.EmailValidator()])
password = models.CharField(max_length=100, null=True, blank=True)
# Add a photo field
owner = models.OneToOneField(Customer, related_name='profile_owner',
on_delete=models.SET_NULL, null=True)
username = models.CharField(max_length=30, null=True, blank=True,
validators=[UnicodeUsernameValidator()])
date_created = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'Profile'
verbose_name_plural = 'Profiles'
if you need any else details, I can provide you with those in the comments.
You can't have both ways OneToOneField. Choose one way.
If you delete Customer's profile field, then still you will have possibility to call relation with:
customer = Customer.objects.get(id=1)
customer.profile # that will call Customer's related Profile object
Assuming, that you will change related_name='profile_owner' to simpler related_name='profile'.
Read more about OneToOneRelationships.
i have follwing structure:
class FullTreeAdminUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
class AdminFullTreeListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = FullTreeAdminUserSerializer
When i query users/all i have following error:
Cannot resolve keyword 'created' into field
The user model looks like
class User(AbstractBaseUser, PermissionsMixin):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
username = models.CharField(max_length=255, unique=True, db_index=True)
first_name = models.CharField(max_length=255, blank=True)
last_name = models.CharField(max_length=255, blank=True)
email = models.EmailField(max_length=255, unique=True, db_index=True)
is_verified = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
date_joined = models.DateTimeField(auto_now=True)
balance = models.FloatField(default=0.0)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
I cannot figure out where the problem is. I simply wanna get list of all user and i didn't expect such problems. I don't have created filed in my user model
I am working with a database that stores sex as 0 - male and 1 - female.
My forms.py looks like this
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = TbUser
def clean_username(self):
username = self.cleaned_data["username"]
try:
TbUser.objects.get(username=username)
except TbUser.DoesNotExist:
return username
raise forms.ValidationError(self.error_messages['duplicate_username'])
class TbUserRegisterForm(CustomUserCreationForm):
email = forms.EmailField()
class Meta:
model = TbUser
fields = ['username', 'email', 'cellphone', 'sex', 'role', 'department', 'password1', 'password2']
Django user model
class TbUser(AbstractBaseUser, PermissionsMixin):
id = models.CharField(primary_key=True, max_length=32, default=uuid.uuid4)
username = models.CharField(max_length=40, blank=True, null=True, unique=True, db_column='usname')
password = models.CharField(max_length=255, blank=True, null=True, db_column='dj_psword')
email = models.CharField(max_length=255, blank=True, null=True)
cellphone = models.CharField(max_length=100, blank=True, null=True)
image_id = models.CharField(max_length=40, blank=True, null=True)
sex = models.IntegerField(blank=True, null=True)
is_available = models.IntegerField(blank=True, null=True)
role = models.ForeignKey(TbRole, on_delete=models.CASCADE)
department = models.ForeignKey(TbDepartment, on_delete=models.CASCADE)
is_superuser = models.BooleanField(default=False, blank=True, null=True, db_column='default_super')
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
objects = TbUserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
class Meta:
managed = False
db_table = 'tb_user'
def __str__(self):
return '%s' % self.username
Since sex is an integer field, the UI form field is not a choice field but just showing arrows for incrementing the integer. Is there a way to make it a choice field that for m will store 0 and f - 1?
Yes, you can assign this to the choices=… parameter [Django-doc]:
SEX_CHOICES = [
(0, 'Male')
, (1, 'Female')
]
class TbUser(AbstractBaseUser, PermissionsMixin):
# …
sex = models.IntegerField(blank=True, null=True, choices=SEX_CHOICES)
# …
Default User Model:
class User(AbstractBaseUser, PermissionsMixin):
avatar = models.ImageField(upload_to='user/avatar', null=True, blank=True)
date_joined = models.DateField(auto_now_add=True)
username = models.EmailField(unique=True, null=False, blank=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_employer = models.BooleanField(default=False)
is_employee = models.BooleanField(default=False)
object = managers.UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = []
class Meta:
verbose_name = 'User'
verbose_name_plural = 'Users'
Employer model:
class Employer(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True)
name = models.CharField(max_length=256, blank=False, null=False)
address = models.CharField(max_length=256, blank=False, null=False)
fax = models.DecimalField(max_digits=11, decimal_places=2, blank=True, null=True)
email = models.EmailField(unique=True, blank=False, null=False)
economic_code = models.DecimalField(max_digits=20, decimal_places=2, blank=True, null=True)
national_id = models.DecimalField(max_digits=20, decimal_places=2, blank=True, null=True)
Employee model:
class Employee(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True)
employer = models.ForeignKey(Employer, null=False, blank=False, on_delete=models.CASCADE)
first_name = models.CharField(max_length=50, null=False, blank=False)
last_name = models.CharField(max_length=100, null=False, blank=False)
national_id = models.PositiveIntegerField(null=False, blank=False)
date_of_birth = models.DateField(blank=False, null=False)
post = models.CharField(max_length=100, null=True, blank=True)
mobile = models.DecimalField(max_digits=11, decimal_places=2, null=False, blank=False)
personnel_code = models.PositiveIntegerField(null=True, blank=True)
eligible_leave = models.FloatField(default=0, blank=False, null=False)
sick_leave_per_month = models.FloatField(default=0, null=False, blank=False)
rfid_card_code = models.CharField(max_length=256, blank=False, null=False)
I want the employer to be authenticated by email and the employee by national code (username filed). How?
you need a custom authentication backend. let's name it backends.py
from django.contrib.auth.backends import ModelBackend
class EmployeeAuthentication(ModelBackend):
"""
Employee Backend
Allows a user to sign in using national_id and password.
"""
def authenticate(self, request, **kwargs):
national_id = kwargs.get('username')
password = kwargs.get('password')
try:
employee = Employee.objects.get(national_id=national_id)
if employee.user.check_password(password) is True:
return employee.user
except Employee.DoesNotExist:
pass
class EmployerAuthentication(ModelBackend):
"""
Employer Backend
Allows a user to sign in using email and password.
"""
def authenticate(self, request, **kwargs):
email = kwargs.get('username')
password = kwargs.get('password')
try:
employer = Employer.objects.get(email=email)
if employer.user.check_password(password) is True:
return employer.user
except Employer.DoesNotExist:
pass
and in settings.py
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
'app.backends.EmployerAuthentication',
'app.backends.EmployeeAuthentication',
]
My models look like this:
class UserDevice(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=False)
device = models.ForeignKey(Device, on_delete=models.PROTECT, null=False)
activation_date = models.DateTimeField(default=timezone.now, null=False)
friendly_name = models.CharField(max_length=20, null=True, blank=True)
is_owner = models.BooleanField(null=False, default=False)
is_admin = models.BooleanField(null=False, default=True)
is_alerts_enabled = models.BooleanField(null=False, default=True)
timeStamp = models.DateTimeField(auto_now = True, null=False)
class UserProfile(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=False)
token = models.TextField(null=False, blank=True)
first_name = models.TextField(null=True, blank=True)
last_name = models.TextField(null=True, blank=True)
timeStamp = models.DateTimeField(auto_now = True, null=False)
I need to get device, user, is_alerts_enabled, is_admin, is_owner from UserDevice and first_name, last_name, token from userProfile. This is what I have so far and it gives me what I need from userdevice but I can't figure out how to add the userprofile stuff.
nonOwners = UserDevice.objects.filter(device=device, is_owner=False)
if nonOwners is None:
return errormsg('non nonOwners found for this device')
nonOwnersArray=[]
for nonOwner in nonOwners:
nonOwner_data = model_to_dict(nonOwner,
fieldlist=(
'device.serial',
'user.email',
'is_alerts_enabled',
'is_admin',
'is_owner',
),
rename={
'device.serial': 'serial',
'user.email': 'email'})
nonOwnersArray.append(nonOwner_data)
Any help would be greatly appreciated. Thanks!
The best way to get a dictionary of values is to use values().
UserDevice.objects.filter(device=device, is_owner=False).values('device', 'user', 'is_alerts_enabled', 'is_admin', 'is_owner')
The above line will give you the relevant fields of the UserDevice model as dictionary values.
If you add a foreign key to UserDevice (here I have changed the user field):
class UserDevice(models.Model):
user = models.ForeignKey(UserProfile, on_delete=models.PROTECT, null=False)
device = models.ForeignKey(Device, on_delete=models.PROTECT, null=False)
activation_date = models.DateTimeField(default=timezone.now, null=False)
friendly_name = models.CharField(max_length=20, null=True, blank=True)
is_owner = models.BooleanField(null=False, default=False)
is_admin = models.BooleanField(null=False, default=True)
is_alerts_enabled = models.BooleanField(null=False, default=True)
timeStamp = models.DateTimeField(auto_now = True, null=False)
You may do this:
UserDevice.objects.select_related('user').filter(device=device, is_owner=False).values('device', 'user', 'is_alerts_enabled', 'is_admin', 'is_owner', 'user__first_name', 'user__last_name', 'user__token')
I have used select_related() to avoid hitting the database unnecessarily.