Django custom user model and registration - django

I have a Django application where I enabled login and registration with Tivix's django-rest-auth (https://github.com/Tivix/django-rest-auth).
Now,
I want to have a custom user model with few additional fields
I want to be able to enable registration along with these additional fields.
Login would be done with email instead of username
What are the steps to achieve this? I went through answers, however I was confused with few things:
The role of serializers here and custom user signUp form and whether I should have a signUp view as well?
Custom user model from AbstractBaseUser or simply Userof django.contrib.auth.models
I already tried to implement something and ran into an issue (django-rest-auth custom registration fails to save extra fields), so wanted to ask for a correct approach.

Related

Django: all auth create account with email - unique constraint failed. Display message instead of giving an error

I am using djnago all-auth to create custom user accounts. When creating an account with email and password, if account with a email already exits it gives an error (UNIQUE constraint failed: account_emailaddress.email) but I would like to display message that an account with this email already exists instead of throwing an error. What is the best way to handle this? In general I would use AJAX to verify and display message for my own views but I do not know how to deal here with django all-auth package.
I'll suggest that you should override the signup/login form in order to manage this error. Have you checked the documentation? https://django-allauth.readthedocs.io/en/latest/forms.html
I think this answer is related to your question.
A relatively similar approach is given in this answer:
Create your custom view that inherits SignupView and overrides the form class
Create a custom form that inherits from SignupForm and overrides the email validation message
In your own urls.py add the following after include('allauth.urls') to override the account_signup url
Since djangoallauth take care of unique constrain you don't have to add unique=True to your field if user try to login with any social media account with email id already present in your database it djangoallauth will simple ignore and will not set email id in your user model. :)
I am handling my unique fields i.e Email field manually

Custom Django Authentication

I have an model named Customers(username,password ..etc) and also an model named User(username,password...etc).
I want to create two different APIs with different authentication.
One should authenticate with the User username,password
and the second should authenticate using the Customers username,password.
Any idea on how can I do this?
Thank you!
I suggest the following options:
1.
I am assuming User model is the "real" user of your app. If this is true use the django's default User model class. It will work out of the box.
For the Customer model, make it inherit from AbstractBaseUser, this will give you password functionality out of the box and you can add other fields as per your need.
Now you can create 2 different urls for login. 1 url for user which checks in the User model and the other for the customer model. This avoids any confusion for everyone.
If you prefer a single url, you have to mention the model class along with username and password to know in which table to verify them.
2.
Create two profile models: UserProfile and CustomerProfile
Each will have a one to one relationship with the django's default User model.
Basically a User can have the profile of a "real" user or of a customer.
In this case when you are creating any User you have check if you want to attach a UserProfile or a CustomerProfile.
In this case it makes sense to just use a single login url. From the user's login information you can first fetch the user from the User table and then check if it is a customer or not by running a query in the CustomerProfile table.
I recommend you to use the django.contrib.auth.user class for your classical authentication. You can either inherit from that class or add a OneToOne relation to your own model as follows
from django.contrib.auth.models import User
class YourUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
For the rest of your question you should add some more details and even some pieces of your code.

How to apply DRY to Django Models, forms

I'm working on a website and simultaneously on a mobile app.
For the website I've created a Django Form for the User model which override the clean and valid_ methods to provide custom validation.
For the mobile app I'm doing a REST API which exposes and endpoint to create a new user using Tastypie for this.
My doubt is where and how should I define the custom validation for the User model applying the DRY principle.
I can create a UserForm from the data provided by the user in the mobile app, then use the method is_valid() for validating the data, but the form contains a password_confirm field which is also validated and in the app this field doesn't exist.
Should I create a UserForm specific for the mobile app? Should I move these validations to the model class?
The simplest way is probably to subclass the form. Create a LoginForm that does not have the password2 field, and use that one for the mobile login API. Then make a subclass called WebLoginForm and add a password2 field, as well as a clean_password2() method that includes the validation logic. That way, you won't even need to override any of your other clean() code.
An even easier--though hackish--solution would be to have the mobile app submit the password the user wrote both as "password1" and "password2" when it makes the API call.

How do I add custom fields to a User when using django-social-auth

I need to add a BooleanField and a ManyToManyField to my users. I'm using django-social-auth. It seems I could use 'CustomUser'. I guess that's what it's for, but how do I take it into use?
I would need to know:
where to define these new fields
How to add them to the new user when the user is created (ie logs in)
How the query the fields afterwards (ie User.myBooleanField?)
Thanks!
Create a model called CustomUser or UserProfile, whatever you want, with these fields.
In settings.py add a setting AUTH_PROFILE_MODULE = "account.UserProfile", with what you named your model.
In the signals for social_auth, make sure the user has a profile, and if not create it for them when the user is created.
Now anywhere in the site you can call user.get_profile() and you'll have access to these fields.

Django authentication problem - how can I force active users to setup a profile first?

I've put myself into somewhat of a pickle. I use django-registration often, and it seems to work for most situations. However, I want to require users to build their profile (eg: demographic information) before they can visit any of the other pages.
This is how I desire the current setup to run:
visitor fills out registration form --(submit)--->
user email verification --(link creates active user)--->
--(redirected to profile view)--->
user fills out profile form --(submit)-->
user can now access the rest of the website
Is there a recommended way to do this?
One of the ways of doing it would be to use your own #profile_required decorator rather than the django's built in login_required on all your views.
#login_required
def profile_required(func,request,*args,**kwargs):
has_profile = request.user.profile_set.count()
if not has_profile:
return redirect('create_profile')
return func(request,*args,**kwargs)
Then on each view you want to have a user with profile visit, just:
#profile_required
def my_awesome_view(request):
...