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

2024-06-06 05:39:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我正试图创建一个数据管理系统的出版商想要跟踪销售。我有一个存储出版商书籍的书店模型,其中包括每个书店的状态字段(来自状态模型)。状态可以是“未设置”、“已收到订单”或“回电”。你知道吗

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

在书店的AdminChange表单中,我禁用了status字段(防止用户在不创建状态更改记录的情况下更改状态),并添加了一个“ChangeStatus”链接,该链接将用户带到一个表单,允许他们创建一个新的状态更改记录。我一直无法解决的问题是:如何访问当前的书店实例,以便将store id及其当前状态传递给change status表单?你知道吗

我可以从请求中获得用户的id,而没有任何问题。我可以使用self.model.objects对象.first(),但在单击“更改状态”链接时,我无法找到获取正在查看的书店id的方法。你知道吗

在型号.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()

在管理员.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)

这当然会将用户带到允许他们更改状态的窗体。。。数据库中的第一家书店!你知道吗


Tags: djangostorefromimportselfidgetmodel
1条回答
网友
1楼 · 发布于 2024-06-06 05:39:50

目前,您可以更改如下路径:
/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()以接受pkbookstore

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 %}。你知道吗

相关问题 更多 >