2016-12-22 2 views
1

В следующей ситуации:Использование функции pre_fetch_related Django

В библиотеке книга может быть размещена всего в одном рукаве. В течение курса книгу можно было перенести из рукава в рукав.

И модели

class Sleeve(models.Model): 
    sleeve_name = models.CharField(max_length=60) 
    sleeve_number = models.DecimalField() 

class Book(models.Model): 
    book_title = models.CharField(max_length=120) 
    sits_in_sleeve = models.ForeignKey(Sleeve, null=False) 

Теперь я хотел бы создать Django QuerySet запросить все рукава с числом от 1 до 10, а также запросить все книги названия, принадлежащие к этому. Как мне это сделать с prefetch_related?

Другими словами, я могу сделать что-то вроде:

sleeves = Sleeve.objects.filter(sleeve_number__lte=10,sleeve_number__gte=1) 
for s in sleeves: 
    b = Book.objects.get(sits_in_sleeve=s) 
    s.book = b 

Но есть более элегантный способ сделать это?

+0

Вы на самом деле нужны рукава вообще или вас интересуют только книги? – Sayse

+0

** и запросить все названия книг, принадлежащие этому ** Насколько я понимаю, вам нужны все книги между рукавом номер 1 и 10. Правильно ..? –

ответ

2

Вы можете сделать что-то вроде этого:

b = Book.objects.filter(sits_in_sleeve__sleeve_number__lte=10,sits_in_sleeve__sleeve_number__gte=1) 

Поскольку книга модель имеет поле с именем sits_in_sleeve, который имеет отношение внешнего ключа с моделью рукава.

Таким образом, вы можете выполнить любую операцию над полями модели Sleeve, добавив двойное подчеркивание (__), чтобы получить поля соответствующей модели Sleeve.

UPDATE:

Как Sayse предложил, вы можете также использовать функцию диапазона вместо отдельного использования __gte и __lte. Как это:

b = Book.objects.filter(sits_in_sleeve__sleeve_number__range=(1,10)) 
+1

Я почти уверен, что это то, что на самом деле нужно оператору, но ожидало ответа ... вы можете использовать ['range'] (https://docs.djangoproject.com/en/1.10/ref/models/querysets/# range) - 'sits_in_sleeve__sleeve_number__range = (1,10)' – Sayse

+1

@Sayse Да, это лучший способ приблизиться к менее чем 10, более 1 условия. –

1

Вы можете сделать это с помощью prefetch_related:

sleeves = Sleeve.objects.filter(sleeve_number__lte=10,sleeve_number__gte=1).prefetch_related('book_set') 

Вы можете получить книги для каждого рукава, не делая дополнительных запросов:

for sleeve in sleeves: 
    books = sleeve.book_set.all() 
+0

эй! мой вопрос для вас был бы следующим: как возникает параметр 'book_set'? Я видел эту реализацию, но не уверен, что ее можно применить ко всем, и именно поэтому я спрашиваю. Спасибо :) – bryansis2010

+1

Добавление '_set' к имени модели с нижним регистром является значением' related_name' по умолчанию. Вы можете переопределить это в полевом определении поля 'ForeignKey' с аргументом' related_name'. 'sleeve.book_set' - это так называемый связанный менеджер, который предоставляет вам функциональность менеджера моделей для всех книг одного рукава. – schwobaseggl