Registration user with multiple usernames - Django REST - python

I'm trying to implement a user registration and authentication using django rest framework and I'm not sure how to implement it.
The thing is that I want a user to have multiple usernames/nicknames so that's why I have a little bit troubles.
The current models I have:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=50,
unique=True,
error_messages={
'unique': _("Email already exists."),
},
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
gender = models.IntegerField(default=GENDER_MALE, choices=GENDER_CHOICES)
date_of_birth = UnixDateTimeField(null=True, blank=True, )
ip = models.GenericIPAddressField(null=True)
USERNAME_FIELD = 'email'
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
class UserNicknames(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
username = models.CharField(max_length=10,
null=False,
unique=True,
validators=[username_validator],
error_messages={
'unique': _("A user with that username already exists."),
},
)
is_current = models.BooleanField(default=False)
As you can see I have the User model just like the django one but without the username and UserNicknames which contains the user nicknames (the UserNicknames.user field is the foreign key to the User.id field).
The question is what is right way to implement the registration serializer? Should I get all the fields in User and UserNicknames and then do the logic or there is some smarter way to do it?

Related

create django user who can not login

I want to create a user whom I'm using as a ForeignKey and i don't want those users can login to system. I have no idea how to go on. (about setting set_unusable_password() or None, and how to perform it):
my accounts.py file is as
class User(AbstractBaseUser):
GENDER = (("MALE", "Male"), ("FEMALE", "Female"))
user_type = models.CharField(max_length=50, choices=Types.choices, default=Types.PATIENT)
full_name = models.CharField(max_length=255, blank=True, null=True)
phone = models.CharField(max_length=255, unique=True)
email = models.CharField(max_length=255, blank=True, null=True, unique=True)
active = models.BooleanField(default=False)
gender = models.CharField(max_length=15, choices=GENDER)
admin = models.BooleanField(default=False)
staff = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
USERNAME_FIELD = "phone" # username
REQUIRED_FIELDS = []
objects = UserManager()
thanks in advance guys. <3
you can use the is_active field of the user record
is_active Boolean. Designates whether this user account should be
considered active. We recommend that you set this flag to False
instead of deleting accounts; that way, if your applications have any
foreign keys to users, the foreign keys won’t break.
In View you should also check whether the user is active or not.
For Eg:
def user_login(request):
if request.method == "POST":
username = request.POST.get("username")
password = request.POST.get("password")
user = authenticate(username = username,password = password)
if user is not None and user.active:
login(request,user)
As you have overide your user model and changed active field from is_active.If active field is False then it will not allow the user to log in if the user is active it will allow user to log in.

Django Extend AbstractUser and use email Field as default in other field

I'm using Django 1.9.2 with python 2.7.3, rest framework and allauth. I'm extending from django.contrib.auth.models.AbstractUser and I want to get the email field from AbstractUser and use it as default in other field:
from django.contrib.auth.models import AbstractUser
class MyUser(AbstractUser):
def get_email(self):
return self.email
email_from_work = models.EmailField(default=get_email())
But when I use this code, I get the following error:
File "./behnowapp/models.py", line 48, in MyUser
email_from_work = models.EmailField(default=get_email())
TypeError: get_email() takes exactly 1 argument (0 given)
What is the way for get the email attribute?
Thanks to RA123 for the orientation, I have also overwritten the save method of MyUser and instead of implementing my own UserManager, I have implemented the default and I have added the necessary fields:
class MyUser(AbstractBaseUser, PermissionsMixin):
def save(self, *args, **kwargs):
if not self.email_from_work:
self.email_from_work = self.get_email()
super(MyUser, self).save(*args, **kwargs)
def get_email(self):
return self.email
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
username = models.CharField(
_('username'),
max_length=30,
unique=True,
help_text=_('Required. 30 characters or fewer. Letters, digits and #/./+/-/_ only.'),
validators=[
validators.RegexValidator(
r'^[\w.#+-]+$',
_('Enter a valid username. This value may contain only '
'letters, numbers ' 'and #/./+/-/_ characters.')
),
],
error_messages={
'unique': _("A user with that username already exists."),
},
)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('email address'), blank=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_('Designates whether the user can log into this admin site.'),
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
date_joined = models.DateTimeField(_('date joined'), default=now)
email_from_work = models.EmailField(max_length=255, unique=True)
You cannot extend AbstractUser for this purpose. Extend AbstractBaseUser for this. Inherit PermissionsMixin, if you want to use those features. And also make a custom manager extending BaseUserManager.
Example -
class MyUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = [] # Fields necessary for making a user
def get_email(self):
return self.email

Django - ModelForm removing not included values when updating

I'm integrating ModelForm with Django's restless to make an API for my server. By now, I'm working on a update operation on a User.
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_("email address"), unique=True)
username = models.CharField(_("username"), max_length=30, unique=True)
first_name = models.CharField(verbose_name=_("First name"), max_length=100, blank=True)
last_name = models.CharField(verbose_name=_("Last name"), max_length=100, blank=True)
description = models.TextField(verbose_name=_("Description"), blank=True)
phone = models.CharField(verbose_name=_("Phone"), max_length=30, blank=True)
last_location = models.PointField(verbose_name=_("Last location"), geography=True, null=True, blank=True)
other fields...
Here's my ModelForm for the User class:
class ProfileForm(ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'description', 'phone', 'last_location', 'lang')
And here's the call I make to update the user from the restless Resource update function:
form = ProfileForm(self.data, instance=user)
if form.is_valid():
user = form.save()
where self.data is a dictionary including the values received on the call.
{dict} {u'lang': u'es', u'phone': u'293923293', u'first_name': u'Name'}
My problem comes when updating a User. The other fields not included in self.data dictionary are setting their values to ''.
Any ideas?

Django: User information split between "User" and "Person" models

Whenever I create a new account, the information I enter "first_name", "last_name", "username", "age", "city", "state", "email" gets split between the built-in User model and the Person model I created. I can see this happening on the admin site, when I click on a user I just created.
Person model:
class Person(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
username = models.CharField(max_length=200, null=True)
first_name = models.CharField(max_length=200, null=True)
last_name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200, null=True)
city = models.CharField(max_length=200, null=True)
state = models.CharField(max_length=200, null=True)
age = models.CharField(max_length=50, null=True)
View for creating an account:
def create_account(request):
if request.method == 'POST':
new_user = User(username = request.POST["username"],
email=request.POST["email"],
first_name=request.POST["first_name"],
last_name=request.POST["last_name"])
new_user.set_password(request.POST["password"])
new_user.save()
Person.objects.create(user=new_user,
age=str(request.POST.get("age")),
city=str(request.POST.get("city")),
state=str(request.POST.get("state")))
new_user.is_active = True
new_user.save()
return redirect('../')
else:
return render(request, 'polls/create_account.html')
I know the problem is in this model and view, I just can't conceptualize how to put all of the information I submit into the Person model (since the User model only has "first_name", "last_name", "email" attributes).
Since your Person model has a one-to-one with the User, you don't need to store username, first_name, and last_name fields on it. Just leave them on the User model and access them through the relation, you are after all using a relational database.

Django error "add a non-nullable field"

i am getting error django model like this when i try to makemigrations:
You are trying to add a non-nullable field 'person' to owner without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows)
2) Quit, and let me add a default in models.py
i use django 1.8 and this is my model:
class Person(models.Model):
user = models.OneToOneField(User)
alphanumeric = RegexValidator(r'^[0-9a-zA-Z]*$', message='hanya yang mengandung karakter alphanumeric')
email = models.EmailField(verbose_name='email address', unique=True, max_length=244)
username = models.CharField(unique=True, max_length=20, validators=[alphanumeric])
first_name = models.CharField(max_length=30, null=True, blank=True)
last_name = models.CharField(max_length=30, null=True, blank=True)
date_of_birth = models.DateTimeField()
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
def get_full_name(self):
fullname = self.first_name+" "+self.last_name
return self.fullname
def get_short_name(self):
return self.username
def list_operator(self):
return self.operators.all()
def __str__(self):
return self.email
class Operator(models.Model):
person = models.ForeignKey(Person, related_name="operators", null=True)
alphanumeric = RegexValidator(r'^[0-9a-zA-Z]*$', message='hanya yang mengandung karakter alphanumeric')
email = models.EmailField(verbose_name='email address', unique=True, max_length=244)
username = models.CharField(unique=True, max_length=20, validators=[alphanumeric])
first_name = models.CharField(max_length=30, null=True, blank=True)
last_name = models.CharField(max_length=30, null=True, blank=True)
date_of_birth = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.username;
i want to know where my code is wrong.
can you help me solved this problem?
Your code isn't wrong. Just follow the instructions provided by the message...
The person field within your Operator model can't be null (because null=True isn't set). You must already have Operators in your database, so Django doesn't know what to do with those.
You need to either: (a) provide a default value in your model, (b) provide a default during the migration process, or (c) enable null values for that field.

Categories