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)
# …
Related
I'm Trying to save an Item with the user's officeid but it's throwing me an error
ValueError: Cannot assign "<CustomUser: admin#gmail.com>": "ClearanceItem.office" must be a "Office" instance.
My customuser has id of 1
while the email is admin#gmail.com
lastly the officeid = 'OSA'
this is my models.py
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
userid = models.CharField(null=True, max_length=9)
officeid = models.ForeignKey('Office', models.DO_NOTHING, db_column='officeid', blank=True, null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
class ClearanceItem(models.Model):
cl_itemid = models.CharField(primary_key=True, max_length=20, default=get_default_id)
studid = models.CharField(max_length=9, blank=True, null=True)
office = models.ForeignKey('Office', models.DO_NOTHING, blank=True, null=True)
sem = models.CharField(max_length=1, blank=True, null=True)
sy = models.CharField(max_length=9, blank=True, null=True)
remarks = models.TextField(blank=True, null=True)
resolution = models.TextField(blank=True, null=True)
resolve = models.BooleanField(default='False', blank=True, null=True)
resolve_date = models.DateField(blank=True, null=True)
resolve_by = models.CharField(max_length=8, blank=True, null=True)
recorded_by = models.CharField(max_length=8, blank=True, null=True)
record_date = models.DateField(auto_now_add = True, blank=True, null=True)
class Meta:
managed = False
db_table = 'clearance_item'
class Office(models.Model):
office_id = models.CharField(primary_key=True, max_length=50)
office_name = models.CharField(max_length=200)
office_head = models.CharField(max_length=8, blank=True, null=True)
designation = models.TextField(blank=True, null=True)
office_parent = models.CharField(max_length=50, blank=True, null=True)
deptlogo = models.TextField(blank=True, null=True)
class Meta:
managed = False
db_table = 'office'
this is my views.py
class APIClerkView(generics.ListCreateAPIView):
permission_classes = [IsAuthenticated]
serializer_class = ClearanceItemSerialize
def perform_create(self, serializer):
serializer.save(office=CustomUser.objects.get(officeid=self.request.user.officeid),
recorded_by=self.request.user.userid)
Based on my previous encounter of this problem i think, it's not throwing an actual officeid but instead a string
How can I remedy that or Any alternative solution
My goal here is to avoid users type their officeid in a field along with other details.
{
"sem": "1",
"sy": "2022-2023",
"remarks": "TEST",
"resolution": "TEST",
"studid": "2012-5037"
}
you can do this way
class APIClerkView(generics.ListCreateAPIView):
permission_classes = [IsAuthenticated]
serializer_class = ClearanceItemSerializer
def perform_create(self, serializer):
try:
office=CustomUser.objects.get(officeid=self.request.user.officeid)
except CustomUser.DoesNotExist:
raise ValidationError({'error':'User does not exist'}
# you can now do whatever you want with the instance
How do I update my form as the
form.instance.users = request.user
is not working however if I print request.user on terminal it prints the username of the user currently logged in.
Also in this form I want to pick existing data from that user to display in the form to update it.
The save form button return HttpResponse saved successfully but the data is not stored in the database.
models.py
class BasicDetails(models.Model):
GENDERS = (
('M', 'Male'),
('F', 'Female'),
('O', 'Others'),
)
users = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=50, null=True, blank=True)
last_name = models.CharField(max_length=50, blank=True, null=True)
father_name = models.CharField(max_length=50, blank=True, null=True)
mother_name = models.CharField(max_length=50, blank=True, null=True)
date_of_birth = models.DateField(blank=True, null=True)
gender = models.CharField(max_length=1, choices=GENDERS)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.first_name+" "+ self.last_name
class Education(BasicDetails):
current_year = datetime.date.today().year
YEAR_CHOICES = [(r, r) for r in range(2000, datetime.date.today().year+2)]
course_name = models.CharField(max_length=100, blank=True, null=True)
university_board_name = models.CharField(
max_length=200, blank=True, null=True)
passing_year = models.IntegerField(
choices=YEAR_CHOICES, default=current_year, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(default=timezone.now)
forms.py
class BasicDetailsForm(forms.ModelForm):
class Meta:
model = BasicDetails
fields = '__all__'
exclude = ['users']
class EducationForm(forms.ModelForm):
class Meta:
model = Education
fields = '__all__'
exclude = ['users']
views.py
#login_required
def View(request):
education = EducationForm()
education.instance.users = request.user
if request.method =="POST":
print(request.user.id)
education = EducationForm(request.POST,instance=request.user)
if education.is_valid():
education.save(commit=True)
return HttpResponse("Saved Successfully")
else:
education = EducationForm()
return render(request, 'app/view.html',{'education':education})
I have this custom User model-
class User(AbstractUser):
email = models.EmailField(unique=True)
picture = models.ImageField(upload_to='profile_picture', null=True, blank=True)
updated_on = models.DateTimeField(auto_now=True)
date_activated = models.DateTimeField(null=True, blank=True)
username = None
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = UserManager()
def __str__(self):
return self.email
class Meta:
verbose_name = 'User'
and this UserProfile model-
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='userprofile', on_delete=models.PROTECT, primary_key=True)
contact = models.CharField(max_length=20, blank=True, default='')
about_me = models.TextField(null=True, blank=True)
latitude = models.FloatField(validators=[MinValueValidator(-90), MaxValueValidator(90)], null=True, blank=True)
longitude = models.FloatField(validators=[MinValueValidator(-180), MaxValueValidator(180)], null=True, blank=True )
age = models.IntegerField(validators=[MinValueValidator(18), MaxValueValidator(100)], null=True, blank=True )
dob = models.DateField(null=True, blank=True,)
source_of_registration = models.ForeignKey('core.SourceOfRegistration', on_delete=models.PROTECT, null=True,blank=True )
interests = models.ManyToManyField('core.Interest')
languages = models.ManyToManyField('core.SpokenLanguage')
gender = models.ForeignKey('core.Gender', on_delete=models.PROTECT, null=True, blank=True )
country = models.ForeignKey( 'core.Country', on_delete=models.PROTECT, null=True, blank=True )
state = models.ForeignKey('core.State', on_delete=models.PROTECT, null=True, blank=True)
city = models.ForeignKey('core.City', on_delete=models.PROTECT, null=True, blank=True)
zip_code = models.CharField(max_length=12, null=True, blank=True)
is_profile_completed = models.BooleanField(default=False)
profile_completed_on = models.DateTimeField(null=True, blank=True)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'User Profile'
def __str__(self):
return self.user.email
def clean(self):
if self.dob:
age_in_days = (datetime.date.today() - self.dob).days
age_in_years = age_in_days / 365
if age_in_years < 18:
raise ValidationError(gettext_lazy('Age should be more or equal to 18.'))
else:
self.age = age_in_years
This is the UserProfileResource-
class UserProfileResource(resources.ModelResource):
class Meta:
model = UserProfile
import_id_fields = (
'user',
'city',
'state',
'country',
'gender',
'source_of_registration',
)
skip_unchanged = True
report_skipped = False
use_bulk= True
fields = (
'user',
'contact',
'about_me',
'longitude',
'latitude',
'age',
'dob',
'zip_code',
'is_profile_completed',
'created_on',
'updated_on',
'city',
'state',
'country',
'gender',
'source_of_registration',
'profile_completed_on',
)
I want to import User data and UserProfile data from one place, UserProfileModelAdmin, i am totally lost now, anyone can give me a hint, how to approach this problem using django_import_export efficiently.
I had also seen this solution, but it is not working for me-
https://github.com/django-import-export/django-import-export/issues/319
Thanks, any kind of hint would be appreciated.
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',
]
In a form I have a drop down of usernames, this is referenced in the 'taken_by' field. I would like to display first_name and last_name, this is achieved through the __str__ but I can't seem to get it to function, the list of usernames are presented but not the firstname. Suggestions welcome.
from django.contrib.auth.models import User
from django.conf import settings
class Sample(models.Model):
sample_id = models.AutoField(primary_key=True)
area_easting = models.IntegerField(choices = EASTING_CHOICES)
area_northing = models.IntegerField(choices = NORTHING_CHOICES)
context_number = models.IntegerField()
sample_number = models.IntegerField()
material_type = models.CharField(max_length=200, default='', blank=True, null=True, choices = MATERIALS)
weight = models.DecimalField(max_digits=6, decimal_places=2)
description = models.CharField(max_length=500, default='', blank=True, null=True)
recovery_method = models.CharField(max_length=200, default='', blank=True, null=True, choices = RECOVERY_METHODS)
taken_by = models.ForeignKey(settings.AUTH_USER_MODEL, db_column='taken_by', on_delete = models.PROTECT)
comments = models.CharField(max_length=1000, default='', blank=True, null=True)
def __str__(self):
return self.taken_by.first_name
# return str(self.sample_id)
# return str(self.firstname)+ '-' +str(self.lastname)
# return u'%s %s' % (self.first_name, self.last_name)
Form setup as requested
class BotanySampleFilterForm(forms.ModelForm):
class Meta:
model = Sample
fields = (
# 'botany_id',
'sample_id',
'area_easting',
'area_northing',
'context_number',
'sample_number',
'material_type',
'weight',
'description',
'recovery_method',
'taken_by',
'comments'
)