multiple users and Django - python

Starting to learn Django, not sure how to deal with multiple users and user types. What I would like to do is have a signin page where users of type A, B or C can log in (or new users can register as type A or B) and depending on their type they are presented with a different site. Furthermore, users of types A and B can actually be organized in groups within their own type and across types. So B1 and B2 may be only assigned to A1 or a group 'GA' which contains members {A2, A1, A3}.
The main goal is to create a site where people can posts question to specific experts or to the general public. When the experts log in they would only be presented to the users assigned to them and if they don't know the answer they could contact other experts or pass the question on to a larger group of experts say GE = {E1, E3, E6}.
There may already be tool out there to do this and I am complete oblivious to it. As of now we're just going to write it from scratch, and Django seemed like a good tool to use.
Any suggestions are helpful.

Sounds like quite the task you have! The first step is to use a Custom User Model, which will take the built-in django user model and allow you to extend it flexibly. I would suggest extending from the AbstractUser.
When you have your user authentication working you can add fields to the users to categorize them how you want.
Your explanation of what you're trying to do after that in the view logic is a little confusing so I'm going to let you figure that part out, but building a custom user model should get you going in the right direction.

It sounds to me that you are building something like a task management system. Where questions are like tasks, and the experts are like the assignees of tasks.
There are two approaches.
APPROACH 1 - use the django authentication system
Suppose you already know how to create users, authenticate them and log them in.
Create user groups and assign permissions to each group (You could either do this through the django admin or through code)
In the views.py, output different contents based on the permission that the logged in user has.
APPROACH 2 - custom build it
Create a Model for User Type and a Model for User (you can either use the default User model or extend it)
Assign each question to a specific User Type.
In the views.py, determine what questions to display based on the User Type of the logged in User.
APPROACH 2 is recommended because it's more flexible and scalable, given that you will extend your programme with more functions in the future.
I think you should have the basic ideas to start with it. Good luck.

Related

Django validate form fields manually

I have a form which is dynamically generated. I cannot predict how many text inputs or multiple choices will be included before hand. Thus, I cannot use ModelForm or anything similar.
I wonder if I can leverage the built-in validating code from Django fields and apply them manually somehow, because I can determine the type of user inputs (e.g. whether if it is text, radio button, checkbox, etc.). Something like this would be great:
if type == 'Text':
#perform validation
#get clean data
elif type == 'Checkbox':
#perform validation
#get clean data
UPDATE: My site allows users to generate a survey according to their needs. So for example, an user decides to create a survey with two questions:
what is your name?
what's the brand of your smartphone? A) iPhone B) HTC
The first question is <input type="text"> and the second one is <input type="radio">
The information about what types of questions are generated is stored in the database. So I would have rows like this in the DB to describe the question:
ID TYPE TEXT
1 TEXT What is your name?
2 RADIO what is your name?
When the survey goes online and an user fills it out. I need to validate their input. How can I utilize the built-in validation functionality of Django to deal with this situation?
I'd recommend you using model formsets, as they are here for exactly the reason you've said: dealing with the arbitrary count of fields. And that way you still will be able to use Django's validation (which is very convenient).
If you post a sample form you're dealing with, I would be able to draft a formset example.
Update: Ah, so you need a survey functionality? It's a totally different beast. Then I can't imagine a reason not to leverage one of the existing solutions. The ed-questionnaire
package seems to be the most featured and mature one. And as always with Django, you can relatively easily customize it away.
If I haven't convinced you yet, just take a look at its models.py file. Do you really have the time and will to re-implement all that stuff?

Django: multiple accounts, with multiple users under each account, but account-specific data

Using Django 1.5 here. I have an application I've created that currently has one big set of data, for one "account" if you will. Meaning all the data in all the models in my application are available to all logged-in users. Now, I want to be able to allow more people to use my application but with their own set of data. So I need to separate users into different accounts with different sets of data for each account. There could potentially be one or multiple users that has access to each account. At this time I don't need different users within one account to have different levels of access though I do intend for one user to be the account "owner".
I know that to make this conversion, I of course need to add a field to every model with a foreign key to a new "account" model. But beyond that I'm a little foggy. This appears to be a square peg in the round hole of Django's auth system. So the question is, what is the best approach?
A few thoughts I had so far:
Simply filter each and every query by account
Wrap each and every view with a decorator, but with multiple models, do I have to create a different decorator for each model? Can I tell from within the decorator which model is being accessed?
Somehow make use of the Auth system's user_passes_test decorator, but again, different models.
Extend the auth system to include a request.account attribute
Create a new mixin for my views? What if I'm not using exclusively CBVs?
Different middleware?
I considered using a new group for each account and then filtering by group instead of a new account model but I predict that would be a poor fit in this situation, as it isn't using groups as they were intended.
This is less of a code question and more of a big-picture, best-practices question. How would you approach this?
What you request is not so exotic: This is called authority data - you seperate your users to authorities and each authority will have each own data. For instance, you may have a number of departments in an organization - the data of each department can be edited only by members of the same department. I have already written a blog post with a simple approach to that using django:
http://spapas.github.io/2013/11/05/django-authoritiy-data/
To recap the post, I propose just adding an Authority model for which your User will have a ForeignKey (each User will have a Profile).
Now, all your Models whose data will belong to specific Authorities will just contain a ForeignKey to Authority. To check for the permissions you could use CBVs - the django admin will only be available to the central Administrators that have access to all the data. I recommend against using the django permissions for authorization of Authority data. If you want read the post which is much more detailed and ask here any questions.

Django: user-profiles and user-registration -- use the bitbucket modules or django's current 1.3 release?

I am fairly new to django, and I thought user registration and profiling would be good to start with. Not so sure any more. So please forgive me for using this expert-forum as a shortcut, but reading quite a few blogs about how user profiling and registration should be accomplished, kind of leaves me with more questions than answers. I'd be glad for some rough line to follow. Here is what the application should do:
Several types of users should be able to register by way of a registration form. This should include not only django's inbuilt username and password but also other specific information. I was successful in creating such a form and saving it into the database (User object, and self-defined UserProfile object). Each user should be able to edit his settings later.
User Profiles:
q1) However, if I want more than 1 profile, is it still correct that these profile classes must be subclasses of class UserProfile because the settings attribute AUTH_PROFILE_MODULE can only have 1 value?
q2) Is it possible to define a base UserProfile with e.g. 10 fields, and flexibly allow for SubUserProfile_A to inherit 6 certain fields, while SubUserProfile_B inherits 6 other fields, i.e. the base class provides all features, and a subclass inherits a subset of it? Or better define a base UserProfile with 2 overall features, and have each subclass have its own specific features?
q3) Then I learnt that there is a predefined package for user-profiles by J. Bennett, django-profiles. I haven't used it since I read it is rarely documented. Is it deprecated, and features are all subsumed by django 1.3, or is it still recommended (last update 2008)? E.g. the user should be able to edit his settings, but this could also be programmed by use of generic.EditView(), available as of django 1.3. No? In other words: which advantages does user-profiles have compared to django 1.3?
User registration:
q4) Then I learnt that there is a predefined package for registration by J. Bennett, django-registration. It comes in 2 flavors: a) with use of class-based generic views (brandnew), b) without class-based gen. views. It seems that I will need them anyway since they offer e.g. "email-confirmation" which is of course not yet in my app.
So, if I need this module at all (do I?), which version should I use, the old (easier?) or the new one (accompanied by a warning of Bennett:) )? Or should I stay with django 1.3?
Answers are highly welcome. I really don't expect novels but maybe helpful hints.
Thanks a lot in advance!
Very good questions. You can try using both applications separately and see how they work first. you can also check out this SO thread django-registration creating blank django-profiles using signals or this article http://dewful.com/?p=70

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.

Categories