I have a project where I need to extend django's User. The way I did this initially (without Mezzanine) was to subclass Model into a custom Profile which had a one-to-one Field to django's User. Aditionally, to guarantee that each user always has a Profile, I created in my app a receiver that would listen to the user_registered signal. Whenever it was triggered I would just do inside the receiver:
user = kwargs.get('user')
profile = Profile(user=user)
profile.save()
Now with Mezzanine a settings exist called AUTH_PROFILE_MODULE which I just set equal to 'myapp.Profile' and Mezzanine does the Profile creation for me. There are two issues though:
a) On my webapp, every time I access my profile page, I'm getting this:
myapp/venv/local/lib/python2.7/site-packages/mezzanine/accounts/templatetags/accounts_tags.py:70: DeprecationWarning: The use of AUTH_PROFILE_MODULE to define user profiles has been deprecated.
profile = user.get_profile()
Indeed, AUTH_PROFILE_MODULE used to exist in django but was deprecated. What should I do? Do I ignore the warning since it's Mezzanine, not django, who's using AUTH_PROFILE_MODULE? Or does Mezzanine have a different way to handle profiles now?
b) On my receiver which I had without Mezzanine, I did more things. For example, I initiated Profile vars depending on some environment vars. How can I still do those custom things with Mezzanine? My old receiver isn't working anymore.
Thanks for any help
This question is a bit old, but I think you can safely ignore the warning.
You should be able to accomplish the extra configuration by connecting to the pre or post save signal for the profile model.
Related
I am trying to authenticate my django application written in python with okta IDP. I have almost configured everything at SP side and IDP side too. Now I need to pass a custom variable from IDP which assert SP that user is a publisher,editor or admin and further save this to the django format database (in auth_user_groups table). Anyone have tried doing this, or anyone has idea about this?
I am able to get the custom variable values by attributes mappings from IDP. But this allows me to save the custom attributes only on the user table. please let me know if i have not made myself clear here about my question.
Once again I have a privilege to answer my own question. So hear is the solution.
Django has a user profile module which is to be turned on by giving the module location in the settings.py
i.e -
"AUTH_PROFILE_MODULE = appTitle.UserProfile"
The UserProfile needs to be specified in modules.py specifying the required structure of user profile u need for your app.
Now doing sync -db django creates the Database table for your user profile and further on the same user profile pysaml adds the value (CustomAttribute) which come on the saml Assertion.
more explanations on this can be found on django documentations too.
If any one still faces any issue please let me know.
I have configured OTP with my app. And after putting otp_required decorator on desired method i am redirecting to /account/login.
This is the default login page that comes with two_factor auth. After providing correct username(email) and password it returns an error.
IMPORTANT:
How i can check i have configured custom user models properly. what are the ways to test it out or where i am going wrong with the configurations.
i have followed this documentation
Please let me know if you required any thing further. Thanks!
This might help
To check you have configured custom user properly you can do the following.
Try to run django's create super user command to check either it is entering in desired table or not(python manage.py createsuperuser)
Try to check if you don't have any custom password hashing techniques for your custom user.
Saver approach is to create your own authentication backend. See the docs
AUTH_USER_MODEL = 'customauth.MyUser' , this is the configuration needed for the custom user model.
However if you need to refer User model in your apps after configuring the custom user model, you have to user get_user_model function. All third party apps you used also needs to follow this.
However you should reference the User model with the AUTH_USER_MODEL setting in code that is executed at import time. get_user_model() only works once Django has imported all models.
About the error you are facing , can you provide the stack trace of the error ?
By default from project directory by running manage.py createsuperuser command I am able to create a superuser, but the .is_superuser flag is the default django flag to differ superuser or other user.
I don't want to use that because i am using that flag throughout the application to show settings menu. Instead, I added a field in my userprofile models, the field is .is_primary_user.
Is there any way to control that, so that if I run createsuperuser comment, it should update the .is_primary_user field by "1" in userprofile model?
Yes there is, you have to catch the signal of the post_save of the User model, and if the .is_superuser is changed, you also change the .is_primary_user.
Has Brian Neal pointed out, you should not use the .is_superuser flag in your application. It is meant to be used along with Django permission system (a superuser has permissions for everything) and/or Django admin.
EDIT: I haven't tested, but it should be something like this:
from django.db.models.signals import pre_save
from django.contrib.auth import User
# method for updating
def update_primary_user(sender, instance, **kwargs):
if instance.pk:
return
if instance.is_superuser and not instance.userprofile.is_primary_user:
instance.userprofile.is_primary_user = True
instance.userprofile.save()
# register the signal
pre_save.connect(update_primary_user, sender=User)
There are two options as I see it. One is on the post save signals for profile and user. The other is to override the profile save method. The later will only handle new users.
The post save signal for either the user model or the profile model can be used for updating the profile models is_primary_user. Then not only when you run the createsuperuser program can you update the profile accordingly, but if you give an existing user superuser rights, it will also update that users profile. The problem with using the user model signal is that the profile may not yet be created. You probably would need to catch signals for both models. One for if a user is updated (user model), and the other (profile model) for if the user is being created.
Another option is to override the profile save method. You could check the user.is_superuser that it is linked to and then update the is_primary_user field accordingly.
On the other hand, you maybe wanting to do this for only the first superuser which is created in which case you would first need to check if any superusers previously existed.
I agree with two other posters that it would be best not to use the is_superuser flag in this manner.
I don't like models.User, but I like Admin view, and I will keep admin view in my application.
How to overwirte models.User ?
Make it just look like following:
from django.contrib.auth.models import User
class ShugeUser(User)
username = EmailField(uniqute=True, verbose_name='EMail as your
username', ...)
email = CharField(verbose_name='Nickname, ...)
User = ShugeUser
That isn't possible right now. If all you want is to use the email address as the username, you could write a custom auth backend that checks if the email/password combination is correct instead of the username/password combination (here's an example from djangosnippets.org).
If you want more, you'll have to hack up Django pretty badly, or wait until Django better supports subclassing of the User model (according to this conversation on the django-users mailing list, it could happen as soon as Django 1.2, but don't count on it).
The answer above is good and we use it on several sites successfully. I want to also point out though that many times people want to change the User model they are adding more information fields. This can be accommodated with the built in user profile support in the the contrib admin module.
You access the profile by utilizing the get_profile() method of a User object.
Related documentation is available here.
I'm wondering what the common project/application structure is when the user model extended/sub-classed and this Resulting User model is shared and used across multiple apps.
I'd like to reference the same user model in multiple apps.
I haven't built the login interface yet, so I'm not sure how it should fit together.
The following comes to mind:
project.loginapp.app1
project.loginapp.app2
Is there a common pattern for this situation?
Would login best be handled by a 'login app'?
Similar to this question but more specific.
django application configuration
UPDATE
Clarified my use-case above.
I'd like to add fields (extend or subclass?) to the existing auth user model. And then reference that model in multiple apps.
Why are you extending User? Please clarify.
If you're adding more information about the users, you don't need to roll your own user and auth system. Django's version of that is quite solid. The user management is located in django.contrib.auth.
If you need to customize the information stored with users, first define a model such as
class Profile(models.Model):
...
user = models.ForeignKey("django.contrib.auth.models.User", unique=True)
and then set
AUTH_PROFILE_MODULE = "appname.profile"
in your settings.py
The advantage of setting this allows you to use code like this in your views:
def my_view(request):
profile = request.user.get_profile()
etc...
If you're trying to provide more ways for users to authenticate, you can add an auth backend. Extend or re-implement django.contrib.auth.backends.ModelBackend and set it as
your AUTHENTICATION_BACKENDS in settings.py.
If you want to make use of a different permissions or groups concept than is provided by django, there's nothing that will stop you. Django makes use of those two concepts only in django.contrib.admin (That I know of), and you are free to use some other concept for those topics as you see fit.
You should check first if the contrib.auth module satisfies your needs, so you don't have to reinvent the wheel:
http://docs.djangoproject.com/en/dev/topics/auth/#topics-auth
edit:
Check this snippet that creates a UserProfile after the creation of a new User.
def create_user_profile_handler(sender, instance, created, **kwargs):
if not created: return
user_profile = UserProfile.objects.create(user=instance)
user_profile.save()
post_save.connect(create_user_profile_handler, sender=User)
i think the 'project/app' names are badly chosen. it's more like 'site/module'. an app can be very useful without having views, for example.
check the 2008 DjangoCon talks on YouTube, especially the one about reusable apps, it will make you think totally different about how to structure your project.