【问题标题】:Add fields from another model to the admin site将另一个模型中的字段添加到管理站点
【发布时间】:2022-10-25 18:23:44
【问题描述】:

我的 Profile 模型与 Django 的内置 User 模型有 OneToOne 关系。

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    verified = models.BooleanField(default=False)

如果我想更改用户的密码或ActiveSuperuser 之类的属性,我必须在一个更改用户页面中进行,而要编辑verified 属性,我必须转到另一个页面。

有没有办法合并这个:

和这个:

放入一个表单中,以便我可以在一页中编辑有关用户的所有内容?

编辑 1

正如你们建议的StackedInline 方法,让我们看看结果如何。

请先查看 Django 的默认 Admin 站点(上图第一张截图):

  1. 所有内容都按部分分组,部分有标题。
  2. 看看密码信息是如何显示的。
  3. 有一个更改密码的链接。

    现在我实施StackedInline 解决方案。

    请注意,这是在我的myappadmin.py 中:

    from django.contrib import admin
    from .models import Profile
    from django.contrib.auth.models import User
    
    # Register your models here.
    
    
    class ProfileInline(admin.StackedInline):
        model = Profile
    
    class UserAdmin(admin.ModelAdmin):
        inlines = (ProfileInline, )
    
    
    admin.site.unregister(User)
    admin.site.register(User, UserAdmin)
    

    现在让我们看一下管理站点:

    1. 一切都散了。部分及其标题已消失(个人信息、权限等)。
    2. 密码字段显示散列密码。所有其他信息都消失了。
    3. 没有更改密码的链接。

      编辑 2

      为了解决问题编辑 1我查看了 Django (https://github.com/django/django/blob/main/django/contrib/auth/admin.py) 的源代码并添加更新我的代码如下:

      class UserAdmin(admin.ModelAdmin):
          inlines = (ProfileInline, )
          fieldsets = (
              (None, {"fields": ("username", "password")}),
              (("Personal info"), {"fields": ("first_name", "last_name", "email")}),
              (
                  ("Permissions"),
                  {
                      "fields": (
                          "is_active",
                          "is_staff",
                          "is_superuser",
                          "groups",
                          "user_permissions",
                      ),
                  },
              ),
              (("Important dates"), {"fields": ("last_login", "date_joined")}),
          )
          add_fieldsets = (
              (
                  None,
                  {
                      "classes": ("wide",),
                      "fields": ("username", "password1", "password2"),
                  },
              ),
          )
      
          filter_horizontal = (
              "groups",
              "user_permissions",
          )
          
      admin.site.unregister(User)
      admin.site.register(User, UserAdmin)
      

      我现在有管理站点中的部分:

      顶部的部分几乎显示了所有内容(除了密码字段仍然不同并且没有更改密码的链接以及 verified 字段是不是那里)但部分和标题又回来了。

      然后是这个额外且完全不必要的部分:

      如你看到的:

      1. 有关用户的所有信息字段都重复
      2. 查看密码字段
      3. 信息未按标题分组
      4. verified 归档出现。

【问题讨论】:

    标签: python django django-models django-admin django-contrib


    【解决方案1】:

    OP 可以使用InlineModelAdmin 对象之一,例如StackedInline。这允许一个人创建内联表单,提供一个在与父模型相同的页面上编辑模型的能力。

    适应OP的情况,就像

    from django.contrib import admin
    
    class ProfileInline(admin.StackedInline):
        model = Profile
    
    class UserAdmin(admin.ModelAdmin):
        inlines = [
            ProfileInline,
        ]
    
    admin.site.register(User, UserAdmin)
    

    现在 OP 的管理站点设置为从用户详细信息页面内联编辑配置文件对象。

    【讨论】:

    • @OmidShojaee 根据问题和最初的要求,我回答的是解决问题的方法。新的编辑提出了不同的要求,其本身可以理解为后续问题,这不是一个好的做法。 See here why(称为chameleon questions)。欢迎您提出新问题。您很可能会在这里获得所需的帮助。
    • 最初的要求仍然存在:向用户的“创建和编辑”页面添加一个字段。我从来没有要求一个完全搞乱这些页面的解决方案。应用您的解决方案后,整个事情都无法使用,因为我无法再更新用户的密码了。也许我应该提到我不想失去管理站点的功能。我只是认为这很明显。
    • @OmidShojaee 首先,问题有两个图像,并询问如何添加该字段。从你这边根本没有表现出任何努力。你得到了如何添加字段的答案。它很有效,因为这是解决它的标准方法。但是,现在您还希望确保进行特定的自定义。这就是自然的发展过程。一个问题可能会导致另一个问题。欢迎您使用您认为适合的任何功能组合,例如fieldslist_displayfieldsetsordering,...甚至其他策略,或者如果您不这样做,请提出不同的问题不知道怎么做。
    • 实际上,我之前尝试过fieldsets,但在密码字段方面遇到了同样的问题,所以如果你也看一下,我很感激:stackoverflow.com/questions/73816296/…
    【解决方案2】:

    用户模型扩展与继承。

    您的个人资料模型仅向用户添加一些元素。在这种情况下,模型继承会更好。

    # models.py
    class Profile(user):
        verified = models.BooleanField(default=False)
    

    之后,您可以实现用户和配置文件的所有字段:

    # admin.py
    class ProfileAdmin(ModelAdmin):
        fields = '__all__'
    

    如果您不想打开模型继承。

    您可以在 UserAdmin 中使用 InlineModel 来更改相关模型。

    # admin.py
    class ProfileInline(StackedInline):
        model=Profile
    
    class UserAdmin(ModelAdmin):
        inlines = (ProfileInline, )
    

    【讨论】:

    • 我更新了我的问题。顺便说一句,fileds = '__all__' 在这里不起作用。
    【解决方案3】:

    您可以使用模型 Django 中的覆盖 AbstractUser ,这样您就可以将用户合并到一个地方,如下所示:

    
    from django.contrib.auth.models import AbstractUser
    from django.db import models
    
    class CustomUser(AbstractUser):
       verified = models.BooleanField(default=False)
    
    

    您需要将此行添加到 Django settings.py 文件中,以便 Django 知道使用新的 User 类:

    
    AUTH_USER_MODEL = 'users.CustomUser'
    
    

    然后确保迁移:

    
    (env)$ python manage.py makemigrations
    (env)$ python manage.py migrate
    

    【讨论】:

    • 所以你的意思是如果我覆盖 AbstractUser,verified 字段会以某种方式出现在管理站点中?不,它没有。
    • @OmidShojaee,是的,它会显示,尝试一下并返回这里,以便您可以删除此评论或修改它。
    猜你喜欢
    • 2012-10-12
    • 2023-03-25
    • 2012-04-15
    • 2016-02-18
    • 2016-03-08
    • 1970-01-01
    • 1970-01-01
    • 2014-09-09
    • 1970-01-01
    相关资源
    最近更新 更多