I have two models:
class Someinfo(models.Model):
name = models.CharField(max_length=200)
#something else
class OtherInfo(models.Model):
name2 = models.CharField(max_lenth=200)
related_someinfo = models.ManyToManyField(Someinfo)
#something else
Now I have created CBV views to create and view them. The CreateView works fine and saves info that can be reviewed in admin, but I cannot get the template to display the data on any other view be it FormView, DetailView or any other, because I get this error:
__call__() missing 1 required keyword-only argument: 'manager'
Request Method: GET
Request URL: http://something
Django Version: 2.0.3
Exception Type: TypeError
Exception Value:
__call__() missing 1 required keyword-only argument: 'manager'
Exception Location: /usr/local/lib/python3.5/dist-packages/django/forms/forms.py in get_initial_for_field, line 494
Python Executable: /usr/bin/python3
Python Version: 3.5.3
Checking the line in forms.py it shows that the function that is not working is:
def get_initial_for_field(self, field, field_name):
"""
Return initial data for field on form. Use initial data from the form
or the field, in that order. Evaluate callable values.
"""
value = self.initial.get(field_name, field.initial)
if callable(value):
value = value() # line 494
return value
Any suggestions? I can query the linked objects via shell and they are saved in the database, so I have no idea how to proceed.
Here is my case, I am using django shell:
python manage.py shell
There are two models: Topic and Entry. I tried to get all entries from Topic which id is 1.
>>> Topic.objects.get(id=1)
<Topic: Chess>
>>> t = Topic.objects.get(id=1)
>>> t.entry_set().all()
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: __call__() missing 1 required keyword-only argument: 'manager'
>>> t.entry_set.all()
<QuerySet [<Entry: Ah okey, so when testing for a console.log (or oth...>]>
>>>
The correct command is: t.entry_set.all(), not t.entry_set().all()
use entry_set instead of entry_set()(wihout brackets )
Related
I am trying to create a generic function lifecycle handler in python.
Working in brief:
Logs the signature and return values.
Handles the exception with or without retry.
Provide cleanup in case of exception.
The issue which I encountered while doing the cleanup is as follows:
Function-based decorator:
def handler(exception=Exception,cleanup=None):
def func_wrapper(func):
def wrapper(*args,**kwargs):
response=None
try:
print(args)
response=func(*args,**kwargs)
except exception as ex:
print(f'Exception occurred:{str(ex)}\nCleaning up resources')
#Passing the object for cleanup, it fails for class based decorators as it does not passes self as argument
cleanup(args[0])
return response
return wrapper
return func_wrapper
The data which is supposed to be cleaned up is stored in the class instance and is cleaned based on the method provided.
For example:
Store some information using third party API.
In case of exception, the cleanup operation passed would invoke a
delete API.
class Test:
def __init__(self,data):
self.main_data=data
#handler(exception=Exception,cleanup=lambda x:print(f"Cleaning data:{x.main_data}"))
def test_data(self):
print(f'Data is :{self.main_data}')
i=1/0
Output:
Exception occurred:division by zero
Cleaning up resources
Cleaning:John Doe
I was more inclinded towards Class based decorator.
class LifeCycleHandler:
def __init__(self,*,func=None,exception=Exception,cleanup=None):
self.__exception=exception
self.__cleanup=cleanup
self.__func=func
def __call__(self,*args,**kwargs):
response=None
try:
print(args)
response=self.__func(*args,**kwargs)
except self.__exception as ex:
print(f'Exception occurred:{str(ex)}\n cleaning up resources')
#Passing the object for cleanup
self.__cleanup(args[0])
return response
def lifecycle_handler(exception=Exception,cleanup=None):
def wrapper(func):
response=LifeCycleHandler(func=func,exception=exception,cleanup=cleanup)
return response
return wrapper
With class based decorator with similar functionality i faced the following error:
()
Exception occurred:test_data() missing 1 required positional argument: 'self'
cleaning up resources
Traceback (most recent call last):
File "test.py", line 27, in __call__
response=self.__func(*args,**kwargs)
TypeError: test_data() missing 1 required positional argument: 'self'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 54, in <module>
test.test_data()
File "test.py", line 31, in __call__
self.__cleanup(args[0])
IndexError: tuple index out of range
Can someone guide me regarding the the argument interpretation for callable classes?
If my comment correct, you could add __get__ to LifeCycleHandler.
def __get__(self, obj, type=None):
return functools.partial(self.__call__, obj)
This will make test_data become a non-data descriptor. I assume you already know descriptor. If not, it's definitely worth to check it.
Back to your question, from trace back, your assumed that python will help you pass the caller instance which is instance of Test as second argument to __call__. That's not true. However, that's true in __get__.
Your core logic (try/except block) needs are:
instance of Test, because you need access to main_data.
instance of LifeCycleHandler in, because you need access to your self.__func.
args in which isn't acceptable in __get__, but you could have them in __call__.
For example, you have test code below:
t = Test(123)
t.test_data()
t.test_data will invoke __get__. In its arguments, self is an instance of LifeCycleHandler and obj is t (instance of Test). __get__ returned a callable function(__call__) in which its first argument is partially feed by obj.
I have a callback method being triggered on a GPIO pin that when fired calls for a read of a input devices register, however when called I get -
Traceback (most recent call last):
File "/home/coder/Try2.py", line 35, in NewPins
x = self.mcp.readGPIO()
AttributeError: 'int' object has no attribute 'mcp'
If I enter-
a.mcp.readGPIO() <- from python shell I get
`BitArray('0xffff')` <-expected result
>>>
where the RotaryEncoder class is instantiated as 'a'
`class RotaryEncoder:`
`def __init__(self,IntPin, Start, Id):`
.... initialise some variables then open the device as 'mcp' -
`self.mcp = MCP23S17(bus=0x00, pin_cs=0x00, device_id=Id)`
`self.mcp.open()`
`def NewPins(self):`
` global OldPins`
` x = self.mcp.readGPIO()`
..... irrelevant code
callback line is
gpio.add_event_detect(IntPin, gpio.FALLING, callback=NewPins)
expected read value is a BitArray
actual result is
AttributeError: 'int' object has no attribute 'mcp'
Ok my dumb.... - the RPiGPIO library I'm using returns the GPIO channel number in the callback, hence the callback function requires two arguments and not one. I had thought I'd messed up my namespaces and so was trying to code around this when I encountered the error above - I'm a novice python programmer and didn't know where to look!
That'll teach me to not to read the documentation thoroughly...
The following code
class Foo:
def bar(self) -> None:
pass
foo = Foo()
if hasattr(foo.bar, '__annotations__'):
foo.bar.__annotations__ = 'hi'
crashes with
AttributeError: 'method' object has no attribute '__annotations__'
How can this happen?
The attribute error here is raised because you can't set any attribute on a method object:
>>> foo.bar.baz = 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'method' object has no attribute 'baz'
The exception here is perhaps confusing because method objects wrap a function object and proxy attribute read access to that underlying function object. So when attributes on the function exist, then hasattr() on the method will return True:
>>> hasattr(foo.bar, 'baz')
False
>>> foo.bar.__func__.baz = 42
>>> hasattr(foo.bar, 'baz')
True
>>> foo.bar.baz
42
However, you still can't set those attributes via the method, regardless:
>>> hasattr(foo.bar, 'baz')
True
>>> foo.bar.baz = 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'method' object has no attribute 'baz'
So, just because the attribute can be read doesn't mean you can set it. hasattr() is speaking the truth, you just interpreted it to mean something different.
Now, if you tried to set the __annotations__ attribute directly on the underlying function object you'd get another error message:
>>> foo.bar.__func__.__annotations__ = 'hi'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __annotations__ must be set to a dict object
You would want to use a dictionary object here:
>>> foo.bar.__func__.__annotations__ = {'return': 'hi'}
>>> foo.bar.__annotations__
{'return': 'hi'}
However, because __annotations__ is a mutable dictionary, it is just easier to directly manipulate the keys and values to that object, which is perfectly feasible to do via the method wrapper:
>>> foo.bar.__annotations__['return'] = 'int'
>>> foo.bar.__annotations__
{'return': 'int'}
Now, if you were hoping to set per instance annotations, you can't get away with setting attributes on method objects, because method objects are ephemeral, they are created just for the call, then usually discarded right after.
You would have to use custom method descriptor objects via a metaclass and re-create the __annotations__ attribute for those each time, or you could instead pre-bind methods with a new function object that would be given their own attributes. You then have to pay a larger memory price:
import functools
foo.bar = lambda *args, **kwargs: Foo.bar(foo, *args, **kwargs)
functools.update_wrapper(foo.bar, Foo.bar) # copy everything over to the new wrapper
foo.bar.__annotations__['return'] = 'hi'
Either way you completely kill important speed optimisations made in Python 3.7 this way.
And tools that operate on the most important use case for __annatotions__, type hints, do not actually execute code, they read code statically and would completely miss these runtime alterations.
You're getting an error. because __annotations__ is a dictionary. If you want to change values you'll have to do it like this:
if hasattr(foo.bar, '__annotations__'):
foo.bar.__annotations__['return'] = 'hi'
This will make the return value of your foo.bar be hi instead of None. The only thing I'm not sure about is how the __annotations__ are protected, not allowing you to change them from a dict to string, but I suppose it's some internal check in the source.
UPDATE
For more control over the signature you can use the inspect module and get the Signature object of your class(or method) and edit it from there. For example
import inspect
sig = inspect.signature(foo.bar)
sig.return_annotation # prints None (before modifying)
sig.replace(return_annotation="anything you want")
More on that here
I am currently running a script that is supposed to create an SQLAlchemy Database that should be populated by the information below; This DB is linked to a Flask based, tasklist application. I am using SQLAlchemy 2.1.
This is the db_create.py script.
# project/db_create.py
from views import db
from models import Task
from datetime import date
# create the database and the db table
db.create_all()
# insert data
db.session.add(Task("Finish this", date(2016, 9, 22), 10, 1))
db.session.add(Task("Finish Python", date(2016, 10, 3), 10, 1))
# commit the changes
db.session.commit()
Now specifically I am receiving this error whenever I try to create the database:
/Users/Paul/Desktop/RealPython/flasktaskr/ENV/lib/python3
.6/site-packages/flask_sqlalchemy/__init__.py:800: UserWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True to suppress this warning.
warnings.warn('SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True to suppress this warning.')
Traceback (most recent call last):
File "db_create.py", line 8, in <module>
db.session.add(Task("Finish this", date(2016, 9, 22), 10, 1))
TypeError: __init__() takes 1 positional argument but 5 were given
I have tracked down an init() function in one of the files within the app, maybe this might be of some help to you:
def __init__(self, name, due_date, priority, status):
self.name = name
self.due_date = due_date
self.priority = priority
self.status = status
When I run the db_create.py file, the database IS created, however, it fails to populate the DB with the data within that original file.
Why am I receiving the error, and why is the DB failing to populate?
You need to add an __init__() method to your sqlalchemy class definition for Task
See the docs for an example.
The first positional argument is always self (read about object oriented programming to understand more about that), but essentially this error is saying that you are passing arguments and your class definition doesn't know what to do with them.
Why is python shell throwing a NameError where as windows console a ValueError?
def PrintArgs(*arg):
list = ['1','2']
for i in arg:
try:
print(list[int(i)])
except ValueError:
print('Please enter integer value')
except NameError:
print('Name Error')
if __name__ == '__main__':
PrintArgs(*sys.argv[1:])
Providing the following arguments to Windows Console gives this output:
Here is how I call the code in windows console:
C:\>C:\Python34\python C:\Users\User\Documents\PYTest\Test.py 0 a
1
Please enter integer value
Providing the following arguments to Python Shell does not display the cusom error for NameError as mentioned in the code above, but mentions the following error:
PrintArgs(0,a)
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
PrintArgs(0,a)
NameError: name 'a' is not defined
In the code example you've provided you define a list i, then you iterate over a collection called list you never initiated, and assign the values in this list to i, thus dropping the original value. I guess you only provided a part of your code, please provide a minimum working example.
If I try to reproduce your problem, I only get a type error, for iterating over a list which is not initialized.