Django对单个对象的管理操作

Django对单个对象的管理操作,django,django-admin,Django,Django Admin,管理操作似乎适用于管理界面列表视图中选定的几个项目: 在我的例子中,我希望在ChangeOne item视图上有一个简单的操作按钮 有没有办法让django管理操作在那里可用 我知道我可以通过转到列表视图并在那里选择一个项目来解决这个问题。但是如果能直接使用它会更好。如果您确实需要每个对象,我建议您使用此解决方案,例如: class Gallery(TimeStampedModel): title = models.CharField(max_length=200) attach

管理操作似乎适用于管理界面列表视图中选定的几个项目:

在我的例子中,我希望在ChangeOne item视图上有一个简单的操作按钮

有没有办法让django管理操作在那里可用


我知道我可以通过转到列表视图并在那里选择一个项目来解决这个问题。但是如果能直接使用它会更好。

如果您确实需要每个对象,我建议您使用此解决方案,例如:

class Gallery(TimeStampedModel):
    title = models.CharField(max_length=200)
    attachment = models.FileField(upload_to='gallery/attachment/%Y/%m/%d')

    def __str__(self):
        return self.title

    def process_button(self):
        return ('<button id="%(id)s class="btn btn-default process_btn" '
                'data-value="%(value)s>Process</button>' % {'id': self.pk, 'value': self.attachment.url})
    process_button.short_description = 'Action'
    process_button.allow_tags = True
然后,在yourfile.js中,您还可以处理它

$('.process_btn').click(function(){
    var id = $(this).attr('id');       // single object id
    var value = $(this).data('value'); // single object value
    ...
});

希望对您有所帮助。

在应用程序中为您的模型创建模板

templates/admin/<yourapp>/<yourmodel>/change_form.html
使用此示例,可以在更改现有对象时添加按钮

{% extends "admin/change_form.html" %}
{% block submit_buttons_bottom %}
    {{ block.super }}
    {% if original %} {# Only show if changing #}
        <div class="submit-row">
            <a href="{% url 'custom-model-action' original.pk %}">
                 Another action
            </a>
        </div>
    {% endif %}
{% endblock %}
将该操作链接到任何url并重定向回模型更改对象视图

更新:为现有对象上的自定义操作添加了完整的通用用例

url.py

views.py


内置的管理操作在queryset上操作

您可以将calable用于所需的操作或显示其他内容:

class ProductAdmin(admin.ModelAdmin):
    list_display ('name' )
    readonly_fields('detail_url)


def detail_url(self, instance):
    url = reverse('product_detail', kwargs={'pk': instance.slug})
    response = format_html("""<a href="{0}">{0}</a>""", product_detail)
    return response
或者使用表单

class ProductForm(forms.Form):
    name = forms.Charfield()

    def form_action(self, product, user):
        return Product.value(
            id=product.pk,
            user= user,
        .....

        )


@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):

# render buttons and links to
def product_actions(self, obj):
        return format_html(
            '<a class="button" href="{}">Action1</a>&nbsp;'
            '<a class="button" href="{}">Action 2</a>',
            reverse('admin:product-action-1', args=[obj.pk]),
            reverse('admin:aproduct-action-3', args=[obj.pk]),
        )

与初学者询问的主题不同,但此代码段允许在列表页面上以最少的代码执行单个对象操作

基本动作码

自定义操作[最小代码量]

管理类

您错过了django.url导入反向
from django.urls import reverse
from django.contrib import messages
from django.http import HttpResponse, HttpResponseRedirect

def custom_model_action(request, object_pk):
    messages.info(request, 'Performed custom action!')
    return HttpResponseRedirect(
       reverse('admin:<yourapp>_<yourmodel>_change', args=[object_pk])
    )
class ProductAdmin(admin.ModelAdmin):
    list_display ('name' )
    readonly_fields('detail_url)


def detail_url(self, instance):
    url = reverse('product_detail', kwargs={'pk': instance.slug})
    response = format_html("""<a href="{0}">{0}</a>""", product_detail)
    return response
class ProductForm(forms.Form):
    name = forms.Charfield()

    def form_action(self, product, user):
        return Product.value(
            id=product.pk,
            user= user,
        .....

        )


@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):

# render buttons and links to
def product_actions(self, obj):
        return format_html(
            '<a class="button" href="{}">Action1</a>&nbsp;'
            '<a class="button" href="{}">Action 2</a>',
            reverse('admin:product-action-1', args=[obj.pk]),
            reverse('admin:aproduct-action-3', args=[obj.pk]),
        )
class AdminActionError(Exception):
    pass


class AdminObjectAction:
    """Base class for Django Admin actions for single object"""

    short_description = None
    exp_obj_state = {}

    def __init__(self, modeladmin, request, queryset):
        self.admin = modeladmin
        self.request = request
        self.queryset = queryset
        self.__call__()

    def validate_qs(self):
        count = self.queryset.count()
        if count != 1:
            self.error("You must select one object for this action.")

        if self.exp_obj_state:
            if self.queryset.filter(**self.exp_obj_state).count() != 1:
                self.error(f'Selected object does not meet the requirements: {self.exp_obj_state}')

    def error(self, msg):
        raise AdminActionError(msg)

    def get_object(self):
        return self.queryset.get()

    def process_object_action(self, obj):
        pass

    def validate_obj(self, obj):
        pass

    def __call__(self, *args, **kwargs):
        try:
            self.validate_qs()
            obj = self.get_object()
            self.validate_obj(obj)
        except AdminActionError as e:
            self.admin.message_user(self.request, f"Failed: {e}", level=messages.ERROR)
        else:
            with transaction.atomic():
                result = self.process_object_action(obj)

            self.admin.message_user(self.request, f"Success: {self.short_description}, {result}")

class RenewSubscriptionAction(AdminObjectAction):
    short_description = 'Renew subscription'

    exp_obj_state = {
        'child': None,
        'active_status': True,        
    }

    def process_object_action(self, obj):
        manager = RenewManager(user=obj.user, subscription=obj)
        return manager.process()

class SomeAdmin(admin.ModelAdmin):
    actions = [RenewSubscriptionAction]