Django comes with a permission framework where the fields of the Auth_User table are difficult to meet the normal requirements and therefore need to be extended, as for extensions, there are generally several options:
1. Directly modify the Django source code, modify the user class definition, and various methods, and then expand the Database Auth_User table field to match their own needs. (Source code: Django.contrib.auth.models import User), this way, every time you upgrade Django is very careful.
2. Copy the source code of the Django user and the authentication part to your app, then modify and configure it so that you don't need to change the Django code. But if you're going to upgrade Django, you might be in trouble.
3. Inherit the user and do the extension.
4. Django's official recommended method, Profile mode extension.
Method One
Compare these several ways, found that 1, 2 methods are very yellow and violent. So not in very special cases, it is not recommended. The 3rd method, I currently test down is can, but after the extension, enter the password when it is actually clear text, and saved into the database is not encrypted password, is still looking for reasons, so here the 4th method is introduced.
In models.py, add the following class to extend the user:
#================== Extended User ==================================== class userprofile(models. Model):user = models. Onetoonefield (User) major = models. TextField (default="', blank=True) address = models. Charfield (max_length= $, default="', blank=True) def __unicode__(self): returnSelf.user.username def create_user_profile(sender, instance, created, **kwargs): "" " Create the UserProfile when a new User is saved" "" ifCreated:profile = UserProfile () Profile.user = Instance Profile.save ()#post_save. Connect (create_user_profile, Sender=user)"" " do not understand is that I must comment out the above line, will not be wrong, otherwise there will be duplicate entry ' 2 ' for key ' user_id '), see meaning, repeat, but do not understand why repeat, comment off the above, everything is normal, But there are differences with official documents, confusing "" "#================== Extended User End ================================
Also need to modify admin.py
"""用户模块扩展"""class ProfileInline(admin.StackedInline): model = UserProfile #fk_name = ‘user‘ 1 Falseclass CustomUserAdmin(UserAdmin): inlines = [ProfileInline,]admin.site.unregister(User)admin.site.register(User, CustomUserAdmin)"""用户模块扩展"""
Modify the configuration of the settings.py to increase
"""用户模块扩展部分"""‘djangoadmin.myadmin.UserProfile‘"""用户模块扩展完成"""
According to the official explanation, here is the name of the app label plus the extension class. The name of the app that should be created is the official recommended way to use "." In two parts. Connected, I have three parts here, there is no error.
Then run the Python manage.py syncdb, which is the table that will create the response in the database, and has user_id this foreign key field.
Finally, let's run the program and go into the Add user interface, and you'll see that the fields you've expanded are displayed.
Each time the user is added, the corresponding data is added to the expanded table, and when modified, the corresponding data is modified, which is correlated by user_id, thus completing the extension of the user model.
If you want to get the contents of an extension table, you can get it by Request.user.get_profile (). Address. After the user object is obtained, it is convenient to get the extended class.
Method Two
If you want to inherit the user's way to do, you can use the following methods, reproduced from the Internet:
1. Create a user profile class that inherits directly from the user
Program Code Program code
fromimport User, UserManagerclass CustomUser(User): timezone = models.CharField(max_length=50, default=‘Asia/shanghai‘) objects = UserManager()
In this way, the user = CustomUser.objects.create (...) can be used directly. method to create a new object. And if you use Request.user to get the object that you extend, you can take the property directly. No need for get_profile.
2. Extended authentication mechanism
Program Code Program code
fromDjango.confImportSettings fromDjango.contrib.auth.backendsImportModelbackend fromDjango.core.exceptionsImportImproperlyconfigured fromDjango.db.modelsImportGet_model class customusermodelbackend(modelbackend): def authenticate(self, Username=none, password=none): Try: User = Self.user_class.objects.get (username=username)ifUser.check_password (password):returnUserexceptSelf.user_class. Doesnotexist:return None def get_user(self, user_id): Try:returnSelf.user_class.objects.get (pk=user_id)exceptSelf.user_class. Doesnotexist:return None @property def user_class(self): if notHasattr (Self,' _user_class '): Self._user_class = Get_model (*settings. Custom_user_model.split ('. ',2))if notSelf._user_class:RaiseImproperlyconfigured (' Could not get custom user model ')returnSelf._user_class
- Configure settings.py
Program Code Program code
AUTHENTICATION_BACKENDS = ( ‘myproject.auth_backends.CustomUserModelBackend‘,)
- Run Python manage.py syncdb
A database is also generated, but the fields of the table are not used with the previous method.
Then run, the same test, can achieve the same effect, but the interface on the password input where I am always dissatisfied, so I did not use.
Method Three
Django User model:
The difference between Django and many other web frameworks is that it comes with a ready-made user model, because 99% of web development involves the concept of a user, Not only does it solve the need to repeat the work of creating a new user table each time a project is developed. And the biggest benefit is the Django model-specific processing, only through the Django.contrib.auth.models import user model, then regardless of which app you come from, each app is referenced by the same User model, The actual foreign key generated in the database after those fields are pointed to the user model via Foreignkey,manytomanyfield,onetoonefield is the ID of the reference auth_user table. This is an indispensable mechanism for many apps that are independent but need a user model, because if Django does not have the built-in user models, then each app has to be isolated, defining the user model independently, and the end result is that when it comes to combining these apps, Because the user model is not unified, it takes a lot of time to modify the user model-related code for these apps. The most obvious example of this is the Pinax project (http://pinaxproject.com/), a SNS project that combines a large number of open source apps and is simply configured to assemble them.
Problems with the Django User model:
Although Django comes with a user model that facilitates a lot of apps, it's important that every app needs to add some additional information to the user model, and that the field defined in the Django-based user model is a regular message. Must not meet the needs of the app itself. To do this, you need to add a profile to put the user's additional information. This is mainly by the following ways:
1. The way Django is officially directed:
See document http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
The approximate process is this: Define a profile model, which contains a unique=true ForeignKey, in settings.py add an option Auth_profile_module point to the profile model, Then the example of the user model can be obtained by get_profile () to obtain the corresponding profile information, although this method seems very convenient, but one of the obvious disadvantage is that it is in an additional table, although the Get_profile () Cached the results of the first fetch of the profile, but each HTTP request to do a query for this, when the number of users, the impact on the performance is relatively large. Another question is what to do when you need to define a manytomanyfield like friends that points to ' self '? Definition in the profile is very unreasonable, a user and another user to make friends, not with the profile of Ta do friends, not to mention the definition in the profile, as the friends of the reverse query, obtained queryset is profiles, When you want to get these profile-directed user information, you have to do a lot of queries.
2. Modify Django's source code directly on the user model to add fields:
This method is very straightforward and obvious, if it is used as a final release version of 1.0.2-final, and it is not intended to update the Django version later, it is also possible. But if you use SVN development version, the way to modify the source is a bit violent.
3, directly discard the Django user model, you define a user model, including their own management auth, write auth backends:
I have seen a few projects are done, although by inheriting the original user Model,modelbackend class, you can only write very little code can be implemented, this way in fact, modify Django source code is no big difference, is to reduce a profile table, Only the extended user model is placed in the Django source code, one is placed in its own source, and this way than to modify the source is worse, this destroys the first mentioned in combination with other apps of the possibility.
Do not modify the Django source code or add an extended user model for the profile table:
The various methods mentioned above are mainly about modifying the Django source code and adding a profile table between the pros and cons of the expansion. So is there a way of both worlds, neither modifying the source code nor adding the profile table. The answer is yes, and in the early Django version, this is even a very common way, but later Django changed the model part of the source, blocking this way, because it seems too magic.
The inner meta in the previous Django model can define a replaces_module parameter that specifies that you want to replace the model with another model, which looks strange and magical, but it's confusing to manage. So the last feature was canceled.
Although the above way is blocked, but still can be changed in other ways the user model class, said so much, or directly look at the source to more clear it:
fromDjango.dbImportModels fromDjango.contrib.auth.modelsImportUser fromDjango.contrib.auth.adminImportUseradminImportDatetime class ProfileBase(type): def __new__(CLS, name, bases, Attrs):module = Attrs.pop (' __module__ ') Parents = [b forBinchBasesifIsinstance (b, ProfileBase)]ifParents:fields = [] forObj_name, objinchAttrs.items ():ifIsinstance (obj, models. Field): Fields.Append (obj_name) user.add_to_class (obj_name, obj) useradmin.fieldsets = List ( Useradmin.fieldsets) UserAdmin.fieldsets.append ((name, {' Fields ': Fields}))returnSuper (ProfileBase, CLS). __new__ (CLS, name, bases, Attrs) class profile(object):__metaclass__ = ProfileBase class myprofile(Profile):Nickname = models. Charfield (max_length =255) Birthday = models. Datetimefield (null =True, blank =True) City = models. Charfield (max_length = -, blank =True) University = models. Charfield (max_length =255, blank =True) def is_today_birthday(self): returnSelf.birthday.date () = = Datetime.date.today ()
The above code defines a profilebase meta-class, and then defines a profile class as the profile base class, and its meta class is profilebase.
The function of a meta-class is simply to create classes of other classes. The example of a meta-class is a normal class, and an instance of an ordinary class is an ordinary instance.
It doesn't matter if you don't understand this, just know that in the code above, when the interpreter sees you defining a subclass of a profile class, and the meta class of the profile class is profilebase, so Myprofilede's meta class is also profilebase, That is, when you define a subclass of any profile, it executes the code in new in the meta-class profilebase, and passes the class (name, base class, Class attribute) that is being defined as a parameter to new.
The field in Myprofilede uses the same declaration syntax as the normal model, so the field and the custom method Is_today_birthday passed in as a property in Attrs, and the meta-class extracts the information through
User.add_to_class (Obj_name, obj) is added to the user class, and Add_to_class is also the way in which field is defined in the normal model, because the common model also has a meta class that is doing something similar, Only the Meta class defined here specifically adds something to the user model.
After adding these fields and custom methods, the previously recognized attributes are field and then added to Useradmin.fieldsets, so that the new field can be edited with the other user fields in Admin.
If you have other apps that you want to add field or method to the user model, just pass the subclass profile and define it using declarative syntax, and all other work has a meta-class to help you do it.
The effect of the field and method added to the user model in this way is the same as modifying the Django User model's source code, but now these changes do not have to be as violent as modifying the source code, and you can add it whenever you want.
Places to be aware of:
1, the definition of the above meta-class includes the definition of myprofile, preferably, like the normal model, placed in the app's models.py file, so that Django can easily encounter these definitions, or Django did not see the code will not be effective, and placing it in other places is very prone to import dependency issues.
2, if you have synchronized the database through SYNCDB, and then use this method to expand the user model, then Django know that you defined these fields, but again run syncdb, no longer for these field automatically create database field, Because Django's syncdb is only responsible for creating fields for new tables. This is the same case that you have defined a model and run SYNCDB, and then add fields to that model.
Reference:
Http://www.yihaomen.com/article/python/334.htm
Http://www.opscoder.info/extend_user.html
Http://www.it610.com/article/3191881.htm
How Django Notes extend the fields of the user table