简体   繁体   English

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

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

I am trying to customise the Django admin add/change for a project.我正在尝试为项目自定义 Django 管理员添加/更改。 I have created a model called "Visit" which contains 3 Foreign Key fields: "Customer", "Pet" and "Doctor".我创建了一个名为“访问”的 model,其中包含 3 个外键字段:“客户”、“宠物”和“医生”。 The workflow is as follows:工作流程如下:

  • The user creates a customer.用户创建客户。
  • The user creates a pet and associates it with a customer.用户创建宠物并将其与客户相关联。
  • The user creates a visit and associates it with a pet and a doctor.用户创建访问并将其与宠物和医生相关联。

Below is the code for my models.py下面是我的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',)

My issue is that someone using the Django Admin to create a Visit can wrongly choose a Customer and Pet.我的问题是使用 Django 管理员创建访问的人可能会错误地选择客户和宠物。 Hence, the Customer does not own that Pet.因此,客户不拥有该宠物。 I would like to know how can I customise the Django Admin, so that, when the user selects a Customer, only Pets under that particular Customer is displayed in the selectbox.我想知道如何自定义 Django 管理员,以便当用户选择客户时,选择框中仅显示该特定客户下的宠物。

Below is my admin.py下面是我的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)

i faced the same issue, in my case i use raw_id_field for my foreign keys and many to many fields in ModelAdmin And override add and change template.我遇到了同样的问题,在我的情况下,我使用raw_id_field作为我的外键和 ModelAdmin 中的多对多字段并覆盖添加和更改模板。

you can use raw_id_field for forign keys and in your templates write javascript to change href of search icon for Pet foreign key field when Customer id field changed, and in href use url lookup to show only Pet which belongs to selected Customer您可以将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),)

and in my template i use javascript to change the href of FeatureOption search icon for url lookup在我的模板中,我使用 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