有没有一种方法可以扩展内置的 Django Group 对象以添加附加属性,类似于扩展用户对象的方式?使用用户对象,您可以执行以下操作:
class UserProfile(models.Model):
user = models.OneToOneField(User)
并将以下内容添加到settings.py文件中
AUTH_PROFILE_MODULE = 'app.UserProfile'
这让你:
profile = User.objects.get(id=1).get_profile()
是否有与此方法等效的扩展组的方法?如果没有,我可以采取其他方法吗?
如果您只是对 Group 对象进行子类化,那么默认情况下它将创建一个新的数据库表,并且管理站点不会选择任何新字段。
您需要向现有组中注入新字段:
if not hasattr(Group, 'parent'):
field = models.ForeignKey(Group, blank=True, null=True, related_name='children')
field.contribute_to_class(Group, 'parent')
要将方法添加到组中,子类化但将模型标记为代理:
class MyGroup(Group):
class Meta:
proxy = True
def myFunction(self):
return True
您可以创建一个子类化 Group 的模型,添加您自己的字段,并使用模型管理器返回您需要的任何自定义查询集。这是一个截断的示例,显示了我如何扩展组来代表与学校相关的家庭:
from django.contrib.auth.models import Group, User
class FamilyManager(models.Manager):
"""
Lets us do querysets limited to families that have
currently enrolled students, e.g.:
Family.has_students.all()
"""
def get_query_set(self):
return super(FamilyManager, self).get_query_set().filter(student__enrolled=True).distinct()
class Family(Group):
notes = models.TextField(blank=True)
# Two managers for this model - the first is default
# (so all families appear in the admin).
# The second is only invoked when we call
# Family.has_students.all()
objects = models.Manager()
has_students = FamilyManager()
class Meta:
verbose_name_plural = "Families"
ordering = ['name']
def __unicode__(self):
return self.name
我设法通过@Semprini aswer 使用迁移。
所以我需要在我的团体相关字段中创建一个公司相关字段,所以在我的模型中我这样做了:
if not hasattr(Group, 'company'):
field = models.ForeignKey(Company, on_delete=models.DO_NOTHING, null=True)
field.contribute_to_class(Group, 'company')
class Group(Group):
class Meta:
proxy = True
然后我运行manage.py makemigrations。这创建了 2 个文件。一个依赖于另一个,但第一个属于
auth
应用程序是在我的虚拟环境中创建的。文件看起来像这样:
# Generated by Django 2.2.5 on 2019-10-08 16:00
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('myapp', '0013_guestuser_permissions_20190919_1715'),
('auth', '0011_update_proxy_permissions'),
]
operations = [
migrations.AddField(
model_name='group',
name='company',
field=models.ForeignKey(
null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='myapp.Company'),
),
]
在 myapp 迁移文件夹中创建的第二个如下所示:
# Generated by Django 2.2.5 on 2019-10-08 16:00
import django.contrib.auth.models
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('auth', '0012_group_company_20191008'),
('myapp', '0013_guestuser_permissions_20190919_1715'),
]
operations = [
migrations.CreateModel(
name='Group',
fields=[
],
options={
'proxy': True,
'indexes': [],
'constraints': [],
},
bases=('auth.group',),
managers=[
('objects', django.contrib.auth.models.GroupManager()),
],
),
]
因此,解决方案是将我的 virtualenv 中创建的文件移至 myapp 迁移文件夹,然后再使用 makemigrations 生成另一个文件,但由于迁移应用于
auth
应用程序而不是 myapp
,我必须在中实现一种解决方法文件。所以现在的最终文件是:
# Generated by Django 2.2.5 on 2019-10-08 16:00
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('myapp', '0013_guestuser_permissions_20190919_1715'),
('auth', '0011_update_proxy_permissions'),
]
operations = [
migrations.AddField(
model_name='group',
name='company',
field=models.ForeignKey(
null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='myapp.Company'),
),
]
def mutate_state(self, project_state, preserve=True):
"""
This is a workaround that allows to store ``auth``
migration outside the directory it should be stored.
"""
app_label = self.app_label
self.app_label = 'auth'
state = super(Migration, self).mutate_state(project_state, preserve)
self.app_label = app_label
return state
def apply(self, project_state, schema_editor, collect_sql=False):
"""
Same workaround as described in ``mutate_state`` method.
"""
app_label = self.app_label
self.app_label = 'auth'
state = super(Migration, self).apply(project_state, schema_editor, collect_sql)
self.app_label = app_label
return state
变异和应用方法允许您从
auth
迁移迁移到 myapp
应用程序。
在第二个文件中,我只是更改依赖项以依赖于新创建的文件:
# Generated by Django 2.2.5 on 2019-10-08 16:00
import django.contrib.auth.models
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('myapp', '0014_group_company_20191008'),
('myapp', '0013_guestuser_permissions_20190919_1715'),
]
operations = [
migrations.CreateModel(
name='Group',
fields=[
],
options={
'proxy': True,
'indexes': [],
'constraints': [],
},
bases=('auth.group',),
managers=[
('objects', django.contrib.auth.models.GroupManager()),
],
),
]
对我来说,工作解决方案基于:
https://docs.djangoproject.com/pl/1.11/topics/auth/customizing/#extending-user
让我解释一下我对使用电子邮件别名扩展默认模型的组做了什么:
首先,我创建了自己的 django 应用程序,命名为它
python Manage.py startapp auth_custom
代码部分:
在 auth_custom/models.py 我创建了对象 CustomGroup
from django.contrib.auth.models import Group
from django.db import models
class CustomGroup(models.Model):
"""
Overwrites original Django Group.
"""
def __str__(self):
return "{}".format(self.group.name)
group = models.OneToOneField('auth.Group', unique=True)
email_alias = models.EmailField(max_length=70, blank=True, default="")
在 auth_custom/admin.py:
from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
from django.contrib.auth.models import Group
class GroupInline(admin.StackedInline):
model = CustomGroup
can_delete = False
verbose_name_plural = 'custom groups'
class GroupAdmin(BaseGroupAdmin):
inlines = (GroupInline, )
# Re-register GroupAdmin
admin.site.unregister(Group)
admin.site.register(Group, GroupAdmin)
进行迁移后,我在 Django 管理视图中得到这样的结果。
为了访问此自定义字段,您必须输入:
from django.contrib.auth.models import Group
group = Group.objects.get(name="Admins") # example name
email_alias = group.customgroup.email_alias
如有错误请通知我,我会更正此答案。
您可以使用 django-group-model 包来覆盖组模型,就像处理用户模型一样。这是一个简短的例子。
安装包
pip install django-group-model
将其添加到顶部已安装的应用程序中。
INSTALLED_APPS = [
...
'django_group_model',
...
]
安装后,我们将覆盖默认的组模型,将其称为角色,并添加类别字段作为自定义字段(可选)。
from django_group_model.models import AbstractGroup
class Role(AbstractGroup):
category = models.CharField(max_length=50)
class Meta:
verbose_name = "role"
verbose_name_plual = "roles"
设置
AUTH_GROUP_MODEL
设置。
AUTH_GROUP_MODEL = 'myapp.Role'
将组模型与您的用户模型一起使用
class User(AbstractUser, ...):
...
roles = models.ManyToManyField(
'myapp.Role',
blank=True,
related_name="user_set",
related_query_name="user",
)
groups = None
...
不要忘记将默认值
groups
设置为 None
您可能还想查看文档这里