我在 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/