[Django 1.5.1]
I've set up django-profiles and django-registration for my small site in a way that involves a 'custom' registration backend such that during registration, a new user fills out their username, password, and profile fields in one go. But I'm now trying to allow users to log in with Facebook and trying to use django-facebook. As far as I understand, logging in through django-facebook's Facebook login will authenticate someone, but that won't create a user object nor a profile object.
So the idea I had in mind would be to add an extra profile field which holds a user's potential Facebook ID(which I believe is unique) if they want to use Facebook. Then force a check on every template if the user has a profile or not, and if not, to direct them to the 'create profile' page. Then whenever a user logs in through the Facebook login, it'll somehow link their session with the corresponding profile object which matches the Facebook ID (and consequently the user object corresponding to the profile object). I think I'd have to apply a filter and then create a 'signal', but I'm not too sure how to do that.
This sounds very convoluted though. How might I be able to get this accomplished the right way?
Here's how I suggest you do things. Do away with django-facebook and look into django-allauth. It will handle accounts (registration, logic, connecting social accounts).
Also, django-profiles has many issues with 1.5+ for me and I don't bother with it and instead create my own profiles app and UserProfile model with any additional fields that wouldn't be handled by django-allauth.
An example from one of my implementations
class UserProfile(models.Model):
user = models.OneToOneField(User)
default_address = models.OneToOneField(Address, blank=True, null=True)
default_tshirt_size = models.CharField(blank=True, null=True, choices=constants.tshirt_sizes, max_length=50)
default_shoe_size = models.CharField(blank=True, null=True, choices=constants.shoe_sizes, max_length=50)
Your user profile model should be pointing to the same User model allauth is using.
from allauth.utils import get_user_model
User = get_user_model()
Here's a neat method I use to create the User's profile automatically if it hasn't been already.
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
Then just create a sign-up form class with a save() method that takes user as an argument. Link to this class in your settings file.
ACCOUNT_SIGNUP_FORM_CLASS = 'yourproject.yourapp.forms.SignupForm'
See this post on for a somewhat relevant example, except of course with your implementation you'll probably want to get the UserProfile based on the user.id at that point, and save the additional values to the profile instance.
How to customize user profile when using django-allauth
Related
I am attempting to write an admin action that accesses data from selected users. i.e. user's email. However, I have only been able to access the instance/data of the user that is currently logged in.
For example, to access the emails of selected users, I have tried:
#models.py
class Account(AbstractBaseUser):
email = models.EmailField(max_length=60, unique=True)
#admin.py
from account.models import Account
for Account in queryset:
author = request.Account.email
#OR
author = Account.objects.get(email=request.email)
print(author)
and both of these will fill "author" with the email address of the admin that is trying to pull the data.
Does anyone know how I could pull data from selected accounts with an admin action?
I was really overcomplicating it. Ironically enough, I found the answer on this site called simpleisbetterthatcomplex. The proper format was
for Account in queryset:
print(Account.email)
Here is what I am trying to accomplish:
- Have admins login to the admin page using the default way (username and password).
- Have users register/login to my web app using a custom User Model which uses email instead of password. They can also have other data associated that I don't need for my admins.
- Separate the admin accounts and user accounts into different tables.
I checked how to create a Custom User class by extending AbstracBaseUser, but the result I got is that my admins also became the new user type. So can I have the Custom User model be used for my app users while keeping the default admin system untouched? Or what is a good alternative to my design?
The recommended Django practice is to create a OneToOne field pointing to the User, rather than extending the User object - this way you build on top of Django's User by decorating only the needed new model properties (for example):
class Profile(models.Model):
user = models.OneToOneField(User,parent_link=True,blank=True,null=True)
profile_image_path = models.CharField(max_length=250,blank=True, null=True)
phone = models.CharField(max_length=250,blank=True, null=True)
address = models.ForeignKey(Address,blank=True,null=True)
is_admin = models.NullBooleanField(default=False,blank=True,null=True)
class Meta:
verbose_name = 'Profile'
verbose_name_plural = 'Profiles'
After couple more hours of digging, I think it is best to keep a single User model and use permissions and roles for regulations.
There are ways that can make multiple different user model authentications work, such as describe in here: How to have 2 different admin sites in a Django project? But I decided it wasn't worth it for my purposes.
When I extend the Django User using a OneToOneField to create a Manager, the form to create a Manager in Django Admin only has fields for username and password.
class Manager(models.Model):
"""
Users who need to login to manage the listing of a Outlet
are represented by this model.
"""
manager = models.OneToOneField(User)
internal_notes = models.TextField(blank=True)
def __unicode__(self):
return self.manager.username
What is the right way to add the other built-in User fields like first_name etc to my Manager model?
It's not clear what you are asking here. The form to create a User (not a Manager) displays only three fields at first, to allow you to set the password, but then continues on to a second form where you can set other fields including first name.
Your Manager class doesn't need to define those fields, since they are attributes of the User class which you access via the one-to-one relation.
I have created a custom User SignUp Class.
class SignUp(models.Model):
userId = models.CharField(max_length=8, blank=False, unique=True)
Name = models.CharField(max_length=200)
VehicleNumber= models.CharField(max_length=12)
ContactNum = models.IntegerField(default=0)
def __unicode__(self):
return smart_unicode(self.Name)
I have used this to create a Sign up form. Now, I am not getting a way for creating user login. Note: I can't use django in-built users because they don't have a field for images.
You can extend the built-in django user, by adding OneToOneField.
YourCustomUser(models.Model):
user = models.OneToOneField(User,related_name='profile')
image = models.ImageField()
//put here your others attributes
If you have YourCustomUser instance and want to access to User built-in instance
your_custom_instance.user
If you have User built-in instance and want to retrieve e.i the image
user.profile.image
You can use and extend the built-in model User. The shortest path is
from django.contrib.auth.models import User
from django.db import models
class UserWithPhoto(User):
image = models.ImageField()
but is better practice to use User Profiles, you can read about it in: User authentication in Django
You can read about this in Django user profile and here Extending the User model with custom fields in Django.
Why is better user profile over extending the User model directly?
If you extend the User model you will have the changes applied to all you users. Think about this, you could have Administrators, Developers, Reviwers, even Guests, all of them might have some field that others don't, so a different profile for each one is the better solution than subclassing User for each one, or even worst create a single class with all fields you need for all kinds of users (only think about it hurts ).
So, I'm trying to build up a simple site with a MongoDB database and Django (using MongoEngine), but I am stuck trying to understand how the user profiles work. I can save the mongo_auth.MongoUser document to the database just fine, but when it comes down to actually saving the profile, I'm not doing the right thing. Here is the User Profile model/document I am trying to setup with the MongoUser:
from mongoengine.django.auth import User
from mongoengine import *
[...]
class UserProfile(Document):
user = EmbeddedDocumentField('User')
telephone = models.CharField(max_length=30,null=True,blank=True)
address = models.CharField(max_length=100, null=True, blank=True)
birthdate = models.DateField(null=True, blank=True)
def create_user_profile(sender, instance, created, **kwargs):
if created:
profile, created = UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_user_profile, sender=User)
In Django with relational databases, the UserProfile was a models.Model and the user field was a OneToOne relationship, but I don't know how to map that with the MongoUser, so I guessed the following lines:
class UserProfile(Document):
user = EmbeddedDocumentField('User')
But, apparently, it's not right since Django can't load the profile:
Unable to load the profile model, check AUTH_PROFILE_MODULE in your project settings
I think my settings.py is configured correctly since I can save a MongoUser just fine (without a profile), and the following line tells Django where to find the UserProfile:
AUTH_PROFILE_MODULE = 'comptes.UserProfile'
I am still new to Django and MongoDB, so all help will be greatly appreciated.
Thanks!
You must use mongoengine.fields.ReferenceField. Something like this
class UserProfile(Document):
user = ReferenceField('User')