I'm trying to configure django_ldap_auth to populate user profile with their region data from LDAP:
I created a model for the profile:
from django.db import models
from django.contrib.auth.models import User
class profile(models.Model):
user = models.ForeignKey(User, unique=True)
region = models.CharField(max_length=128, null=True, blank=True)
def __unicode__(self):
return '{0} profile'.format(self.user.username)
class Meta:
app_label = 'core'
I configured my settings to map to 'l' LDAP attribute (that's how region is marked in LDAP)
AUTH_PROFILE_MODULE = 'core.profile'
AUTH_LDAP_PROFILE_ATTR_MAP = {"region": "l"}
This may be important, the profile class sits inside app/models/UserProfile.py file and models/init.py has from UserProfile import profile statement.
However, I still get the following message in debug and profile won't populate:
search_s('dc=*****,dc=ru', 2, '(sAMAccountName=******)') returned 1 objects: CN=Болотнов Александр,OU=****,OU=****,DC=***,DC=ru
Populating Django user *****
Django user **** does not have a profile to populate
Is there anything I'm missing? userdata such as first/last name and email populate just fine but region won't.
This means that this particular User object does not have an associated profile object. Django does not automatically create profile objects, nor does django-auth-ldap. Typically, you will install a post_save signal handler on the User model to create profiles.
See https://docs.djangoproject.com/en/1.4/topics/auth/#storing-additional-information-about-users.
Related
I have two classes in models.py
class Account(models.Model):
...
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
accounts = models.ManyToManyField(Account, blank=True)
Now in my views.py I have:
def create_account(request):
account = Account(symbol=request.POST['symbol'])
account.save()
However, when the form that calls the create_function is successfully submitted, my Django debug mode throws the error: 'ManyToManyDescriptor' object has no attribute 'create', and SELECT * FROM the relevant table in my database confirms that no row has been added.
After searching this error online, I can confirm that this probably has to do with the fact that the Profile class is many-to-many associated with the Account class and that I should be creating Account objects differently, however I am not sure how to do it correctly.
Now I have 5 models and I want to retrieve objects filtered by the user created specific object
models.py
for instance this model
class FileCategory(models.Model):
file_type = models.CharField(_('type'), max_length=128)
def __unicode__(self):
return self.file_type
Now I have an objects with file_type equals ABC, ENB, ORJ
and I want to list only the file_types which the request user created only. Is it doable?
Sure I know I can add user attribute OneToOne to user model
I fount to use LogEntry model
from django.contrib.admin.models import LogEntry
file_category = ContentType.objects.get_for_model(FileCategory)
logs = LogEntry.objects.filter(content_type=file_category,
user__username=request.user.username
).values('object_repr')
FileCategory.objects.filter(name__in=logs)
I'm trying to use a custom user model in my Django project. After running migrations, the database table is named accounts_listuser while Django appears to be looking for them in accounts_user. How can I change this so Django looks at the correct table (accounts_user) for the user model instead of accounts_listuser?
In my settings.py:
# Auth user models
AUTH_USER_MODEL = 'accounts.User'
AUTHENTICATION_BACKENDS = (
'accounts.authentication.PersonaAuthenticationBackend'
)
The accounts/models.py file:
class User(models.Model):
email = models.EmailField(primary_key=True)
last_login = models.DateTimeField(default=timezone.now)
REQUIRED_FIELDS = ()
USERNAME_FIELD = 'email'
is_authenticated = True
is_anonymous = False
And the file (accounts/authentication.py) where the query fails:
from django.contrib.auth import get_user_model
User = get_user_model()
# .. user's email retrieved ..
def get_user(self, email):
try:
return User.objects.get(email=email)
except User.DoesNotExist:
return None
The full source code can be found here if it helps.
Not sure what you mean by correct table in this case, but this behavior sounds about right since your model is called user and is declared in an app named accounts.
You can overwrite the auto-generated table name using class Meta attribute db_table: https://docs.djangoproject.com/en/1.10/ref/models/options/#db-table
Also just a note, the django docs recommend that your custom user model inherits from AbstractBaseUser, otherwise you will be responsible for implementing quite a few things on your own. https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#specifying-a-custom-user-model
I'm trying to use social_auth (omab) for the first time and I'm find that there is no working example how to store basic facebook user data. Authentication works and user is created without problem as it's explained in the social_auth docs but I need to store gender and locale also. Both of them belongs to the basic facebook user data so they are in the facebook response all the time.
I'm use Django 1.4, Python2.7 and latest social_auth. So I was try to use SOCIAL_AUTH_USER_MODEL = 'myapp.UserProfile' in settings.py file and model.py is:
#!/usr/bin/python
#-*- coding: UTF-8 -*-
from django.db import models
from django.contrib.auth.models import User
from django.db.models import signals
import datetime
from datetime import timedelta
from django.db.models.signals import post_save
from social_auth.signals import pre_update
from social_auth.backends.facebook import FacebookBackend
class CustomUserManager(models.Manager):
def create_user(self, username, email):
return self.model._default_manager.create(username=username)
class UserProfile(models.Model):
gender = models.CharField(max_length=150, blank=True)
locale = models.CharField(max_length=150, blank=True)
#social_auth requirements
username = models.CharField(max_length=150)
last_login = models.DateTimeField(blank=True)
is_active = models.BooleanField()
objects = CustomUserManager()
class Meta:
verbose_name_plural = 'Profiles'
def __unicode__(self):
return self.username
def get_absolute_url(self):
return '/profiles/%s/' % self.id
def facebook_extra_values(sender, user,response, details, **kwargs):
profile = user.get_profile()
current_user = user
profile, new = UserProfile.objects.get_or_create(user=current_user)
profile.gender = response.get('gender')
profile.locale = response.get('locale')
profile.save()
return True
pre_update.connect(facebook_extra_values, sender=FacebookBackend, weak = False, dispatch_uid = 'facebook_extra_values_user')
In the settings.py I'm define pipeline
SOCIAL_AUTH_PIPELINE = (
'social_auth.backends.pipeline.social.social_auth_user',
#'social_auth.backends.pipeline.associate.associate_by_email',
'social_auth.backends.pipeline.user.create_user',
'social_auth.backends.pipeline.social.associate_user',
'social_auth.backends.pipeline.social.load_extra_data',
'social_auth.backends.pipeline.user.update_user_details',
'social_auth.backends.pipeline.misc.save_status_to_session',
)
but with above I get error AssertionError: ForeignKey(None) is invalid. First parameter to ForeignKey must be either a model, a model name, or the string 'self'
Also I was try to use AUTH_PROFILE_MODULE = 'myapp.UserProfile' instead as I was do before to extend user.model, which works well but don't understand how to populate needed data when UserProfile is created. Does anyone can place working code for this problem?
Thanks
There are a couple of ways to archive it, what fits better to your project is up to you of course, here's a list of available options:
Define this setting FACEBOOK_EXTRA_DATA = ('gender', 'locale'), the values will be available at the UserSocialAuth instance, to get them just do user.social_auth.get(provider='facebook').extra_data['gender'] or ['locale']. This is possible just because the information is available in the basic user data response.
Use a user profile to store this data (check django doc about it). Then just add a pipeline entry that stores the values in your profile instance.
Create a custom user model, SOCIAL_AUTH_USER_MODEL = 'myapp.CustomUser', and again add a custom pipeline entry that stores the values in your user instance.
Number 1 is not the best solution IMO, since a user can have several Facebook accounts connected and it could create a mess. Number 2 is good for Django 1.4 and lower, but it's deprecated starting from Django 1.5, something to take into account. Number 3 is a bit messy IMO.
In my Django project I have a user authentication system. Each user has a userprofile:
# Extending main user profile
class UserProfile(models.Model):
# Required
user = models.OneToOneField(User)
# Added fields to main user model
position = models.CharField(max_length=20, null=True, blank=True)
avatar = models.ImageField(upload_to=upload_path_handler, blank=True, default='images/avatar.png')
class Meta:
app_label = 'auth'
# handler -- Create automatically UserProfile foreign key when
# a new user is registered.
def create_user_profile(sender, instance, created, **kwargs):
if created:
# Creating UserProfile
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
Well, I have a context_processor.py which its main function returns something like this:
return {'USER_MEDIA_URL': settings.USER_MEDIA_URL,
'DEBUG': settings.DEBUG,
'SITE_URL': settings.SITE_URL,
'keys_left': keys_left,
'ownRoom': c,
'userThumbnail': request.user.get_profile().avatar,}
All my templates use "userThumbnail" and "request.user.get_profile().avatar" fails randomly without any kind of explication.
The returned error in template is:
Unable to load the profile model, check AUTH_PROFILE_MODULE in your project settings
Sometimes I get this error and sometimes not. It's very annoying.
Any hint?
It's very annoying.
:)
If you don't need to perform other extra tasks on post_save except of creating a profile, maybe you could use AutoOneToOneField from django-annoying instead?
The method get_profile() does not create the profile, if it does not exist.
(django docs)
AutoOneToOneField does.
It's not really an answer, but it may turn out to be a solution for you.
from annoying.fields import AutoOneToOneField
class UserProfile(models.Model):
user = AutoOneToOneField(User, verbose_name=_(u"user"),
on_delete=models.CASCADE,
related_name="profile")
Then you use it with something like that:
return { 'userThumbnail': request.user.profile.avatar, }
Add the following to your settings.py
AUTH_PROFILE_MODULE = 'appname.UserProfile'
That should solve the issue.