Django-仅在字段存在时删除重复项

时间:2016-06-06 11:54:52

标签: django python-2.7 django-models django-queryset

我有两种模式:

class BookSeries(models.Model):
    title = models.CharField(max_length=200, null=False, blank=False, unique=True)
    #extra fields

class Book(models.Model):
    series = models.ForeignKey(BookSeries, blank=True, null=True, default=None)
    publisher = models.ForeignKey(Publisher, default=None, null=True, blank=True)
    title = models.CharField(max_length=200, null=False, blank=False, unique=True)
    #extra fields

现在我想查询所有不属于系列的书籍,并且只有属于同一系列的任何一本书中的一本(系列可以为空)。

问题陈述:

我想查询所有个人书籍和系列。 由于一个系列可以有多本书,而一本书可能不属于一个系列。其中一个解决方案是查询所有书籍对象(它们不属于一系列)并查询所有系列对象here。但是这会将所有系列组合在一起,并在回应中将书籍放在一起。我不希望它们被组合在一起(我也在使用分页)。

类似于:Book.objects.filter( disctinct only if(series is not None))

我想过使用distinct和exclude但是无法使它工作。

2 个答案:

答案 0 :(得分:1)

我建议采用以下方法:

  1. 获取不属于series的所有图书的ID:

    ids_list1 = list(Book.objects.filter(series=None).values_list('id', flat=True))
    
  2. 获取属于series的所有图书的ID,并仅使用distinct获取:

    ids_list2 = list(Book.objects
                         .exclude(series=None)   # exclude ones which are not in a series
                         .order_by('series')     # order by series
                         .distinct('series')     # keep the first book in each series
                         .values_list('id', flat=True))
    
  3. 现在,您可以合并这两个列表并进行另一个查询,以仅返回包含这些ID的书籍:

    ids = id_list1 + id_list2
    books = Book.objects.filter(id__in=ids)
    

答案 1 :(得分:0)

如果系列为None,则首先排除所有,然后调用distinct()返回一个列表。

Book.objects.exclude(series=None).distinct('series')

如果需要排除空值和空字符串,首选方法是将条件链接在一起,如下所示: Book.objects.exclude(series__isnull=True).exclude(series__exact='')

您可以按照此主题更好地理解Filtering for empty or NULL names in a queryset