2013-11-06 2 views
1

У меня есть класс под названием ToggleProperty. Я использую его для хранения информации о том, используется ли использование некоторых свойств объекта. Примерами свойств являются «как», «bookmark» и «follow».Есть ли способ переписать этот, по-видимому, простой фрагмент Django, чтобы он не попадал в базу данных?

class ToggleProperty(models.Model): 
    # "like", "bookmark", "follow" etc 
    property_type = CharField() 

    # The user who toggled the property 
    user = ForeignKey(User) 

    # The object upon which the user is toggling the property, e.g. "user likes image" 
    object_id = models.TextField() 
    content_type = models.ForeignKey(ContentType) 
    content_object = generic.GenericForeignKey('content_type', 'object_id') 

Теперь я хотел бы получить список пользователей, за которыми следует определенный пользователь, назовем его Томом.

Я не могу просто запросить на ToggleProperty, потому что это даст мне ToggleProperties, а не для пользователей!

Так я это сделать:

# First get the ContentType for user, we'll need it 
user_ct = ContentType.objects.get_for_model(User) 

# Now get the users that Tom follows 
followed_by_tom = [ 
    user_ct.get_object_for_this_type(id = x.object_id) for x in 
    ToggleProperty.objects.filter(
     property_type = "follow", 
     user = tom, 
     content_type = ContentType.objects.get_for_model(User)) 
] 

Проблема с этим состоит в том, что она попадает в базу данных, на мой взгляд, и мне не нравится это.

Если это не было достаточно уродливым, выслушайте меня. Меня действительно интересуют изображения, загруженные пользователями, которых следует за Томом, поэтому я могу показать Тому все изображения людей, которых он следует.

Так в приведенном выше коде, я добавляю это:

images = Image.objects.filter(user__in = followed_by_tom) 

Это заканчивает выполнение более 400 запросов, и принимать в течение секунды, чтобы обработать. Должен быть лучший способ, не могли бы вы показать мне путь?

ответ

2

Эта часть:

followed_by_tom = [ 
user_ct.get_object_for_this_type(id = x.object_id) for x in 
ToggleProperty.objects.filter(
    property_type = "follow", 
    user = tom, 
    content_type = ContentType.objects.get_for_model(User)) 
] 

получает все User экземпляров, которые следуют в N запросах, когда это может быть сделано в одном запросе. На самом деле вам не нужны сами экземпляры только идентификаторы для получения Images с запросом IN. Таким образом, вы можете удалить лишние запросы в цикле с помощью:

followed_by_tom = ToggleProperty.objects.filter(
    property_type="follow", 
    user=tom, 
    content_type=ContentType.objects.get_for_model(User) 
).values_list('object_id', flat=True) 

images = Image.objects.filter(user__in=followed_by_tom) 

Поскольку followed_by_tom никогда не оценивали ОРМ должны выполнять это как один запрос с суб-выбора.

+0

Спасибо, что сделал! –

+0

follow_by_tom должен иметь список пользователей правильно? но вы получите список object_ids. Как это работает? – iamkhush

+0

Дело в том, что вам не нужен список пользователей. Вам нужен только список идентификаторов. –

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

  • Нет связанных вопросов^_^