per*_*ror 9 django django-models
我知道,这个问题在SO中已经被多次提出过了,但我读到的大部分答案都已过时(建议现在已弃用的AUTH__PROFILE_MODULE方法),或缺乏具体的例子.
所以,我读了Django文档[ 1,2 ],但我缺乏关于如何正确使用它一个真实的例子.
事实上,我的问题出现在通过表单创建(或更新)新用户时.显然创建了用户,但扩展中的字段都未设置.我知道Django文档说明:
这些配置文件模型在任何方面都不是特别的 - 它们只是恰好与User模型具有一对一链接的Django模型.因此,在创建用户时不会自动创建它们,但
django.db.models.signals.post_save可以使用a 来根据需要创建或更新相关模型.
但是,我不知道如何在实践中这样做(我应该添加aa receiver,如果' 是 ',哪一个).
现在,我有以下内容(为了简洁起见,从文档中获取):
models.pyfrom django.contrib.auth.models import User
class Employee(models.Model):
user = models.OneToOneField(User)
department = models.CharField(max_length=100)
Run Code Online (Sandbox Code Playgroud)
admin.pyfrom django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from my_user_profile_app.models import Employee
# Define an inline admin descriptor for Employee model
class EmployeeInline(admin.StackedInline):
model = Employee
can_delete = False
verbose_name_plural = 'employee'
# Define a new User admin
class UserAdmin(UserAdmin):
inlines = (EmployeeInline, )
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Run Code Online (Sandbox Code Playgroud)
forms.pyclass SignupForm(account.forms.SignupForm):
department = forms.CharField(label="Department", max_length=100)
class SettingsForm(account.forms.SignupForm):
department = forms.CharField(label="Department", max_length=100)
Run Code Online (Sandbox Code Playgroud)
然后,在我的代码中,我使用它像这样:
u = User.objects.get(username='fsmith')
freds_department = u.employee.department
Run Code Online (Sandbox Code Playgroud)
但是,"注册和设置"表单无法按预期运行,并且departement未记录新值.
任何暗示都是受欢迎的!
per*_*ror 16
我已经查看了所有的答案,但没有一个确实能解决我的问题(尽管你们中的一些人给了我很好的提示,以便找到正确的方向).我将在这里总结一下我找到的解决问题的方法.
首先,我不得不承认我没有说出我的问题.我想在User模型中插入额外的字段并使用其他应用程序,例如Django的默认身份验证方案.因此,User通过继承和设置扩展默认值AUTH_USER_MODEL是一个问题,因为其他Django应用程序停止正常工作(我相信他们没有使用user = models.OneToOneField(settings.AUTH_USER_MODEL)但是user = models.OneToOneField(User)).
因为,如果正确地重写我正在使用的其他应用程序将会太长,我决定通过一对一字段添加此额外字段.但是,文档遗漏了几点,我想填写以下内容.
因此,这是一个完整的示例,User使用相同的模型向模型添加额外的字段.
首先,编写模型的描述,收集要添加到models.py文件中的额外字段:
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User)
extra_field = models.CharField(max_length=100)
Run Code Online (Sandbox Code Playgroud)
然后,我们需要在UserProfile每次User创建时触发添加对象.这是通过将此代码附加到receiver.py文件中的正确信号来完成的:
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from my_user_profile_app.models import UserProfile
@receiver(post_save, sender=User)
def handle_user_save(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
Run Code Online (Sandbox Code Playgroud)
现在,如果您希望能够通过管理界面对其进行修改,只需将其与文件中的常用UserAdmin表单进行堆叠即可admin.py.
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from my_user_profile_app.models import UserProfile
# Define an inline admin descriptor for UserProfile model
class UserProfileInline(admin.StackedInline):
model = UserProfile
can_delete = False
# Define a new User admin
class UserAdmin(UserAdmin):
inlines = (UserProfileInline, )
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Run Code Online (Sandbox Code Playgroud)
然后,现在是时候尝试将此额外字段与默认的Django身份验证应用程序混合使用.为此,我们需要添加一个额外的字段来填充文件中SignupForm的SettingsForm直接继承forms.py:
import account.forms
from django import forms
class SignupForm(account.forms.SignupForm):
extra_field = forms.CharField(label="Extra Field", max_length=100)
class SettingsForm(account.forms.SignupForm):
extra_field = forms.CharField(label="Extra Field", max_length=100)
Run Code Online (Sandbox Code Playgroud)
而且,我们还需要添加一些代码来显示并正确获取已添加到原始User模型的数据.这是通过继承到文件中SignupView的SettingsView视图来完成的views.py:
import account.views
from my_user_profile_app.forms import Settings, SignupForm
from my_user_profile_app.models import UserProfile
class SettingsView(account.views.SettingsView):
form_class = SettingsForm
def get_initial(self):
initial = super(SettingsView, self).get_initial()
initial["extra_field"] = self.request.user.extra_field
return initial
def update_settings(self, form):
super(SettingsView, self).update_settings(form)
profile = self.request.user.userprofile
profile.extra_field = form_cleaned_data['extra_field']
profile.save()
class SignupView(account.views.SignupView):
form_class = SignupForm
def after_signup(self, form):
profile = self.created_user.userprofile
profile.extra_field = form_cleaned_data['extra_field']
profile.save()
super(SignupView, self).after_signup(form)
Run Code Online (Sandbox Code Playgroud)
一旦一切就绪,它应该很好地工作(希望如此).
我在这个主题上挣扎了大约一年,直到我终于找到了一个我很满意的解决方案,而且我确切地知道你的意思是"那里有很多,但它不起作用".我曾尝试以不同的方式扩展User模型,我尝试过UserProfile方法,以及其他一些一次性解决方案.
我终于想出了如何简单地扩展AbstractUser类来创建我的自定义用户模型,这对我的许多项目来说都是一个很好的解决方案.
所以,让我澄清你上面的一条评论,你真的不应该在2个模型之间创建链接,普遍接受的"最佳"解决方案是根据您的需要从AbstractUser或AbstractBaseUser继承一个模型.
让我觉得一个棘手的问题是"扩展用户模型"没有让我到达我想要的地方,我需要替换用户模型,我确信你已经多次看到/读过,但可能没有吸收它(至少我知道我没有).
一旦你掌握了它,那真的没有那么多代码,它也不是太复杂.
# models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
'''
Here is your User class which is fully customizable and
based off of the AbstractUser from auth.models
'''
my_custom_field = models.CharField(max_length=20)
def my_custom_model_method(self):
# do stuff
return True
Run Code Online (Sandbox Code Playgroud)
在此之后有几件事需要注意,其中一些在django 1.7中出现.
首先,如果您希望管理页面看起来像以前一样,则必须使用UserAdmin
# admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
# Register your models here.
admin.site.register(get_user_model(), UserAdmin)
Run Code Online (Sandbox Code Playgroud)
另一件事是,如果您想要在模型文件中导入User类,则必须从设置中导入它,而不是使用get_user_model().如果你碰到这个,很容易修复,所以我只想给你一个抬头.
您可以查看我用于启动项目的种子项目,以获得使用自定义用户模型的完整但简单的项目.用户的东西在主应用程序中.
从那里所有注册和登录的工作方式与普通的Django用户相同,所以我不会详细介绍该主题.我希望这对你有所帮助,就像它帮助了我一样!
我试图避免扩展用户模型,如django文档中所述.
我用这个:
class UserExtension(models.Model):
user=models.OneToOneField(User, primary_key=True)
... your extra model fields come here
Run Code Online (Sandbox Code Playgroud)
OneToOneField的文档:https://docs.djangoproject.com/en/1.7/topics/db/examples/one_to_one/
我看到了这些好处:
UserExtension应该可以在不提供参数的情况下创建.所有字段必须具有合理的默认值.
然后,您可以创建一个信号处理程序,在创建UserExtension用户时创建实例.
| 归档时间: |
|
| 查看次数: |
9488 次 |
| 最近记录: |