【问题标题】:Filter related values from Django Admin M2M relation从 Django Admin M2M 关系中过滤相关值
【发布时间】:2021-05-14 06:51:38
【问题描述】:

是否可以在 Django admin 中过滤相关值?我有多对多关系设置为内联显示。 但是有很多值,所以我希望能够以某种方式搜索/过滤我需要的值。

所以这里有两个模型(我用的是 Join 表):

# Create your models here.
class Country(models.Model):
    name = models.CharField(max_length=100, unique=True, verbose_name='Country')

    class Meta:
        verbose_name_plural = "Countries"

    def __str__(self):
        return self.name

class OpenDestination(models.Model):
    name = models.CharField(max_length=100, unique=True, verbose_name='Country')
    origin_country = models.ManyToManyField(Country, through='BorderStatus')

    def __str__(self):
        return self.name

class BorderStatus(models.Model):
    STATUS_CHOICES = [
        ('OP', 'OPEN'),
        ('SEMI', 'CAUTION'),
        ('CLOSED', 'CLOSED')
    ]
    Country = models.ForeignKey(Country, on_delete=models.CASCADE)
    OpenDestination = models.ForeignKey(OpenDestination, on_delete=models.CASCADE)
    status = models.CharField(max_length=6, choices=STATUS_CHOICES, default='CLOSED')

    class Meta:
        unique_together = (('Country', 'OpenDestination'))

    def __str__(self):
        return str(self.Country) + ' and ' + str(self.OpenDestination)

admin.py

class OpenDestinationInline(admin.TabularInline):
    model = OpenDestination.origin_country.through

class ConutryAdmin(admin.ModelAdmin):
    inlines = [
        OpenDestinationInline
    ]
    filter_horizontal = ('origin_country',)


admin.site.register(Country, ConutryAdmin)
admin.site.register(OpenDestination)
admin.site.register(BorderStatus)

所以现在当我从Country 模型访问一个国家时,我会看到来自OpenDestination 模型的许多国家的列表(由于加入表,每个国家都有自己的状态)。现在我试图弄清楚从“国家”访问单个国家时是否可以从“OpenDestination”中过滤国家。

我尝试将 filter_vertical/horizo​​ntal filter_vertical = ('name',) 添加到 CountryAdmin 但出现错误:

The value of 'filter_vertical[0]' must be a many-to-many field.

【问题讨论】:

  • 我认为autocomplete fields 更适合解决这个问题。
  • 当我将 filter_vertical 更改为 autocomplete_fields 时出现同样的错误

标签: django django-models django-rest-framework


【解决方案1】:

所以您的数据模型没有多大意义。我稍微改写了一下,我认为的意图是:可以从不同来源(也是国家)到达的目的地(国家)。

数据模型:

from django.db import models


class Country(models.Model):
    name = models.CharField(max_length=100, unique=True, verbose_name="Country")

    class Meta:
        verbose_name_plural = "Countries"

    def __str__(self):
        return self.name


class Destination(models.Model):
    destination = models.ForeignKey(
        Country, on_delete=models.CASCADE, related_name="destinations"
    )
    origin_countries = models.ManyToManyField(
        Country, related_name="origins", through="BorderStatus"
    )

    def __str__(self):
        return self.destination.name


class BorderStatus(models.Model):
    STATUS_CHOICES = [("OP", "OPEN"), ("SEMI", "CAUTION"), ("CLOSED", "CLOSED")]
    destination = models.ForeignKey(Destination, on_delete=models.CASCADE)
    origin_country = models.ForeignKey(Country, on_delete=models.CASCADE)
    status = models.CharField(max_length=6, choices=STATUS_CHOICES, default="CLOSED")

    class Meta:
        unique_together = [("origin_country", "destination")]

    def __str__(self):
        return (
            f"{self.origin_country.name} -> {self.destination.destination.name}"
            f" ({self.status})"
        )

现在对我来说更有意义的管理员是 Destination 模型:它定义了您可以从哪个国家/地区到达那里。它看起来像这样:

此处的所有国家/地区选择都是自动填充字段。

所以我们得到了这个管理员代码:

from django.contrib import admin
from . import models


class BorderStatusInline(admin.TabularInline):
    model = models.BorderStatus
    autocomplete_fields = ("origin_country",)


@admin.register(models.Destination)
class OpenDestinationAdmin(admin.ModelAdmin):
    inlines = [BorderStatusInline]
    autocomplete_fields = ("destination",)


@admin.register(models.Country)
class CountryAdmin(admin.ModelAdmin):
    search_fields = ("name",)
    ordering = ("name",)

【讨论】:

  • 实际上我的想法相反,所以我试图创建一个模型,其中原产国有对他们开放的目的地列表,实际上你的解决方案就是这样但相反的方式(除非我失踪某物?)。非常感谢,我现在将使用您的建议来改进自动填充字段。
猜你喜欢
  • 2015-12-23
  • 2020-04-13
  • 2016-05-07
  • 2012-02-29
  • 2021-04-21
  • 1970-01-01
  • 2011-02-05
  • 1970-01-01
  • 2012-05-16
相关资源
最近更新 更多