【问题标题】:Is there a way to turn on/off a particular field from Django admin?有没有办法从 Django 管理员打开/关闭特定字段?
【发布时间】:2021-12-26 18:53:48
【问题描述】:

我想在我的 Django 管理仪表板中实现一个设置,我可以在其中禁用/启用特定字段。如果我应该禁用该字段,该字段中的数据将不会呈现在网页上。如果我应该启用该字段,那么数据将显示在网页中。我只想从我的管理仪表板执行此操作。

这是我的models.py

class Product(models.Model):
    category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
    name = models.CharField(max_length=100, unique=True)
    slug = models.SlugField(max_length=100, unique=True)
    image = models.ImageField(upload_to='products/')
    description = models.TextField()
    quantity = models.CharField(max_length=10)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    available = models.BooleanField(default=True)

这是admin.py

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = ('name', 'category', 'slug', 'price', 'available')
    list_filter = ('category', 'available')
    list_editable = ('price', 'available')
    prepopulated_fields = {'slug': ('name',)}

我希望能够从我的管理仪表板启用/禁用(可能像一个切换按钮)description 字段。有没有办法在我的admin.py 文件中实现这一点?我该怎么办?谢谢。

编辑:为了更好地理解(正如评论所建议的那样),我想在管理仪表板中实现一个主切换,它可以打开/关闭向用户显示的每个实例的所有描述。

【问题讨论】:

  • 这似乎有点不清楚。您是否想切换该字段在 Django 管理中是否像折叠元素一样可见,或者您是否想要模型上的一个额外字段来确定用户是否可以在您的 HTML 模板中看到该实例的描述,或者您想要关闭向用户显示的每个实例的所有描述的主开关?
  • 我也不清楚。如果您想在访问此仪表板时在仪表板上隐藏/显示,那么也许您应该使用 JavaScript 切换 HTML 并将此开始保存在 cookie 中。如果您想在其他用户访问页面时使用仪表板将其隐藏,那么它可能需要其他表进行设置,并且在为其他用户呈现 HTML 时需要使用这些设置。
  • @Jacinator 您评论的后半部分正是我想要实现的。管理仪表板中的主开关,用于打开/关闭向用户显示的每个实例的所有描述。

标签: python django django-models django-admin


【解决方案1】:

你可以这样做:

首先,将此字段添加到您的models.py

is_description = models.BooleanField(default=True)

然后进行迁移:

python manage.py makemigrations
python manage.py migrate

然后您可以将以下自定义添加到您的admin.py

  • 覆盖get_urls 方法并在模型管理员上添加enable_descriptiondisable_discription 方法。它们将用作两种视图方法:

      def get_urls(self):
          urls = super().get_urls()
          my_urls = [ 
              path('descriptionon/', self.enable_description),
              path('descriptionoff/',self.disable_discription),
          ]
          return my_urls + URLs 
    
      def enable_description(self, request):
          self.model.objects.all().update(is_description=True)
          self.message_user(request, "All descriptions are now turned on")
          return HttpResponseRedirect("../") 
    
      def disable_description(self, request):
          self.model.objects.all().update(is_description=False)
          self.message_user(request, "All descriptions are now turned on")
          return HttpResponseRedirect("../")
    

接下来,您需要通过创建模板文件product_changelist.html 来覆盖您的 Django 管理模板,然后扩展 admin/change_list.html

{% extends 'admin/change_list.html' %}

{% block object-tools %}
    <div>
        <form action="descriptionoff/" method="POST">
            {% csrf_token %}
                <button type="submit">Turn description on</button>
        </form>
        <form action="descriptionoff/" method="POST">
            {% csrf_token %}
                <button type="submit">Turn description off</button>
        </form>
    </div>
    <br />
    {{ block.super }}
{% endblock %}

访问您的 Product 模型的管理仪表板。您现在应该会看到搜索栏上方的两个按钮。

最后,在你的views.py 中添加这个逻辑:

def product_list(request):
    products = Product.objects.all()
    for product in products.iterator():    
    if product.is_description:
        return render(request,
                      'product_list.html',
                      {'product': products})
    disable_descp = product.__class__.objects.all().values('category', 'name', 'image',...)

    return render(request,
                  'product_list.html',
                  {'product': disable_descp})

当您在管理仪表板中单击 Turn description on 并刷新您的模板页面时,描述将可用。如果您在管理仪表板中单击 Turn description off,它将不可用。

【讨论】:

    【解决方案2】:

    Django constance(与我没有关联)可能会做你想做的事。它不一定以任何方式存储您描述的与您的模型相关联的切换,但它允许您拥有可编辑的设置。这可以在您的表单定义中使用,也可以通过视图或context processor 传递给您的上下文。

    【讨论】:

      【解决方案3】:

      有几种方法可以做到这一点。

      1 管理员用户权限。 2 bool 显示或不显示对象。 3 新的管理员视图。

      1

      您可以添加查看此字段的权限并在 admin.py 中创建一个方法以查看它或根据权限值返回 None。

      在admin.py中

      class YourAdminClass(admin.ModelAdmin)
          def get_queryset(self, request):
               queryset= super(YourAdminClass, self).get_queryset(request)
               self.request = request
               return queryset 
      
          def mobile_phone(self, obj):
              return obj.user.mobile_phone if self.request.user.has_special_permission else None
      

      2

      您可以向对象添加布尔值而不是用户权限(在管理员中显示或不显示)并更改选项 1 中的查询集(这样您可以从客户端 FE 控制它)

      def get_queryset(self, request):
          qs = super(YourAdminClass, self).get_queryset(request)
          return qs.filter(SHOW_MY_FIELD=True)
      

      3

      创建新的管理视图 NoFieldAdmin 和 Admin 的替代品,并通过管理 url 在主管理中显示或不显示链接 在主 admin.py 文件中

      class NoFieldAdminSite(AdminSite):
          pass
          #or overwrite some methods for different functionality
      
      NoFieldAdmin= NoFieldAdminSite(name="nofield_admin")   
      
      in urls.py
              urlpatterns = [
                  url(r'^admin/', admin.site.urls),
                  url(r'^NOFIELD-admin/', NoFieldAdmin.urls),
      

      【讨论】:

      • 谢谢你,但这不会影响前端。数据仍在前端反映。我该如何做到这一点,以便管理员中的更改也将反映在模板中,而无需编辑模板或视图?
      • JS - 但它可以被管理员用户破解...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-11
      • 2017-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多