The methods I'm using are unbound? - python

I'm working on a calendar via Python's HTMLCalendar and Django. The functions I'm using to input data into the calendar are showing up as unbound, and therefore not working.
Here's the calendar code:
from www.wednesday.models import Event
import calendar
e = Event()
class EventCal(calendar.HTMLCalendar):
def formatday(self, day, weekday):
if day == 0:
return '<td class="noday"> </td>' # Day outside month
if day == e.dd():
return '<td class="%s">%d</p>%s</td>' % (self.cssclasses[weekday], day, e.link(), e.res())
else:
return '<td class="%s">%d</td>' % (self.cssclasses[weekday], day)
class rendCal:
c = EventCal(calendar.SUNDAY)
Here's my models.py:
from django.db import models
class Event(models.Model):
Restaurant = models.CharField(max_length=200)
LinkURL = models.CharField(max_length=200)
created = models.DateTimeField(auto_now_add=True)
DateDay = models.IntegerField(max_length=2)
def dd(self):
return '%i' % self.DateDay
def link(self):
return '%s' % self.LinkURL
def res(self):
return '%s' % self.Restaurant
And lastly, my views.py:
from django.shortcuts import render_to_response
import www.wednesday.models
from www.wednesday.cal import rendCal
import datetime as dt
def calendar(request):
now = dt.datetime.now()
cal = rendCal.c.formatmonth(now.year, now.month)
return render_to_response('cal.html', {'calendar': cal})
Everything works except for the functions from Event that are called inside the EventCal class.
Obviously I'm quite new at this.
Okay, #Marcin asked for an error, this is what I'm seeing, also I corrected the capitalization.
TypeError at /calendar/
unbound method dd() must be called with Event instance as first argument (got nothing instead)
cal.py in formatday, line 9
The environment variables in EventCal from Event are showing up blank, I'm pretty sure that's why I'd been getting the needs int not str error. When I change e.dd() to a static number, it returns everything but e.link() and e.res().

dd() is a method of an instance of the class.
You call it like this:
e = Event()
x = e.dd()
You can't apply dd to Event itself.
I am not sure what exactly you are trying to do, so I am not sure how you need to modify your code.

In formatday you have:
if day == 0:
but also:
if day == Event.dd():
and Event.dd() returns a string.
So, is day an int or a string?

Related

"Invalid Syntax" by overwriting HTMLCalendar functions in Python

I want to create a webiste with a calendar in Django. Therefor i have found a tutorial on the web. Here you have to overwrite the functions from the HTMLCalendar When I use the Code from there comes the Error :
File "/home/work/Desktop/Coden /Projects/Calendar/anotherone/cal/utils.py", line 18
d += f"<li> {event.title} </li>"
The tutorial - when it comes to overwriting the functions:
https://www.huiwenteo.com/normal/2018/07/24/django-calendar.html
This is just a Django Project. I code on Ubuntu in Visualstudio code. Here the start from the files. I think it occurs because of the " and the following HTML Code. As you can see, is this not once in the file it comes again and again. I hope someone can give me a solution for the whole file.
from datetime import datetime, timedelta
from calendar import HTMLCalendar
from .models import Event
class Calendar(HTMLCalendar):
def __init__(self, year=None, month=None):
self.year = year
self.month = month
super(Calendar, self).__init__()
# formats a day as a td
# filter events by day
def formatday(self, day, events):
events_per_day = events.filter(start_time__day=day)
d = ''
for event in events_per_day:
d += f"<li> {event.title} </li>"
if day != 0:
return f"<td><span class='date'>{day}</span><ul> {d} </ul></td>"
return '<td></td>'
I hope I can display the calendar after fixing the error.

Django 1.11.7: How do I call a Class method in Views?

In my models.py I have a Class (Paths) with a method, validate_time that tries to access two fields of the Paths model (time_start, time_end):
class Paths(m.Model):
time_start: m.TimeField()
time_end: m.TimeField()
def validate_time(self):
start = self.time_start
end = self.time_end
print start #print start to test it out
#...some function that returns True or False
I call validate_time in my views.py:
from .models import Paths
def paths_data(request):
ps = Paths()
valid_times = ps.validate_time()
if valid_times == False:
....
I see the method, validate_time, is hit because I see the print statement
But it appears the print out says: None
But time_start and time_end have already been saved to the model as strings. How can I get them as their string value in validate_time?
I think self.time_start might not have been set as ps is an empty Path object initialized by 'ps = Paths()' and time_start does not have a default value.
If you are looking for a saved instance, you need to query database for it first with something like Paths.objects.get(your_key=your_value). More details on queries: https://docs.djangoproject.com/en/1.11/topics/db/queries/
You can use either #classmethod or #staticmethod decorator for validate_time

Convert Data Objects to Strings for Script

I am getting this error each time I try to run this app in its present state.
TypeError: cannot concatenate 'str' and 'GameData' objects
I am trying to get a data object from my Game(GameData) class onto the browser with my html. It's a subclass of GameData() which is a template class.
class GameData(object): #This class is the template for the data for each game.
def __init__(self):
self.title = ''
self.genre = ''
self.description = ''
self.developer = ''
self.rating = ''
self.image = ''
class Game(GameData): #Thas class holds all the data for each game.
def __init__(self):
#object for Castlevania
self.castlevania = GameData()
self.castlevania.title = 'Castlevania'
self.castlevania.genre = 'Action Platformer'
self.castlevania.description = 'Released in 1986 in Japan, Castlevania for the NES and Famicom Disc System spawned a series rich in action as well as exploration. This first game was merely a simple platformer but it inspired many changes to the formula over the years and invented the "Metroidvania" genre.'
self.castlevania.developer = 'Konami'
self.castlevania.rating = '7.5/10'
self.castlevania.image = 'images/t_castlevania.png'
There are other objects but if I can get one of them to work I can figure out the rest. I need it to get into this elif statement highlighted with a comment.
class MainHandler(webapp2.RequestHandler):
def get(self):
i = Intro()
d = GameData()
g = Game()
if self.request.GET:
page = self.request.GET['page']
if page == 'main_page':
self.response.write(i.head + i.main_page + i.main_title + i.main_links)
elif page == 'castlevania': #The data needs to go in this concatenation.
self.response.write(i.head + i.main_page + i.castlevania + (the data object should go here) + i.main_links)
From there I know what to do. I just need to know how to convert the data into a string so I can concatenate it. If anyone can help I would appreciate it. Also I tried using an array for the objects but that didn't work for me either.
You just need to include the __str__ function in your Game(GameData) class.
eg.
def __str__(self):
# Here you would put whatever logic in terms of returning a string
# representation of your game object. Eg:
return self.castlevania.title
Then, you would simply call str(g) where g is your Game(GameData) object

Python3.5 object and json.dumps() output

I wrote a class that would allow me to add days (integers) to dates (string %Y-%m-%d). The objects of this class need to be JSON serializable.
Adding days in the form of integers to my objects works as expected. However json.dumps(obj) returns too much info ("2016-03-23 15:57:47.926362") for my original object. Why ? How would I need to modify the class to get ""2016-03-23" instead ? Please see the example below.
Code:
from datetime import datetime, timedelta
import json
class Day(str):
def __init__(self, _datetime):
self.day = _datetime
def __str__(self):
return self.day.date().isoformat()
def __repr__(self):
return "%s" % self.day.date().isoformat()
def __add__(self, day):
new_day = self.day + timedelta(days=day)
return Day(new_day).__str__()
def __sub__(self, day):
new_day = self.day - timedelta(days=day)
return Day(new_day).__str__()
if __name__ == "__main__":
today = Day(datetime.today())
print(today) # 2016-03-23
print(json.dumps(today)) # "2016-03-23 15:57:47.926362"
print(today+1) # 2016-03-24
print(json.dumps(today+1)) # "2016-03-24"
print(today-1) # 2016-03-22
print(json.dumps(today-1)) # "2016-03-22"
Update. Here's my final code for those interested:
from datetime import datetime, timedelta
import json
class Day(str):
def __init__(self, datetime_obj):
self.day = datetime_obj
def __new__(self, datetime):
return str.__new__(Day, datetime.date().isoformat())
def __add__(self, day):
new_day = self.day + timedelta(days=day)
return Day(new_day)
def __sub__(self, day):
new_day = self.day - timedelta(days=day)
return Day(new_day)
if __name__ == "__main__":
today = Day(datetime.today())
print(type(today))
print(today) # 2016-03-23
print(json.dumps(today)) # "2016-03-23"
print(today + 1) # 2016-03-24
print(json.dumps(today + 1)) # "2016-03-24"
print(today - 1) # 2016-03-22
print(json.dumps(today - 1)) # "2016-03-22"
print(json.dumps(dict(today=today))) # {"today": "2016-03-23"}
print(json.dumps(dict(next_year=today+365))) # {"next_year": "2017-03-23"}
print(json.dumps(dict(last_year=today-366))) # {"last_year": "2015-03-23"}
Cool! Let's go with it. You are seeing:
print(json.dumps(today)) # "2016-03-23 15:57:47.926362"
Because somewhere in the encoding process, when deciding how to serialize what was passed to it, json.dumps calls isinstance(..., str) on your object. This returns True and your object is serialized like this string it secretly is.
But where does the "2016-03-23 15:57:47.926362" value come from?
When you call day = Day(datetime_obj), two things happen:
__new__ is called to instantiate the object. You haven't provided a __new__ method, so str.__new__ is used.
__init__ is called to initialize the object.
So day = Day(datetime_obj) effectively translates to:
day = str.__new__(Day, datetime_obj)
For json.dumps, your object will be a str, but the value of the str is set to the default string representation of datetime_obj. Which happens to be the full format you are seeing. Builtins, man!
I played around with this, and it seems if you roll your own __new__ (which is slightly exciting territory, tread carefully) which intercepts the str.__new__ call, you ~~should~~ be fine:
class Day(str):
def __new__(self, datetime):
return str.__new__(Day, datetime.date().isoformat())
But you didn't hear it from me if the whole thing catches fire.
PS The proper way would be to subclass JSONEncoder. But there is zero fun in it.
PS2 Oh, shoot, I tested this on 2.7. I may be completely out there, and if I am, just give me a "you tried" badge.
The reason for the json.dumps(today)'s behavior is not as obvious as it might appear at the first glance. To understand the issue, you should be able to answer two questions:
where does the string value that includes the time come from?
why Day.__str__ is not called by json encoder ? Should it?
Here're some prerequisites:
datetime.today() method is similar to datetime.now() -- it includes the current time (hour, minutes, etc). You could use date.today(), to get only date.
str creates immutable objects in Python; its value is set in the __new__ method that you have not overriden and therefore the default conversion str(datetime.today()) is used to initialize Day's value as a string. It creates the string value that includes both date and time in your case. You could override __new__, to get a different string value:
def __new__(cls, _datetime):
return str.__new__(cls, _datetime.date())
Day is a str subclass and therefore its instances are encoded as JSON strings
str methods return str objects instead of the corresponding subclass objects unless you override them e.g.:
>>> class S(str):
... def duplicate(self):
... return S(self * 2)
...
>>> s = S('abc')
>>> s.duplicate().duplicate()
'abcabcabcabc'
>>> s.upper().duplicate()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'duplicate'
s.upper() returns str object instead of S here and the following .duplicate() call fails.
In your case, to create the corresponding JSON string, json.dumps(today) performs an operation (re.sub() call in json.encode.encode_basestring()) on the today object that uses its value as a string i.e., the issue is that neither re.sub() nor encode_basestring() call __str__() method on instances of str subclasses. Even if encode_basestring(s) were as simple as return '"' + s + '"'; the result would be the same: '"' + today returns a str object and Day.__str__ is not called.
I don't know whether re module should call str(obj) in functions that accept isinstance(obj, str). Or whether json.encode.encode_basestring() should do it (or neither).
If you can't fix Day class; you could patch json.encode.encode_basestring() to call str(obj), to get a desirable JSON representation for str subtype instances (if you want to get the value returned by __str__() method -- putting aside whether it is wise to override __str__() on a str subclass in the first place):
import json
for suffix in ['', '_ascii']:
function_name = 'encode_basestring' + suffix
orig_function = getattr(json.encoder, function_name)
setattr(json.encoder, function_name, lambda s,_e=orig_function: _e(str(s)))
Related Python issue: Cannot override JSON encoding of basic type subclasses

Django - Functions in models and views don't return correct Boolean value

I am creating a django app/website and am in trouble with some Boolean results I don't understand.
In my models, I have a Article class with 2 functions :
class Article(models.Model):
#some vars
basetime = models.IntegerField()
duration = models.IntegerField()
has_begun = models.BooleanField()
def remainingTime(self):
if(self.basetime + self.duration) - time.time() >= 0:
return ((self.basetime + self.duration) - time.time())
else:
return -1
def stillAvailable(self):
if self.remainingTime() >= 0:
return True
return False
And in my views I have a function check :
def check(request,i):
try:
article = Article.objects.get(pk=i)
except Article.DoesNotExist:
return ccm(request)
if (article.stillAvailable):
return test(request,article.remainingTime)
else:
return quid(request)
When a page calls check, my browser displays the test page, and the argument article.remainingTime is -1. (wich is the correct value for what I want to do).
My problem is : if article.remainingTime = -1, then article.stillAvailable should return False, and so the check function should return quid(request).
I don't see the reason why django/python interpreter evaluates article.stillAvailable True.
If anyone can help, that'd be very appreciated :P
You are using
if (article.stillAvailable):
As a attribute, rather than calling it as a method. As the attribute exists, it's interpreted as non false. You just need to add the brackets to call the method.

Categories

Resources