You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django中获取模型的所有重复记录并创建展示该记录的API?

嘿,这个需求我之前帮人处理过好几次,其实挺清晰的,我一步步给你拆解实现步骤:

第一步:先明确「重复记录」的判定规则

首先得搞清楚:你认为什么样的记录算重复?比如是**name、start_date、start_time三个字段完全相同才算重复**,还是只需要其中某几个字段重复?这里我默认按三个字段组合重复来演示,你可以根据自己的需求随时调整字段组合。

先假设你的模型是这样的(如果已有模型,直接用自己的就行):

# models.py
from django.db import models

class Event(models.Model):  # 这里用Event做示例名,你换成自己的模型名
    name = models.CharField(max_length=255)
    start_time = models.TimeField()
    start_date = models.DateField()
    # 其他你已有的字段...

    def __str__(self):
        return f"{self.name} - {self.start_date} {self.start_time}"
第二步:编写查询重复记录的逻辑

要找出重复记录,核心思路是:先按目标字段分组,统计每组的记录数,筛选出数量大于1的分组,再把这些分组对应的所有记录捞出来。

我推荐给模型加个自定义管理器,把查询逻辑封装起来,这样代码更整洁,也方便复用:

# models.py 里继续加
from django.db.models import Count, F, Subquery, OuterRef

class EventManager(models.Manager):
    def get_duplicates(self):
        # 第一步:找出所有重复的字段组合(记录数>1)
        duplicate_groups = self.values('name', 'start_date', 'start_time') \
            .annotate(record_count=Count('id')) \
            .filter(record_count__gt=1)
        
        # 第二步:根据这些组合,获取所有对应的重复记录
        # 用子查询的方式更高效,避免多次查询
        duplicate_ids = self.filter(
            name=OuterRef('name'),
            start_date=OuterRef('start_date'),
            start_time=OuterRef('start_time')
        ).values('id')

        duplicates = self.filter(
            id__in=Subquery(duplicate_ids)
        ).order_by('name', 'start_date', 'start_time')
        
        return duplicates

# 给模型绑定这个管理器
class Event(models.Model):
    # ...你的字段定义
    objects = EventManager()  # 替换默认的objects管理器
第三步:用Django REST Framework构建API

如果还没装DRF,先装一下:pip install djangorestframework,然后把rest_framework加到settings.py的INSTALLED_APPS里。

先写序列化器

把模型数据转换成API返回的JSON格式:

# serializers.py
from rest_framework import serializers
from .models import Event

class EventSerializer(serializers.ModelSerializer):
    class Meta:
        model = Event
        fields = '__all__'  # 或者指定你需要返回的字段,比如['id', 'name', 'start_date', 'start_time']

再写API视图

用DRF的ListAPIView快速实现列表接口:

# views.py
from rest_framework.generics import ListAPIView
from .models import Event
from .serializers import EventSerializer

class DuplicateEventsAPIView(ListAPIView):
    serializer_class = EventSerializer

    def get_queryset(self):
        # 调用我们刚才封装的重复记录查询方法
        return Event.objects.get_duplicates()

如果想返回更友好的分组信息(比如每个重复组有多少条记录),可以自定义APIView:

# views.py 可选的分组视图
from rest_framework.views import APIView
from rest_framework.response import Response

class DuplicateGroupsAPIView(APIView):
    def get(self, request):
        # 直接返回分组后的统计信息和对应记录
        duplicate_groups = Event.objects.values('name', 'start_date', 'start_time') \
            .annotate(record_count=Count('id')) \
            .filter(record_count__gt=1) \
            .order_by('-record_count')
        
        # 给每个分组加上具体的记录列表
        result = []
        for group in duplicate_groups:
            group_records = Event.objects.filter(
                name=group['name'],
                start_date=group['start_date'],
                start_time=group['start_time']
            ).values('id', 'name', 'start_date', 'start_time')
            
            result.append({
                'group_key': f"{group['name']} - {group['start_date']} {group['start_time']}",
                'record_count': group['record_count'],
                'records': list(group_records)
            })
        
        return Response(result)
第四步:配置API路由

在app的urls.py里添加路由:

# urls.py (app级别)
from django.urls import path
from .views import DuplicateEventsAPIView, DuplicateGroupsAPIView

urlpatterns = [
    # 所有重复记录的列表接口
    path('api/duplicate-events/', DuplicateEventsAPIView.as_view(), name='duplicate-events'),
    # 可选的分组统计接口
    path('api/duplicate-groups/', DuplicateGroupsAPIView.as_view(), name='duplicate-groups'),
]

然后在项目根目录的urls.py里把这个app的路由包含进去:

# urls.py (项目级别)
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('your_app_name.urls')),  # 替换成你的app名称
]
一些优化建议
  • 如果你的数据量很大,建议给name、start_date、start_time加联合索引,提升查询速度:
    class Event(models.Model):
        # ...字段定义
        class Meta:
            indexes = [
                models.Index(fields=['name', 'start_date', 'start_time']),
            ]
    
  • 如果重复规则需要调整(比如只按name重复),只需要修改values()里的字段列表即可。

内容的提问来源于stack exchange,提问作者raj-kapil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 08:02:31