Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I don't see any great way to do what you're trying to do directly. If you're willing to accept a little de-normalization, I would recommend a pre-save signal to mark messages as being at the head.</p> <pre><code>#In your model head = models.BooleanField(default=True) #As a signal plugin: def check_head(sender, **kwargs): message = kwargs['instance'] if hasattr(message,'no_check_head') and message.no_check_head: return previous_message = Message.objects.filter(time__lt=message.time).order_by('-time')[0] if message.source == previous_message.source: message.head = False next_message = Message.objects.filter(time__gt=message.time).order_by('time')[0] if message.source == next_message.source: next_message.head = False next_message.no_check_head next_message.save() </code></pre> <p>Then your query becomes magically simple:</p> <pre><code>messages = Message.objects.filter(head=True).order_by('time')[0:15] </code></pre> <p>To be quite honest...the signal listener would have to be a bit more complicated than the one I wrote. There are a host of lost synchronization/lost update problems inherent in my approach, the solutions to which will vary depending on your server (if it is single-processed, multi-threaded, then a python <code>Lock</code> object should get you by, but if it is multi-processed, then you will really need to implement locking based on files or database objects). Also, you will certainly also have to write a corresponding delete signal listener.</p> <p>Obviously this solution involves adding some database hits, but they are on edit as opposed to on view, which might be worthwhile for you. Otherwise, perhaps consider a cruder approach: grab 30 stories, loop through the in the view, knock out the ones you won't display, and if you have 15 left, display them, otherwise repeat. Definitely an awful worst-case scenario, but perhaps not terrible average case?</p> <p>If you had a server configuration that used a single process that's multi-threaded, a Lock or RLock should do the trick. Here's a possible implementation with non-reentrant lock:</p> <pre><code>import thread lock = thread.allocate_lock() def check_head(sender, **kwargs): # This check must come outside the safe zone # Otherwise, your code will screech to a hault message = kwargs['instance'] if hasattr(message,'no_check_head') and message.no_check_head: return # define safe zone lock.acquire() # see code above .... lock.release() </code></pre> <p>Again, a corresponding delete signal is critical as well.</p> <p>EDIT: Many or most server configurations (such as Apache) will prefork, meaning there are several processes going on. The above code will be useless in that case. See <a href="https://stackoverflow.com/questions/698950/what-is-the-simplest-way-to-lock-an-object-in-django/699222#699222">this page</a> for ideas on how to get started synchronizing with forked processes.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload