modeling user settings in django - python

I would like have additional settings tied to each user in my application (beyond, is_staff, is_admin etc etc). Basically I'd like to have different settings to customize their user experience (ie: don't show tooltips, how many rows to display in results tables, other flags for turning things on or off).
Are there best practices for adding these types of settings, or example model to do this without touching the django user object (in the past when i needed a quick user property, i just added it to my django source code, but obviously know that this is a horrible idea).
So when someone sucessfully logs in, I would grab the settings for the user and add them to the session.
I wasn't sure if there was a pretty way, or best practice for doing this.

As already said, use UserProfile. To store many flags in the same field there's django-bitfield.

Either put them in the user profile model, or create another model with a one-to-one to User.

Related

Does Django Admin support an "Are you sure you want to do that" popup when a user is saving a new record?

I have an admin page that allows a user to make "usual" and and some "unusual" changes.
The "unusual" would be setting a field on the model to None. I could check for this in ModelAdmin.save_model but I'd like to check the user is happy with what they're doing. Is there a standard way of notifying the user that they're doing something a bit funky and checking whether or not they definitely want to proceed? Ideally without custom html and redirects.

Best Way To Store User Info separate from User model in django

Say I have a bunch of flags/options related to using my app. Stuff like firstSetupCompleted, tutorialCompleted, userExperienceLevel.
What would be the best way to store these on a per-user basis? The options I've considered so far are
django-constance package
A profile model that's 1-1 with a User model
a JSON field on the user model
What would the best approach be to storing flags/info related to using the site, but not necessarily directly related to the user themselves (thus do not want to store in the User model)
Well I would definitely prefer the second option and go with that. It is because when you do that the linking and reference is easy to maintain and you can get the data of the user with just an extra attribute .

Use Django User-Model or create a own Model?

I'm currently designing a Django based site. For simplicity lets assume that it is a simple community site where users can log in and write messages to other users.
My current choice is wether to use the buildin User-Model or to build something my own. I don't need much from the buildin User: there will be no username (you e-mail address is you username), but you an set an internal Name of your choice which can be used by multiple users (like Facebook). Additionally, I don't need the permission system, since access to others will not be based on groups. So I would end up using only the email, firstname, lastname and password fields from the buildin User and everything else would be placed in a UserProfile.
On the other hand, the buildin User system will come handy on the backend of the site, since there is the chance I will need a group based permission system there.
All in all, it looks to me, that I rather build my one User Model and use the buildin only for access to the admin backend.
Is there anything wrong with my reflections?
Is there anything wrong with my reflections?
Yes.
My current choice is wether to use the buildin User-Model or to build something my own.
There is a third choice.
http://docs.djangoproject.com/en/1.2/topics/auth/#storing-additional-information-about-users
everything else would be placed in a UserProfile
Correct.
build my one User Model and use the buildin only for access to the admin backend
Don't build your own.
Do this:
If you'd like to store additional
information related to your users,
Django provides a method to specify a
site-specific related model -- termed
a "user profile" -- for this purpose.
As the author of django-primate I would like to add some comments. Django-primate which easily lets ju modify the built in User model is meant for just that. You might need just something a little extra, then use django-primate.
But there are problems, although I do not think modifying the django User model per se is a problem at all. One problem is that the "users" are quite different, the admin user and some other user are often not related. This can cause problems when for example an admin is logged in and then wants to login to the site as a "normal user", they do not expect those accounts to be related and do not expect to be logged in automatically as the admin user. This causes headaches for no reason. It also causes a lot of other headaches to implement the recommended related Profile model, you often need to make sure there is a contrib user for every profile and a profile for every contrib user if you for example want to use the authentication decorators. Forms and administration of "users" make this even more cumbersome. In short: usually something will go wrong in this process at some point, it's a curse.
I have mostly abandoned the contrib User model for anything else but for admins. Building another user model is really what you want, but you also want the authenicating part for that user, hence the common use of django contrib User (using it for the wrong reasons). The best solution if you are in a situation like this is to build your own authenication for that custom user model. This is actually quite easy and I cannot recommend this approach enough. I think that the official recommendation is wrong and that there should instead be good tools for authenticating custom user models built into django.
You might want to have a look at the recently created django-primate: https://github.com/aino/django-primate
I once built a custom user model, inheriting from the default one. It works, however, I wouldn't recommend it.
Currently, you have some requirements, but over time they may change. Django's user system is quite straightforward, and using it allows to adapt more easily to some of the most common use cases.
Another aspect to think about, is that there are several applications already available that you can use, and that may require Django's users. Using your own model, may make usage of such modules much more difficult.
On the other hand, hacking the Django's user system in order to comply with your current requirements may be tricky.
Moreover, migrating a 'Custom-User' to a 'Django-User' is always possible, so you are not really closing that door.
Overall, I think it really depends on what you mean with 'user'.
If you mean just a registration, and no real interaction with the core Django features, then I think a separate model is enough, especially because you can migrate at any time, with relatively little effort.
However, if for your application a 'user' maps to something very similar to the what Django is for, then I would use the Django User-Model.

Design ideas for a webapp in Django

I'm working on a user based, social networking type of web application in Django. It's my first one so I would like to make sure I'm using some good practices.
Currently the web app supports two kinds of users. This is represented by two different Groups. When I register a user I assign them to one of these two groups. I also have two apps, one for each type of user. The apps handle whatever things are distinct to a particular type of user. I have another app that handles the actual authentication. This app uses Django's built in User type and assigns them a UserProfile. The two different types of users have their own profiles which extend/inherit from UserProfile.
This works reasonably well, and is fairly reusable since the authentication app can pull the user type from the url and figure out which type of user to create. Since the groups are named conveniently, they can be added to the correct group too.
Is this the best way or are there more preferred, tried and true ways to handle this? It seems like a pretty common enough scenario. I don't want to continue incorrectly reinventing the wheel if I don't have to.
I was thinking of adding another app called, common, or something which would handle things that are common to all users. For example, viewing a users profile page might be something anyone who is logged in might want to do, regardless of what type of user they are.
Thanks!
Easy part first, with 2) you're spot on. That would be the simplest and most effective way of doing that. It makes sense instead of replicating functionality across both applications to have one app that handles things that are common to both user types.
Back to 1)
With both profiles extending from UserProfile, you'd run into the issue of (if you were using get_profile() on a User object - see http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users) that you'd get back just a UserProfile object, not knowing which group the user actually belongs to based on the object received. This is because they both extend UserProfile but UserProfile would not be able to be (I believe) abstract, because you want every User to have a pointer to a UserProfile object which may actually be a UserGroup1 or a UserGroup2 object.
What I would suggest you do is make two seperate Models, that do not extend from the same Model (out of necessity): Group1 and Group2. You would store the information that is common to both profiles in the UserProfile of the User object. Then in the UserProfile you would have a ForeignKey to both a Group1 and a Group2 object:
group1 = models.ForeignKey(Group1, blank=True, null=True)
You would have to do the logic checking yourself, to ensure that only one is ever valid (you could just do this in an overridden save() method or something), but then to grab all of a user's data at once, and also know which group they are on you could do the following:
User.objects.filter(username='blahblah').select_related('profile', 'profile__group1', 'profile__group2')
Only one query to the database would give you all the information you'd need about a user, and you'd also know which group they are in (the one that isn't 'None').
I hope that helps.
P.S. I am assuming in this that groups don't just have unique data to each other, but also unique functionality.

How to change default django User model to fit my needs?

The default Django's User model has some fields, and validation rules, that I don't really need. I want to make registration as simple as possible, i.e. require either email or username, or phone number - all those being unique, hence good as user identifiers.
I also don't like default character set for user name that is validated in Django user model. I'd like to allow any character there - why not?
I used user-profile django application before to add a profile to user - but this time I'd rather make the class mimimal. But I still want to use the User class, as it gives me an easy way to have parts of site restricted only for users logged in.
How do I do it?
Rather than modify the User class directly or do subclassing, you can also just repurpose the existing fields.
For one site I used the "first_name" field as the "publicly displayed name" of a user and stuff a slugified version of that into the "username" field (for use in URLs). I wrote a custom auth backend to allow people to log in using their "public name" or their email address, and I enforce the uniqueness of both of those at registration time. This plays nicely with other reusable apps and doesn't introduce extra tables or queries.
For another site I didn't want usernames at all, just unique emails. In order to satisfy Django's need for a unique username, I just hashed the email address and used that as the username (you have to base64-encode the hash to squeeze it under 30 characters). Custom auth backend to allow login with email.
If backwards-compatibility weren't an issue, there are a lot of improvements I'd love to see made to django.contrib.auth and the User model to make them more flexible. But there's quite a lot you can do inside the current constraints with a little creativity.
I misread the question. Hope this post is helpful to anyone else.
#in models.py
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.ForeignKey(User)
#other fields here
def __str__(self):
return "%s's profile" % self.user
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 settings.py
AUTH_PROFILE_MODULE = 'YOURAPP.UserProfile'
This will create a userprofile each time a user is saved if it is created.
You can then use
user.get_profile().whatever
Here is some more info from the docs
http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
The Django User model is structured very sensibly. You really don't want to allow arbitrary characters in a username, for instance, and there are ways to achieve email address login, without hacking changes to the base model.
To simply store additional information around a user account, Django supports the notion of user profiles. While you don't need to rely on the built in support to handle this, it is a convention that is commonly followed and it will allow you to play nice with the reusable Django apps that are floating around in the ether. For more information, see here.
If you want to actually modify the core User model but also "play nice" with reusable apps that rely on it, you're opening a bit of a Pandora's Box. Developers make base assumptions about how the core library is structured, so any changes may cause unexpected breakage. Nonetheless, you can monkeypatch changes to the base model, or branch a copy of Django locally. I would discourage the latter, and only recommend the former if you know what you're doing.
You face a bit of a dilemma which really has two solutions if you're committed to avoiding the profile-based customization already pointed out.
Change the User model itself, per Daniel's suggestions
Write a CustomUser class, subclassing User or copying its functionality.
The latter suggestion means that you would have to implement some things that User does automatically manually, but I wonder whether that's as bad as it sounds, especially if you're at the beginning of your project. All you'd have to do is rewrite a middle-ware class and some decorators.
Of course, I don't think this buys you anything that 1 won't get you, except that your project shouldn't break if you svn update your django. It may avoid some of the compatibility problems with other apps, but my guess is most problems will exist either way.
There are anumber of ways to do this, but here's what I'd do: I'd allow a user to enter an email, username (which must contain at least one letter and no # symbols) or mobile number. Then, when I validate it:
Check for the presence of #. If so, set it as the user's email, hash it appropriately and set it as their username as well.
Check to see if it's only numbers, dashes and +. Then, strip the appropriate characters and store it as both mobile number and username (if you're storing the mobile number in another model for SMS purposes or something).
If it's not either, just set it as username.
I'd also validate the user/phone/email field similarly on login and look in the appropriate place so that if, say, a user signs up with their mobile number and then changes their username (for some other purpose), they can still sign in with their mobile number.

Categories