繁体   English   中英

在 Django 管理员添加/更改表单中获取外键数据

[英]Getting Foreign Key data in Django Admin Add/Change Form

我正在尝试为项目自定义 Django 管理员添加/更改。 我创建了一个名为“访问”的 model,其中包含 3 个外键字段:“客户”、“宠物”和“医生”。 工作流程如下:

  • 用户创建客户。
  • 用户创建宠物并将其与客户相关联。
  • 用户创建访问并将其与宠物和医生相关联。

下面是我的models.py的代码

class Visit(models.Model):
    customer = models.ForeignKey('customer.Customer', on_delete=models.CASCADE)
    pet = models.ForeignKey('pet.Pet', on_delete=models.CASCADE)
    date = models.DateTimeField()
    doctor = models.ForeignKey(
        'configuration.Doctor', on_delete=models.DO_NOTHING, null=True, blank=True)
    status = models.CharField(
        choices=PET_STATUS, max_length=3, null=True, blank=True)
    reason = models.CharField(max_length=255)
    diagnosis = models.TextField(null=True, blank=True)
    treatment = models.TextField(null=True, blank=True)
    comment = models.TextField(null=True, blank=True)
    prescription = models.TextField(null=True, blank=True)
    weight = models.DecimalField(
        max_digits=6, decimal_places=2, null=True, blank=True)

    class Meta:
        ordering = ('-date',)

我的问题是使用 Django 管理员创建访问的人可能会错误地选择客户和宠物。 因此,客户不拥有该宠物。 我想知道如何自定义 Django 管理员,以便当用户选择客户时,选择框中仅显示该特定客户下的宠物。

下面是我的admin.py

class VisitAdmin(admin.ModelAdmin):
    change_form_template = 'visit/invoice_button.html'
    add_form_template = 'visit/add_visit.html'

    list_display = ('customer', 'pet', 'date', 'status')
    list_filter = ('date', 'customer', 'pet', 'status')
    search_fields = ('customer__first_name',
                     'customer__last_name', 'pet__pet_name')
    autocomplete_fields = ['customer', 'pet', 'doctor']
    radio_fields = {'status': admin.HORIZONTAL}
    fieldsets = (
        (None, {
            "fields": ('customer', 'pet', 'doctor'),
        }),
        ("Visit Details", {
            "fields": ('date', 'reason', 'weight', 'status'),
        }),
        ("Visit Outcome", {
            "fields": ('diagnosis', 'treatment', 'comment')
        })
    )
    inlines = [FeeInLine, AttachmentInLine]

    actions = ['export_as_csv']

    def export_as_csv(self, request, queryset):

        meta = self.model._meta
        field_names = [field.name for field in meta.fields]

        response = HttpResponse(content_type='text/csv')
        response['Content-Disposition'] = 'attachment; filename={}.csv'.format(
            meta)
        writer = csv.writer(response)

        writer.writerow(field_names)
        for obj in queryset:
            row = writer.writerow([getattr(obj, field)
                                   for field in field_names])

        return response

    export_as_csv.short_description = "Export Selected"

    def response_change(self, request, obj):
        if "invoice" in request.POST:
            return render_pdf(request, obj.pk)
        return super().response_change(request, obj)


admin.site.register(Visit, VisitAdmin)

我遇到了同样的问题,在我的情况下,我使用raw_id_field作为我的外键和 ModelAdmin 中的多对多字段并覆盖添加和更改模板。

您可以将raw_id_field用于外键,并在模板中编写 javascript 以在Customer id 字段更改时更改Pet外键字段的搜索图标的href ,并在href中使用 url 查找以仅显示属于所选CustomerPet

# stock/models.py

class Category(models.Model):
    title = models.CharField(max_length=255, blank=True)
    is_active = models.BooleanField(default=True)


class Product(models.Model):

    category = models.ForeignKey(
        Category, on_delete=models.PROTECT, related_name="product"
    )

    feature_option = models.ManyToManyField("FeatureOption", blank=True, related_name="product")


class Feature(models.Model):
    title = models.CharField(max_length=255, blank=True)
    category = models.ManyToManyField(Category, blank=True, related_name="feature")


class FeatureOption(models.Model):
    title = models.CharField(max_length=255, blank=True)
    feature = models.ForeignKey(
        Feature, on_delete=models.CASCADE, related_name="feature_option"
    )


# stock/admin.py

class CategoryAdmin(admin.ModelAdmin):
    raw_id_fields = ['parent']


class ProductAdmin(admin.ModelAdmin):
    add_form_template = 'admin/product_add_form.html'
    change_form_template = 'admin/product_change_form.html'
    raw_id_fields = ['category', "feature_option"]


class FeatureOptionAdmin(admin.ModelAdmin):
    list_filter = (("feature__category", admin.RelatedOnlyFieldListFilter),)

在我的模板中,我使用 javascript 更改 url 查找的FeatureOption搜索图标的href

<!-- product_add_form.html -->

{% extends "admin/change_form.html" %}
{% load i18n %}


{% block admin_change_form_document_ready %} {{ block.super }}
    <script lang="text/javascript">
        function changeFeatureOptionPopupUrl() {
            const featureOptionBaseUrl = "/admin/stock/featureoption/";
            let categoryTextBox = document.getElementById("id_category");
            document.getElementById("lookup_id_feature_option").href = featureOptionBaseUrl + "?feature__category__id__exact=" + categoryTextBox.value;
        }
        document.getElementById("lookup_id_feature_option").onfocus = function () {changeFeatureOptionPopupUrl()}
    </script>
{% endblock %}

暂无
暂无

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

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