django - 在 django admin 中使用按钮调用函数

标签 django

我在 models.py 中有一个 python 类:

class Scenario(TemporalObject):
    name = models.CharField(max_length=200)
    user = models.CharField(max_length=200)
    start = models.DateTimeField(default=django.utils.timezone.now)
    end = models.DateTimeField(default=django.utils.timezone.now)

    def nb_hours(self):
        """Compute the number of hours between start and end"""
        return (int((self.end - self.start).total_seconds() // 3600))+1

    def activate_button(self):
        return format_html(
            '''<form action="activate/" method="POST">
                   <button type="submit"> Activate </button>
                </form>''')
    

和相应的

class ScenarioAdmin(admin.ModelAdmin):
    list_display = ("name", "user", "start", "end", "nb_hours","activate_button")

我想通过使用 activate_button 创建的按钮调用函数。我该怎么办?

我想要的功能就像一个旧 Action :

def make_active(scenario_admin, request, queryset):
    if len(queryset) == 0:
        logger.info("No scenario selected when activating one of them")
        return
    if len(queryset) > 1:
        msg = "Can't activate more than one scenario at a time."
        msg += " Please select only one scenario."
        scenario_admin.message_user(request, msg, level=messages.ERROR)
        return
    # Get the scenario to activate
    target = queryset[0]
    # It is already activated
    if target.user == request.user.username:
        msg = "Scenario already active"
        scenario_admin.message_user(request, msg, level=messages.WARNING)
        return
    if target.user is not None and len(target.user) > 0:
        msg = f"Can't activate scenario '{target}'"
        msg += f" because it is active for user '{target.user}'"
        scenario_admin.message_user(request, msg, level=messages.ERROR)
        return
    # Deactivate all other scenarios that are active
    for scenario in Scenario.objects.filter(user=request.user.username):
        scenario.user = ""
        scenario.save()
    # Activate the scenario
    target.user = request.user.username
    target.save()
    msg = f"Activated scenario '{target}'"
    scenario_admin.message_user(request, msg, level=messages.INFO)

我应该在类 Scenario 中用 self 替换 queryset[0]

最佳答案

您可以使用 get_urls method并创建 ScenarioAdmin 的自定义 View 方法。

模型.py:

from django.utils.html import format_html
from django.urls import reverse_lazy

class Scenario(TemporalObject):
    ...

    def activate_button(self):
        return format_html('<a href="{}" class="link">Activate</a>',
            reverse_lazy("admin:admin_activate_scenario", args=[self.pk])
        )

admin.py:

from django.template.response import TemplateResponse
from django.urls import path
from django.shortcuts import redirect, get_object_or_404


class ScenarioAdmin(admin.ModelAdmin):
    list_display = (
        "name", "user", "start", 
        "end", "nb_hours", "activate_button")

    def get_urls(self):
        urls = super().get_urls()
        my_urls = [
            path('activate-scenario/<int:pk>/', self.acitvate_scenario, name="admin_activate_scenario"),
        ]
        return my_urls + urls

    def acitvate_scenario(self, request, pk):
        # ...
        context = dict(
           # Include common variables for rendering the admin template.
           self.admin_site.each_context(request),
           # Anything else you want in the context...
        )

        # Get the scenario to activate
        target = get_object_or_404(Scenario, pk=pk)
        # It is already activated
        if target.user == request.user.username:
            msg = "Scenario already active"
            self.message_user(request, msg, level=messages.WARNING)
            return redirect(request.META.get('HTTP_REFERER'))
        if target.user is not None and len(target.user) > 0:
            msg = f"Can't activate scenario '{target}'"
            msg += f" because it is active for user '{target.user}'"
            self.message_user(request, msg, level=messages.ERROR)
            return redirect(request.META.get('HTTP_REFERER'))
        # Deactivate all other scenarios that are active
        for scenario in Scenario.objects.filter(user=request.user.username):
            scenario.user = ""
            scenario.save()
        # Activate the scenario
        target.user = request.user.username
        target.save()
        msg = f"Activated scenario '{target}'"
        self.message_user(request, msg, level=messages.INFO)

        # redirect or TemplateResponse(request, "sometemplate.html", context)
        return redirect(request.META.get('HTTP_REFERER'))

关于django - 在 django admin 中使用按钮调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66318063/

相关文章:

python - 如何防止 mod_wsgi Django 应用程序重复重新加载?

python - Django 模型查询使用 join

jquery - django csrf 在生产服务器上失败

python - Django - ModelForm 到模板不提交数据

python - Django:有什么办法可以删除这个清晰的字段?

Django,如何在没有 for 循环的情况下解析单个表单字段(HTML)

python - 在我的 Web 应用程序中为架构做 302 是否可以?

sql - Django 中大表的内存效率(常数)和速度优化迭代

python - 如何使用 Django mptt 查询节点的所有子节点的对象?

python - 如何使用 django/python 从网络服务获取返回值