How to schedule task to run in background using django background tasks - django

I have set up a background task "date_check" but it does not run daily. I can't figure out where I've went wrong in the setup. I also got the error "TypeError: date_check() missing 1 required positional argument: 'self' when I tried to run python manage.py process_tasks.
here is my model.py:
...
#background(schedule=5)
def date_check(self):
"""Will be used as a background task to make sure trips that have ended don't hog van availability."""
today = datetime.date.today()
name = self.van_used
if today > self.trip_start and today > self.trip_end:
vans.objects.filter(vanName = name).update(available = True)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.date_check(repeat=Task.DAILY)
UPDATE:
I tried removing self from the function parameter, still to no avail. I am now getting the error TypeError: date_check() missing 3 required positional arguments: 'van_used', 'trip_start', and 'trip_end'.
Here's the updated code:
#background(schedule=5)
def date_check(van_used, trip_start, trip_end):
"""Will be used as a background task to make sure trips that have ended don't hog van availability."""
today = datetime.date.today()
name = van_used
if today > trip_start and today > trip_end:
vans.objects.filter(vanName = name).update(available = True)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.date_check(self.van_used, self.trip_start, self.trip_end, repeat=Task.DAILY)

In order to actually run the function, it (of course) needs the arguments. There is, however, not really a position in your code that calls it (since its scheduled), meaning there is not really a position in your code where you can actually pass the arguments. This is also what Willem meant in his reply when he mentioned it was a "standalone", you don't call it yourself. Since python doesn't know what to pass but is asked to give vars, it throws an exception.
The answer: find a way to retrieve the argument within the function. Make the signature arg-free. I'm guessing the "self" in your original post is a "Van"-object, so you'd get something like this:
def date_check():
"""Will be used as a background task to make sure trips that have ended don't hog van availability."""
van = vans.objects.all() # or some appropriate filter
today = datetime.date.today()
for v in van:
name = van.van_used
if today > van.trip_start and today > van.trip_end:
vans.objects.filter(vanName = name).update(available = True)
There's not really a way to make a background task execute on all vans individually (not one that I know of at least) but this should give you the same result

Related

how to get ticking timer with dynamic label?

What im trying to do is that whenever cursor is on label it must show the time elapsed since when it is created it does well by subtracting (def on_enter(i)) the value but i want it to be ticking while cursor is still on label.
I tried using after function as newbie i do not understand it well to use on dynamic labels.
any help will be appreciated thx
code:
from Tkinter import *
import datetime
date = datetime.datetime
now = date.now()
master=Tk()
list_label=[]
k=[]
time_var=[]
result=[]
names=[]
def delete(i):
k[i]=max(k)+1
time_var[i]='<deleted>'
list_label[i].pack_forget()
def create():#new func
i=k.index(max(k))
for j in range(i+1,len(k)):
if k[j]==0:
list_label[j].pack_forget()
list_label[i].pack(anchor='w')
time_var[i]=time_now()
for j in range(i+1,len(k)):
if k[j]==0:
list_label[j].pack(anchor='w')
k[i]=0
###########################
def on_enter(i):
list_label[i].configure(text=time_now()-time_var[i])
def on_leave(i):
list_label[i].configure(text=names[i])
def time_now():
now = date.now()
return date(now.year,now.month,now.day,now.hour,now.minute,now.second)
############################
for i in range(11):
lb=Label(text=str(i),anchor=W)
list_label.append(lb)
lb.pack(anchor='w')
lb.bind("<Button-3>",lambda event,i=i:delete(i))
k.append(0)
names.append(str(i))
lb.bind("<Enter>",lambda event,i=i: on_enter(i))
lb.bind("<Leave>",lambda event,i=i: on_leave(i))
time_var.append(time_now())
master.bind("<Control-Key-z>",lambda event: create())
mainloop()
You would use after like this:
###########################
def on_enter(i):
list_label[i].configure(text=time_now()-time_var[i])
list_label[i].timer = list_label[i].after(1000, on_enter, i)
def on_leave(i):
list_label[i].configure(text=names[i])
list_label[i].after_cancel(list_label[i].timer)
However, your approach here is all wrong. You currently have some functions and a list of data. What you should do is make a single object that contains the functions and data together and make a list of those. That way you can write your code for a single Label and just duplicate that. It makes your code a lot simpler partly because you no longer need to keep track of "i". Like this:
import Tkinter as tk
from datetime import datetime
def time_now():
now = datetime.now()
return datetime(now.year,now.month,now.day,now.hour,now.minute,now.second)
class Kiran(tk.Label):
"""A new type of Label that shows the time since creation when the mouse hovers"""
hidden = []
def __init__(self, master=None, **kwargs):
tk.Label.__init__(self, master, **kwargs)
self.name = self['text']
self.time_var = time_now()
self.bind("<Enter>", self.on_enter)
self.bind("<Leave>", self.on_leave)
self.bind("<Button-3>", self.hide)
def on_enter(self, event=None):
self.configure(text=time_now()-self.time_var)
self.timer = self.after(1000, self.on_enter)
def on_leave(self, event=None):
self.after_cancel(self.timer) # cancel the timer
self.configure(text=self.name)
def hide(self, event=None):
self.pack_forget()
self.hidden.append(self) # add this instance to the list of hidden instances
def show(self):
self.time_var = time_now() # reset time
self.pack(anchor='w')
def undo(event=None):
'''if there's any hidden Labels, show one'''
if Kiran.hidden:
Kiran.hidden.pop().show()
def main():
root = tk.Tk()
root.geometry('200x200')
for i in range(11):
lb=Kiran(text=i)
lb.pack(anchor='w')
root.bind("<Control-Key-z>",undo)
root.mainloop()
if __name__ == '__main__':
main()
More notes:
Don't use lambda unless you are forced to; it's known to cause bugs.
Don't use wildcard imports (from module import *), they cause bugs and are against PEP8.
Put everything in functions.
Use long, descriptive names. Single letter names just waste time. Think of names as tiny comments.
Add a lot more comments to your code so that other people don't have to guess what the code is supposed to do.
Try a more beginner oriented forum for questions like this, like learnpython.reddit.com

Python: Child Inheriting Parents Default Values If Not Specified

fairly intermediate programmer but Python beginner here. I've been working on a game for a while and I restructured all of my classes yesterday. Where I was initially using only compositional data structure, I'm now using a mix of both. My issues come when I want to spawn the player. Here's the relevant code.
class Object(object):
def __init__(self, **kwargs):
DeaultValues={'x':0, 'y':0, 'name':None, 'texture':None, 'blocks':False, 'ObjectID':None, 'Fighter':None, 'Corpse':None, 'Skill':None, 'ai':None}
for key,value in DeaultValues.items():
try:
vars(self)[key] = kwargs[key]
except ValueError:
vars(self)[key] = value
except KeyError:
vars(self)[key] = value
self.x = kwargs['x']
self.y = kwargs['y']
self.name=kwargs['name']
self.blocks=kwargs['blocks']
self.ObjectID=self.AttachID()
self.texture = kwargs['texture']
#This section binds an actors compenents to itself
self.Corpse = kwargs['Corpse']
if self.Corpse:
self.Corpse.owner = self
self.Skill=kwargs['Skill']
if self.Skill:
self.Skill.owner = self
self.Fighter = kwargs['Fighter']
if self.Fighter:
self.Fighter.owner = self
self.ai = kwargs['ai']
if self.ai:
self.ai.owner = self
class HighActor(Object):
def __init__(self, **kwargs):
super(HighActor, self).__init__(**kwargs)
class Player(HighActor):
def __init__(self, Level=1, Xp=0, PreviousLevel=0, PreviousLevelThreshold=100, LevelThreshold=500, **kwargs):
super(Player, self).__init__(**kwargs)
self.LevelThreshold = LevelThreshold
self.PreviousLevelThreshold=PreviousLevelThreshold
self.PreviousLevel=PreviousLevel
self.Level = Level
self.Xp = Xp
def SpawnPlayer():
global player
FighterComponent = Fighter(MaxHp=100, Hp=100, IsHasted=[False, False], death_function=None)
CorpseComponent = Corpse()
SkillComponent = HighActorSkill()
player=Player(name="player", x=None, y=None, texture="player.png", blocks=True, ObjectID=None, Fighter=FighterComponent, Corpse=CorpseComponent, Skill=SkillComponent, ai=None)
The above code works just fine, however its not really inheriting anything. To get the player object to not error I had to add to add all of the attributes of the base object class to the Player initialization. If I remove any of the values that are set to none in the player=Player() statement I get value errors or key errors. I tried to correct this by having a dict of default values that looped through all kwargs the init was given and if they had no value, set them to the default found. This worked until I got to any of the components. So in the case of not specifying ai=none, I got key errors. I would really love to have my code in such a format that if I do not specify a value for any of the base object class attributes the default values would be passed in, but if I do specify a value, that gets passed up to the base class. My ideal end result would be to have my player instancing look like this:
def SpawnPlayer():
global player
FighterComponent = Fighter(MaxHp=100, Hp=100, IsHasted=[False, False], death_function=None)
CorpseComponent = Corpse()
SkillComponent = HighActorSkill()
player=Player(name="player", texture="player.png", blocks=True, Fighter=FighterComponent, Corpse=CorpseComponent, Skill=SkillComponent)
I have a suspicion that my inheritance isn't working 100% because I get errors if I leave out ObjectID even though that should be assigned since in the init of the bass class its set equal to getid(self). So I'm either having issues with my inheritance (I'm really struggling with Super), or the signatures of my objects, and I'm not quite sure what my problem is, and more importantly why. I'm not opposed to changing the codes signature dramatically, as I'm still writing the engine so nothing is reliant on this yet. What should be done?
I think your class structure should be different. Each class should only have the attributes it needs, add new ones as you build up the inheritance, e.g.:
class Object(object):
def __init__(self, x=0, y=0, name=None, **kwargs):
self.x = x
self.y = y
self.name = name
class HighActor(Object):
def __init__(self, corpse=None, skill=None, **kwargs):
super(HighActor, self).__init__(**kwargs)
self.corpse = corpse
self.skill = skill
class Player(HighActor):
def __init__(self, level=1, xp=0, **kwargs):
super(Player, self).__init__(**kwargs)
self.level = level
self.xp = xp
At each level you specify the attributes - all Objects should have x, y and name, all HighActors should also have corpse and skill, etc. Now you can specify arguments to supply to any of the three levels of the hierarchy, or leave them out to get defaults:
player = Player(name="player one", skill=100, xp=12)
You may have things that don't fit into this inheritance scheme - it is OK to have more than one separate set of inheritance relationships in your model, don't force it!
This works because the **kwargs at the end of each __init__ "mops up" any keyword arguments that method isn't expecting into a dictionary kwargs, and can then pass them all to the next level. When you do so, super(...).__init__(**kwargs), this unpacks the dictionary back into keyword arguments, and any that aren't present will take the specified default value.

Custom Number Field is not executing "to_python"?

I am new to Django and Python.
In my project I am using CustomField defined by me so that I can encrypt the data values before storing into database and decrypt it after retreiving (there is need for encryption in my case).
I have gone through git-repository / stackoverflow / google to find the answer for my question, there are similar questions on stackoverflow but none of them got this issue. As I am unable to fix it from 2 days, would certainly need help now.
I have the code which is defining CustomField as follows -
def get_multiple_of_8(some_value):
some_value = str(some_value)
while(len(some_value) % 8 != 0):
some_value = '0'+some_value
return some_value
def is_multiple_of_8(input_str):
input_str = str(input_str)
if(len(input_str) % 8 == 0):
return True
return False
class CustomField(models.Field):
'''To Encrypt the values in Model'''
__metaclass__ = models.SubfieldBase
def __init__(self, *args, **kwargs):
self.key = myProject.settings.SECRET_KEY[:8]
self.des = DES.new(self.key, DES.MODE_ECB)
kwargs['max_length'] = kwargs.get('max_length',128)
models.Field.__init__(self, *args, **kwargs)
def get_internal_type(self):
return 'CharField'
def get_prep_value(self, value):
if value is None:
return None
value = "%.2f" % value
value = get_multiple_of_8(value)
to_return = self.des.encrypt(value)
to_return = to_return.decode('latin-1')
# to_return = force_unicode(to_return)
return to_return
def to_python(self, value):
value = value.encode('latin-1')
if is_multiple_of_8(value):
to_return = self.des.decrypt(value)
try:
to_return = float(to_return)
return to_return
except:
return 0
Encryption works perfectly, I can see the encrypted field values using sqlite3 command line.
error I am getting is :
Exception Type: InvalidOperation
Exception Value: Invalid literal for Decimal: '\xc3\x85\xc3\x84\xc3\xa13\xc2\xa6\x0f(u'
On debugging found that "to_python()" is not functioning properly. (Code source from django-fields git). I am getting error which shows encrypted string on screen instead of actual value upon retrieval through views.py !
I found one question on stackoverflow having same problem but got fixed because of metaclass syntax in different Python version.
My Python version 2.7.5 and Django 1.4.5, I am developing site on Windows 7.
Please someone help me resolve the issue, also Is there a way to debug these kind of issues ?, any suggestion is accepted, thank you in advance...
Finally got the answer :)
Had to understand how the SQLite database system works!
The problem here is, when the Database which we are using, let it be any in that case. Firstly we shall format the data to be stored into it. Once the types are assigned to the database table fields, (I don't know why) still it can save data of other format (May be bug in SQLite, table had Integer field but still stored 350 characters long string, command line displayed). Problem arises when retrieval is done, Database SW will look for Integer value from the field but gets some non-supported values. (Hence error).
May be my question now shifted to the one in brackets in fore mentioned paragraph ? Is it true (because it proved like that to me) or Is there other reasons ?

Dynamic forms in Django hosted by GAE

I am a newbie to Django, GAE, and met some problems when I am trying to build some dynamic forms using Django. The idea is that the selection made from one drop-down box determines value in another field.
In detail, if an user
choose "A" in "Species", then the value in the "body_weight" will be 178. Similarly,
if he choose "B" in "Species", the value in "body_weight" is 1580, and
if choose "C" in "Species", the he can fill in the "body_weight"
I read some examples, and found some features like "init, and super should be included". Thus I modified my codes, but it still did not work.
My problems are:
What is the right position to place "init" and "super"?
Do I need "self.field" here?
All suggestions are welcomed!
Thanks!
Here is the code.
Species_CHOICES=(('178','A'),('1580','B'),('','C'))
class Inp(forms.Form):
Species = forms.ChoiceField(label='Species', choices=Species_CHOICES, initial='A')
#Here detect the choice made by the user
def get_STB_choices(Species):
if Species=='178':
r= 178
elif Species=='1580':
r= 1580
else:
r= 4440
return a
#assign values to a new parameter based on user's choice
def __init__(self, *args, **kwargs):
super(Inp, self).__init__(*args, **kwargs)
body_weight=forms.FloatField(required=True, label='Body weight', initial=get_STB_choices(Species))
#write out in HTML
class InputPage(webapp.RequestHandler):
def get(self):
html = str(Inp())
self.response.out.write(html)
You're going to need Javascript running on the page to update the available selections.
I implemented it one way here. Each time you make a selection, the page makes an AJAX request to get the new form fields that were dependent on the initial change.
https://github.com/dragonx/django-hier-ajax-form
After I did mine, I realized there was already an existing project that did the same thing, but our implementations are pretty different:
https://github.com/digi604/django-smart-selects
btw, I believe usually when you call super() you use it with the name of the current class, so I would have expected
super(Inp, self).__init__(*args, **kwargs)

How to have django give a HTTP response before continuing on to complete a task associated to the request?

In my django piston API, I want to yield/return a http response to the the client before calling another function that will take quite some time. How do I make the yield give a HTTP response containing the desired JSON and not a string relating to the creation of a generator object?
My piston handler method looks like so:
def create(self, request):
data = request.data
*other operations......................*
incident.save()
response = rc.CREATED
response.content = {"id":str(incident.id)}
yield response
manage_incident(incident)
Instead of the response I want, like:
{"id":"13"}
The client gets a string like this:
"<generator object create at 0x102c50050>"
EDIT:
I realise that using yield was the wrong way to go about this, in essence what I am trying to achieve is that the client receives a response right away before the server moves onto the time costly function of manage_incident()
This doesn't have anything to do with generators or yielding, but I've used the following code and decorator to have things run in the background while returning the client an HTTP response immediately.
Usage:
#postpone
def long_process():
do things...
def some_view(request):
long_process()
return HttpResponse(...)
And here's the code to make it work:
import atexit
import Queue
import threading
from django.core.mail import mail_admins
def _worker():
while True:
func, args, kwargs = _queue.get()
try:
func(*args, **kwargs)
except:
import traceback
details = traceback.format_exc()
mail_admins('Background process exception', details)
finally:
_queue.task_done() # so we can join at exit
def postpone(func):
def decorator(*args, **kwargs):
_queue.put((func, args, kwargs))
return decorator
_queue = Queue.Queue()
_thread = threading.Thread(target=_worker)
_thread.daemon = True
_thread.start()
def _cleanup():
_queue.join() # so we don't exit too soon
atexit.register(_cleanup)
Perhaps you could do something like this (be careful though):
import threading
def create(self, request):
data = request.data
# do stuff...
t = threading.Thread(target=manage_incident,
args=(incident,))
t.setDaemon(True)
t.start()
return response
Have anyone tried this? Is it safe? My guess is it's not, mostly because of concurrency issues but also due to the fact that if you get a lot of requests, you might also get a lot of processes (since they might be running for a while), but it might be worth a shot.
Otherwise, you could just add the incident that needs to be managed to your database and handle it later via a cron job or something like that.
I don't think Django is built either for concurrency or very time consuming operations.
Edit
Someone have tried it, seems to work.
Edit 2
These kind of things are often better handled by background jobs. The Django Background Tasks library is nice, but there are others of course.
You've turned your view into a generator thinking that Django will pick up on that fact and handle it appropriately. Well, it won't.
def create(self, request):
return HttpResponse(real_create(request))
EDIT:
Since you seem to be having trouble... visualizing it...
def stuff():
print 1
yield 'foo'
print 2
for i in stuff():
print i
output:
1
foo
2