Help with Manager.

9 views
Skip to first unread message

Marc Aymerich

unread,
Oct 14, 2010, 11:27:24 AM10/14/10
to django...@googlegroups.com
Hi, 
I'm trying to make a Manager for my model "order". I want that it returns all orders that their 'active period'* is greater than a certain threshold. With "active period" I mean: (order.cancel_date - order.register_date )

My Order model looks like this:

class order(models.Model):
    register_date = models.DateTimeField(auto_now_add=True)
    cancel_date = models.DateTimeField(null=True, blank=True)


I'm wondering if is possible to achieve that using "annotate", something like that:
(this not work) 
order.objects.annotate(diff=SUB('cancel_date','register_date')).filter(diff__gt=period_threshold)


or maybe django provides another kind of tool to achieve what i want ? 
I'll appreciate any kind of orientation :) 

thanks!! 


--
Marc

Jonathan Barratt

unread,
Oct 14, 2010, 12:10:57 PM10/14/10
to django...@googlegroups.com
Unless I'm misunderstanding what you're looking for, I think this might suit your needs:

in your model:
class order(models.Model):
...
    def get_active_period(self): return self.cancel_date - self.register_date active_period = property(get_active_period)
(you may want to add some checking that cancel_date is not null, or that active_period is not negative but you get the idea)

Then where you need to access that queryset use:

order.objects.filter(active_period__gt=period_threshold)

But others with more Django experience than I may give you better advice...

Good luck!
Jonathan

Marc Aymerich

unread,
Oct 14, 2010, 12:19:58 PM10/14/10
to django...@googlegroups.com


2010/10/14 Jonathan Barratt <jonathan...@knifeict.com>
Hi Jonathan!, 
Thank you very much for your answer, it's a pretty good solution :)
 


--
Marc

Marc Aymerich

unread,
Oct 14, 2010, 12:40:54 PM10/14/10
to django...@googlegroups.com


2010/10/14 Jonathan Barratt <jonathan...@knifeict.com>
jops ;(, unfortunately the Manager doesn't know what "active_period" is. 

This is my order model now:

class order(models.Model):
    [...]
    def get_active_period(self):
        if self.cancel_date:
            return self.cancel_date-self.register_date
        else:
            return datetime.datetime.now()-self.register_date
        
    active_period = property(get_active_period)    

    objects = models.Manager()
    pending_of_bill = pending_of_billManager()  


And this is my manager:

class pending_of_billManager(models.Manager):
    def get_query_set(self):
        [...]
        return super(pending_of_billManager, self).get_query_set().filter(active_period__gt=threshold)

This Works:
>>> order.objects.get(pk=1).active_period
datetime.timedelta(0, 8347, 24949)

but this doesn't:
>>> order.pending_of_bill.all()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/lib/python2.6/dist-packages/django/db/models/manager.py", line 117, in all
    return self.get_query_set()
  File "/home/ucp/trunk/ucp/../ucp/order/models.py", line 15, in get_query_set
    return super(pending_of_billManager, self).get_query_set().filter(active_period__gt=threshold)
  File "/usr/lib/python2.6/dist-packages/django/db/models/query.py", line 549, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/usr/lib/python2.6/dist-packages/django/db/models/query.py", line 567, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "/usr/lib/python2.6/dist-packages/django/db/models/sql/query.py", line 1128, in add_q
    can_reuse=used_aliases)
  File "/usr/lib/python2.6/dist-packages/django/db/models/sql/query.py", line 1026, in add_filter
    negate=negate, process_extras=process_extras)
  File "/usr/lib/python2.6/dist-packages/django/db/models/sql/query.py", line 1191, in setup_joins
    "Choices are: %s" % (name, ", ".join(names)))
FieldError: Cannot resolve keyword 'active_period' into field. Choices are: amendment_invoice, amendment_quota, bill, cancel_date, comment, contracted_pack, discount, entity, forward, htacces, htpasswd, id, included, installed_app, mailman, name, order_disk, order_memory, order_swap, ovz, pack, price, register_date, renew, service, size, system_group, system_user, system_user_related, traffic, virtual_aliase, virtual_user, virtual_user_related, virtualhost


What I'm missing ?? why super(pending_of_billManager, self).get_query_set() doesn't know about active_period?
Thanks! 

--
Marc

Marc Aymerich

unread,
Oct 14, 2010, 3:50:56 PM10/14/10
to django...@googlegroups.com


2010/10/14 Marc Aymerich <glic...@gmail.com>
Seems that we can't use a property as a queryset 'filter', in other words we can't use property like this:  order.objects.filter(active_time__gt=whatever)



--
Marc

Alec Shaner

unread,
Oct 14, 2010, 4:08:23 PM10/14/10
to django...@googlegroups.com
See this:

http://ifacethoughts.net/2009/07/14/calculated-fields-in-django/

So perhaps the 'extra' query filter is what you need.

> --
> You received this message because you are subscribed to the Google Groups
> "Django users" group.
> To post to this group, send email to django...@googlegroups.com.
> To unsubscribe from this group, send email to
> django-users...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/django-users?hl=en.
>

Marc Aymerich

unread,
Oct 14, 2010, 5:57:47 PM10/14/10
to django...@googlegroups.com
On Thu, Oct 14, 2010 at 10:08 PM, Alec Shaner <ash...@chumpland.org> wrote:
See this:

http://ifacethoughts.net/2009/07/14/calculated-fields-in-django/

So perhaps the 'extra' query filter is what you need.


Yep, I got a success using extra filter :) Thanks Alec for sharing this! 

by the way, just right now I found the way to reference field on filter and operates with it. It can be achieved using instances of F()  

it could be more 'elegant' than using an extra filter, all I need is something like that:

order.objects.filter(Q(cancel_date__isnull=False, cancel_date__lt=F('register_date') + Threshold) | Q(cancel_date__isnull=True, register_date__gt=Threshold) )

but i couldn't get working this part: "F('register_date')+Threshold" ,(threshold is a datetime.datetime object, and also 'register_date' field. Anyone knows the correct way to use instances of F() with date field?  

  

--
Marc

Alec Shaner

unread,
Oct 14, 2010, 9:39:35 PM10/14/10
to django...@googlegroups.com
You can't add a datetime to another datetime - you want to add a
datetime.timedelta instance instead. Out of curiosity I just tested it
on one of my models and it does work, e.g.,

MyModel.objects.filter(update_date__gt=F('entry_date')+timedelta(days=5))

Marc Aymerich

unread,
Oct 15, 2010, 3:17:43 AM10/15/10
to django...@googlegroups.com
On Fri, Oct 15, 2010 at 3:39 AM, Alec Shaner <ash...@chumpland.org> wrote:
You can't add a datetime to another datetime - you want to add a
datetime.timedelta instance instead. Out of curiosity I just tested it
on one of my models and it does work, e.g.,

MyModel.objects.filter(update_date__gt=F('entry_date')+timedelta(days=5))



Hi Alec, thanks again for your answer :) 

When you executes this filter on a shell you don't get a warning ? 

This is what happens to me: 

>>> order.objects.filter(cancel_date__isnull=False).filter(cancel_date__lt=F('register_date') + timedelta(days=3))
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/usr/lib/python2.6/dist-packages/django/db/models/query.py", line 67, in __repr__
    data = list(self[:REPR_OUTPUT_SIZE + 1])
  File "/usr/lib/python2.6/dist-packages/django/db/models/query.py", line 82, in __len__
    self._result_cache.extend(list(self._iter))
  File "/usr/lib/python2.6/dist-packages/django/db/models/query.py", line 268, in iterator
    for row in compiler.results_iter():
  File "/usr/lib/python2.6/dist-packages/django/db/models/sql/compiler.py", line 672, in results_iter
    for rows in self.execute_sql(MULTI):
  File "/usr/lib/python2.6/dist-packages/django/db/models/sql/compiler.py", line 727, in execute_sql
    cursor.execute(sql, params)
  File "/usr/lib/python2.6/dist-packages/django/db/backends/util.py", line 18, in execute
    return self.cursor.execute(sql, params)
  File "/usr/lib/python2.6/dist-packages/django/db/backends/mysql/base.py", line 86, in execute
    return self.cursor.execute(query, args)
  File "/usr/lib/pymodules/python2.6/MySQLdb/cursors.py", line 168, in execute
    if not self._defer_warnings: self._warning_check()
  File "/usr/lib/pymodules/python2.6/MySQLdb/cursors.py", line 82, in _warning_check
    warn(w[-1], self.Warning, 3)
Warning: Truncated incorrect DOUBLE value: '3 0:0:0'

It's only a warning, but I can't see the output queryset result, maybe it's a ""fatal"" warning? you know why this is happening? 

Thanks again!!
 
--
Marc

Alec Shaner

unread,
Oct 15, 2010, 9:29:51 AM10/15/10
to django...@googlegroups.com
Sorry, not sure about that warning because I'm using a postgresql database.

Reply all
Reply to author
Forward
0 new messages