Skip to main content
 首页 » 编程设计

python之Django Admin 仅按反向外键查找中的第一个对象按功能/过滤器过滤

2025年04月02日33pengyingh

我正在尝试在 Django 中按函数构建过滤器。根据我通过谷歌搜索了解到的情况,这是很难实现的。

这是我的代码:

class TrackingEventType(models.Model): 
    name = models.CharField(blank=False, null=False, max_length=255) 
 
class TrackingEvent(models.Model):     
    datetime = models.DateTimeField(blank=False, null=False, default=datetime.now, verbose_name="Zeitpunkt")     
    event_type = models.ForeignKey(TrackingEventType, help_text="Art des Events")     
    tracking = models.ForeignKey('Tracking')     
 
    class Meta: 
        ordering = ['-datetime'] 
 
 
class Tracking(models.Model): 
    tracking_no = models.CharField(blank=False, null=False, max_length=10, unique=True, verbose_name="Tracking Nummer") 
 
    def get_last_event(self): 
        """ 
        Todo: return the latest event. 
        """ 
        return TrackingEvent.objects.filter(tracking=self.id).first() 
    get_last_event.short_description = 'Last event' 
 
    class Meta: 
        ordering = ['-tracking_no'] 

我的目标是可以通过最近的事件类型名称过滤跟踪对象。在 django admin 中显示函数的结果很容易,但添加相应的过滤器却不是。

我的想法也是尝试构建一个类似于以下内容的过滤器:

trackingevent__set__first__event_type__name 

但是,是的,那太容易了:)

欢迎任何意见。

请您参考如下方法:

如您所见,以这种方式进行过滤并非易事。如果您定期访问该信息,它可能也不是很有效。

我建议您在 Tracking 模型本身中存储对最新跟踪事件的引用:

class Tracking(models.Model) 
    # ... 
    last_event = models.ForeignKey(TrackingEvent, null=True) 

然后您将使用 signals每当创建新的跟踪事件时更新此引用。类似的东西:

from django.db.models.signals import post_save 
from django.dispatch import receiver 
 
@receiver(post_save, sender=TrackingEvent) 
def update_latest_tracking_event(sender, instance, created, **kwargs): 
    # Is this a new event? 
    if created: 
        # If yes, then update the Tracking reference 
        tracking = instance.tracking 
        tracking.last_event = instance 
        tracking.save() 

(请阅读有关放置此代码的位置的文档)。

一旦所有这些都准备就绪,就可以很容易地根据最后的跟踪事件类型进行过滤:

# I'm just guess what event types you have... 
cancellation = TrackingEventType.objects.get(name='cancel') 
Tracking.objects.filter(last_event__event_type=cancellation)