用自定义字段扩展User模型(与Django的身份验证应用程序绑定)的最佳方法是什么?我还可能想使用电子邮件作为用户名(用于身份验证)。
我已经看到了一些方法,但不能决定哪一个是最好的。
用自定义字段扩展User模型(与Django的身份验证应用程序绑定)的最佳方法是什么?我还可能想使用电子邮件作为用户名(用于身份验证)。
我已经看到了一些方法,但不能决定哪一个是最好的。
当前回答
下面是另一种扩展User的方法。 我觉得它比上面两种方法更清晰,简单,易读。
http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/
使用上述方法:
你不需要使用 user.get_profile()。Newattribute访问额外的信息 与用户相关 你可以直接访问 通过 user.newattribute
其他回答
关于存储用户的附加信息,有一个官方建议。 Django手册也在Profiles部分讨论了这个问题。
试试这个:
创建一个名为Profile的模型,并使用OneToOneField引用用户,并提供一个related_name选项。
models.py
from django.db import models
from django.contrib.auth.models import *
from django.dispatch import receiver
from django.db.models.signals import post_save
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_profile')
def __str__(self):
return self.user.username
@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
try:
if created:
Profile.objects.create(user=instance).save()
except Exception as err:
print('Error creating user profile!')
现在要使用User对象直接访问配置文件,可以使用related_name。
views.py
from django.http import HttpResponse
def home(request):
profile = f'profile of {request.user.user_profile}'
return HttpResponse(profile)
从Django 1.5开始,你可以很容易地扩展用户模型,在数据库中只保留一个表。
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import ugettext_lazy as _
class UserProfile(AbstractUser):
age = models.PositiveIntegerField(_("age"))
您还必须在设置文件中将其配置为当前用户类
# supposing you put it in apps/profiles/models.py
AUTH_USER_MODEL = "profiles.UserProfile"
如果你想添加很多用户的首选项,OneToOneField选项可能是一个更好的选择。
给开发第三方库的人一个提示:如果您需要访问用户类,请记住人们可以更改它。使用官方帮助获取正确的类
from django.contrib.auth import get_user_model
User = get_user_model()
你可以通过每次使用Django post save信号创建用户时创建一个新条目来扩展用户配置文件
models.py
from django.db.models.signals import *
from __future__ import unicode_literals
class UserProfile(models.Model):
user_name = models.OneToOneField(User, related_name='profile')
city = models.CharField(max_length=100, null=True)
def __unicode__(self): # __str__
return unicode(self.user_name)
def create_user_profile(sender, instance, created, **kwargs):
if created:
userProfile.objects.create(user_name=instance)
post_save.connect(create_user_profile, sender=User)
这将在创建新用户时自动创建一个雇员实例。
如果你想扩展用户模型,并在创建用户时添加更多信息,你可以使用django-betterforms (http://django-betterforms.readthedocs.io/en/latest/multiform.html)。这将创建一个包含UserProfile模型中定义的所有字段的用户添加表单。
models.py
from django.db.models.signals import *
from __future__ import unicode_literals
class UserProfile(models.Model):
user_name = models.OneToOneField(User)
city = models.CharField(max_length=100)
def __unicode__(self): # __str__
return unicode(self.user_name)
forms.py
from django import forms
from django.forms import ModelForm
from betterforms.multiform import MultiModelForm
from django.contrib.auth.forms import UserCreationForm
from .models import *
class ProfileForm(ModelForm):
class Meta:
model = Employee
exclude = ('user_name',)
class addUserMultiForm(MultiModelForm):
form_classes = {
'user':UserCreationForm,
'profile':ProfileForm,
}
views.py
from django.shortcuts import redirect
from .models import *
from .forms import *
from django.views.generic import CreateView
class AddUser(CreateView):
form_class = AddUserMultiForm
template_name = "add-user.html"
success_url = '/your-url-after-user-created'
def form_valid(self, form):
user = form['user'].save()
profile = form['profile'].save(commit=False)
profile.user_name = User.objects.get(username= user.username)
profile.save()
return redirect(self.success_url)
addUser.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="." method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Add</button>
</form>
</body>
</html>
urls . py
from django.conf.urls import url, include
from appName.views import *
urlpatterns = [
url(r'^add-user/$', AddUser.as_view(), name='add-user'),
]
简单而有效的方法是 models.py
from django.contrib.auth.models import User
class CustomUser(User):
profile_pic = models.ImageField(upload_to='...')
other_field = models.CharField()