Django user with custom data in multiple apps - django

Customer User models was great but if you want to build a project combining multiple apps, each app can assume it's going to have the user model as part of it's models. My plan is to revert to the standard django User and have a profile in each app.
eg.
app1.models.py
from django.contrib.auth.models import User
Class App1User(models.Model):
user = models.OneToOne(User)
special = models.CharField( some field that relates to the user in this app)
app2.models.py
from django.contrib.auth.models import User
Class App2User(models.Model):
user = models.OneToOne(User)
another = models.CharField( some field that relates to the user in this app)
etc.
Then add code to go and get the relevant profile data when needed, maybe adding some middleware or template context processors. Before I go down this route I wanted to check this is the most Djangoeque solution?

Imho yes, you doing it in the right way.
And you don't need any middleware or context processors to get relevant data for the user. OneToOne field is easily accessible as the attribute of the user instance:
{{ user.app1user.special }}
{{ user.app2user.another }}

Related

Create editable page for user User Account

So my question is what should I look for creating a page which will allow user to add some information after the registration. I took a look at Django Profiles, but it requires lower version of Python (2.7), if I'm not mistaken.
Another thing is I need to create two types of users - I'm thinking of maybe #permission to implement it, but another point is that I want to include something like checkbox while registration, and if user chooses one type of user, he will be allowed to see default account page for this type of user which he should fill up.
I'm running Django 1.10.5 and Python 3.6.0.
Thanks in advance.
If you want to add custom fields to your user object take a look at custom user model django implementation. Then, for updating user object you can just use generic update view, it will look something like this:
from django.contrib.auth import get_user_model
class UserUpdateView(UpdateView):
model = get_user_model()
fields = ['field1', 'field2', 'field3']
template_name = "core/user_edit.html"

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 use anafero to create a referral system in django?

I want to create a two-sided benefit referral system, with different types of referrals in django using the anafero app.
I looked at this article and looked at the documentation for anafero and I cannot make sense of it. Can someone please give an simple example of:
What database changes need to be made, i.e. which models need to
be created and how the user object needs to be changed
Which view needs to be created
How to display the referral url in the template
Anafero is outdated. Instead of it you can use pinax_referrals
Install the package as it described in documentation, add middleware etc, synchronize database.
Depending on what do you use for signing up hack the view. In my case I have reimplemented SignUp view and added following lines inside:
profile = user.userprofile
referral = Referral.create(
user= user,
redirect_to= "/"
)
profile.ref = referral
profile.save()
You see that when User signs up the Refferal object is created and saved into User profile. It means that you have to change the model for UserProfile and add additional field:
Import:
from pinax.referrals.models import Referral
Inside model:
ref = models.OneToOneField(
Referral,
null=True,
on_delete=models.CASCADE,
)
Make migrations, migrate, check in the admin if new fields are added, try to sign up and see whether the new Referral object is created and saved.

django - Extending `auth.models.User` and usering login, logout

If I create a CustomUser model which inherits from django.contrib.auth.models.User, like so:
in models.py
class CustomUser(django.contrib.auth.models.User):
customfield = TextField()
...
Should I still be able to use
django.contrib.auth.{authenticate, login, logout} in the normal way? Do I have to make some additional configuration change? I know these methods only work on User objects, but technically my CustomUser is-a User.
Currently, authenticate(username=u, password=p) is always returning None, even with valid credentials.
Since Django 1.5 (officially but it doesn't worked for me) and "stable" in 1.6 there is a functionality to extend the User model in a clean way.
At first:
-> Take care that you load the User model only via:
from django.contrib.auth import get_user_model
User = get_user_model()
-> Once you have built the database theres no easy way to change the User model. The database relations will break and Django / South isn't able to fix it.
-> third party modules have to be compatible with that new layout and refer in it's models to "get_user_model()", too.
You have to add some Code for the admin to respect your new model:
See: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-the-existing-user-model
To Override the model you need to inherit from AbstractBaseUser:
from django.contrib.auth.models import AbstractBaseUser
class MyUser(AbstractBaseUser):
...
date_of_birth = models.DateField()
height = models.FloatField()
...
REQUIRED_FIELDS = ['date_of_birth', 'height']
AbstractBaseUser provides you all attributes of the default user model. So you don't have to take care of email, username, first_name, last_name, password etc.
More info about overriding the user model: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#django.contrib.auth.models.CustomUser
In your settings link your new model:
AUTH_USER_MODEL = 'customauth.MyUser'
Please read the whole documentation of customizing the user model, there are some interesting hints for overriding the default manager, admin forms etc. Just remember that bigger changes in an existing project can be a big pain.
A short overview:
- Extend models.AbstractUser
- Set AUTH_USER_MODEL in settings.py
All details can be found here: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#specifying-a-custom-user-model

Extending the User model in django

http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/
When it comes to extending the User model, the above article list two methods: the old way (ForeignKey) and the new way (User model with inheritance). But at the same time, this article dates back to Aug 2008.
I am using Django's development version.
Would you recommend Extending the Django User model with inheritance or by using ForeignKey?
I read in a couple of posts that extending django.contrib.auth.models.User is not recommended, so I will not be looking at that.
AFAIK, the cleaner approach - if this can fit in your project architecture - is to have a distinct user profile model, and use the AUTH_PROFILE_MODEL setting to link it up to the Django User model.
See the Django Doc about storing additional information for Users
Dominique Guardiola is right. Use the AUTH_PROFILE_MODEL. James Bennett reiterated this in his 'Django in Depth' talk. http://www.youtube.com/watch?v=t_ziKY1ayCo&feature=related around 1hr:37mins.
Decide on the application where we want to house our user's profile, let's call it BngGangOfFour.
Define a Model class, lets name it UserProfile for clarity, and give it the extra field(s) we desire.
BngGangOfFour/models.py
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User) #notice it must contain a 1 to 1 field with the auth user.
last_ip_address = models.CharField(max_length=20, default="")
Edit settings.py to designate our newly created model as the user profile.
settings.py
....
AUTH_PROFILE_MODULE = 'BngGangOfFour.UserProfile' #not case sensitive.
....
Access the profile directly off the user objects.
BngGangOfFour/views.py
....
def index(request):
if request.user.get_profile().last_ip_address = "127.0.0.1":
print("why hello me!")
return render_to_response('index.html', locals(), context_instance=RequestContext(request))
Sip a cold beer and call it a day.
The only time you can cleanly get away with extending User via inheritance is if you're writing an auth backend which will return an instance of the appropriate model instead.