繁体   English   中英

在“管理员更改表单”中,如何访问模型的当前实例?

[英]How can I access the current instance of my model when in the Admin Change Form?

我正在尝试为想要跟踪销售的发布者创建一个数据管理系统。 我有一个用于书店的模型,该模型存储着出版商的书籍,其中包括每个商店的状态字段(来自状态模型)。 状态可能是“未设置”,“收到订单”或“回叫”之类的内容。

除了能够查看当前状态外,客户还希望能够在检查“管理员更改表格”上的书店数据时查看给定商店的状态更改:状态本身,状态的日期和时间更改,进行更改的用户以及有关更改的一些评论。 因此,我创建了一个状态更改模型来存储此数据,并添加了一个内联。

在书店的管理员更改表单中,我禁用了状态字段(以防止用户更改状态而不创建状态更改记录),并添加了“更改状态”链接,该链接将用户带到允许他们创建新表单的表单状态更改记录。 我一直无法解决的问题是:如何访问当前的书店实例,以便可以将商店ID及其当前状态传递到更改状态表单?

我可以获取用户的ID,而该请求没有任何问题。 我可以使用self.model.objects.first()获取数据库中第一个书店的ID,但是当“更改状态”链接时,我无法找到一种方法来获取正在查看的书店的ID。被点击。

在models.py中:

from django.contrib.auth import get_user_model
from django.db import models
from datetime import datetime


class Status(models.Model):
    DEFAULT_PK = 1
    status_name = models.CharField(max_length=255)


class Bookstore(models.Model):
    store_code = models.CharField(max_length=255)
    store_name = models.CharField(max_length=255)
    address = models.CharField(max_length=255, null=True, blank=True)
    phone_number = models.CharField(max_length=255, null=True, blank=True)
    description = models.CharField(max_length=1024, null=True, blank=True)
    status = models.ForeignKey(Status, on_delete=models.SET_DEFAULT, default=Status.DEFAULT_PK)


class StatusChange(models.Model):
    date_time = models.DateTimeField(default=datetime.now)
    user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
    bookstore = models.ForeignKey(Bookstore, on_delete=models.CASCADE)
    status = models.ForeignKey(Status, on_delete=models.CASCADE)
    notes = models.TextField()

在admin.py中:

from django.contrib import admin
from django.urls import path
from django.shortcuts import render
from django.utils.safestring import mark_safe
from django.forms.models import BaseInlineFormSet
from .models import Status, Bookstore, StatusChange
from .forms import StatusChangeForm


class StatusChangeFormSet(BaseInlineFormSet):
    def get_queryset(self):
        qs = super(StatusChangeFormSet, self).get_queryset()
        return qs[:5]


class StatusChangeInline(admin.TabularInline):
    model = StatusChange
    formset = StatusChangeFormSet
    fields =  ('date_time', 'user', 'status', 'notes')
    readonly_fields = ('date_time', 'user', 'status')
    can_delete = False
    max_num = 0
    ordering = ('-date_time',)


class BookstoreAdmin(admin.ModelAdmin):
    model = Bookstore
    list_display = ('id', 'store_code', 'store_name', 'status')
    list_display_links = ('id', 'store_code', 'store_name')
    ordering = ('id', )
    fields =('store_code', 'store_name', 'address', 'phone_number', 'description', 'status')
    inlines = [StatusChangeInline, ]

    # Disable the status field except if we are creating a new bookstore
    def get_readonly_fields(self, request, obj=None):
        if obj:
            return self.readonly_fields + ('status',)
        return self.readonly_fields

    def get_urls(self):
        urls = super().get_urls()
        my_urls = [path('statuschange/', self.change_store_status, name='statuschange'), ]
        return my_urls + urls

    def change_store_status(self, request):
        if request.method == 'POST':
            pass

        obj = self.model.objects.first()
        store_id = getattr(obj, 'id')
        store_status = getattr(obj, 'status')
        form = StatusChangeForm(
            initial={'user': request.user, 'bookstore': store_id, 'status': store_status}
        )
        payload = {"form": form}
        return render(request, "admin/change_status.html", payload)

admin.site.register(Bookstore, BookstoreAdmin)

当然,这会将用户带到允许他们更改数据库中第一个书店的状态的表格!

目前,您可以通过书店更改路径,例如:
/admin/<app_name>/bookstore/<pk>/change/
我建议您保留此url配置并为statuschange创建url,例如:
/admin/<app_name>/bookstore/<pk>/statuschange/

假设您的StatusChangeForm为:

class StatusChangeForm(forms.ModelForm):
    class Meta:
        model = models.StatusChange
        fields = ['user', 'bookstore', 'status',]

因此,为此,您需要调整get_urls()以接受bookstore pk

def get_urls(self):
        urls = super().get_urls()
        my_urls = [path('<int:pk>/statuschange/', self.change_store_status, name='statuschange'), ]
        return my_urls + urls

并修改您的change_store_status()以接收该pk并在获取bookstore实例时使用它:

def change_store_status(self, request, pk):
        obj = self.model.objects.get(pk=pk)

        store_id = getattr(obj, 'id')
        store_status = getattr(obj, 'status')
        form = forms.StatusChangeForm(request.POST or None,
            initial={'user': request.user, 'bookstore': store_id, 'status': store_status}
        )

        if request.method == 'POST':
            if form.is_valid():
                form.save()

        payload = {"form": form}
        return render(request, "admin/change_status.html", payload)

另外,您还必须在书店更改模板中提供pk以指导用户正确填写表格,例如:
{% url 'admin:statuschange' pk=original.pk %}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM