2016-06-06 3 views
2

У меня есть две модели:Django- Удалить дубликаты только, если поле присутствует

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))

Я думал об использовании различны и исключить, но не мог заставить его работать.

+0

В какой базе данных у вас есть? – AKS

+0

@AKS postgresql – dnit13

ответ

1

Я хотел бы предложить следующий подход:

  1. Получить идентификатор из всех книг, которые не принадлежат к series:

    ids_list1 = list(Book.objects.filter(series=None).values_list('id', flat=True)) 
    
  2. Получить идентификатор всех книг, которые принадлежат к series и получить только первый используя 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)) 
    

Теперь вы можете объединить эти два списка и сделать еще один запрос, чтобы вернуться только книги с этими идентификаторами:

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

Сначала исключить все, если серия не является None, а затем вызвать отчетливый() вернет вам список.

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

+0

Это предоставит только книги, которые не являются частью серии, я также хочу, чтобы одна книга из серии. как было предложено AKS – dnit13

Смежные вопросы