Django ManyToManyField error when trying to pull values from other models - python

I'm trying to recreate Groupon using purely django and have having trouble with the below. This is my below idea
A Merchant can start a Campaign(which has a unique CampaignID)
A Customer(who has his own unique ID) can save a Campaign to be redeemed later
I created a model with 3 columns (CampaignID, CustomerID and a booleanfield with a default value of False)
class Customer_save(models.Model):
Customer_ID = models.ManyToManyField(Customer)
Campaign_ID = models.ManyToManyField(Campaigns)
Redeemed = models.BooleanField(default = False) #False denotes that it hasnt been redeemed yet
def __str__(self):
return self.Customer_ID.username,self.Campaign_ID.Campaign_desc
I'm trying to create a fake a row wanting to test if everything properly gets fed into the table. But i'm coming across errors. Could you please tell me where i'm going wrong?
Campaign_ID = '10001'
Customer_ID = 'C12345'
Customer_save.add(Customer_ID = Customer_ID,Campaign_ID = Campaign_ID)
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: type object 'Customer_wallet' has no attribute 'add'
>>> New = Customer_save(Customer_ID = Customer_ID, Campaign_ID `=Campaign_ID)`
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/kj/Desktop/projects/lib/python3.4/site-packages/django/db/models/base.py", line 480, in __init__
raise TypeError("'%s' is an invalid keyword argument for this function" % list(kwargs)[0])
>>> new = Customer_save.Customer_ID.create(Customer_ID = Customer_ID)
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'ReverseManyRelatedObjectsDescriptor' object has no attribute 'create'
TypeError: 'Customer_ID' is an invalid keyword argument for this function

You need to create the relevant records before assigning them to a many-to-many field:
customer = Customer(...)
customer.save()
campaign = Campaigns(...)
campaign.save()
customer_save = Customer_save(Redeemed=...)
customer_save.save()
customer_save.Customer_ID.add(customer)
customer_save.Campaign_ID.add(campaign)
More information on Django documentation: Many-to-many relationships.
PS. I would recommend you to choose better names for your fields and models and follow the formal style guide. They are a bit misleading and often such names lead to confusion, never mind that it is difficult for others to follow your code.

Related

Query about usage of setattr() in Python-Redmine

setattr() for an item in Redmine issues, is failing, with the following error.
Traceback (most recent call last):
File "E:\test\get_redmine_data.py", line 47, in <module>
print (item.assigned_to)
File "C:\Python27\lib\site-packages\redminelib\resources\standard.py", line 150, in __getattr__
return super(Issue, self).__getattr__(attr)
File "C:\Python27\lib\site-packages\redminelib\resources\base.py", line 164, in __getattr__
attr, encoded = self.encode(attr, decoded, self.manager)
File "C:\Python27\lib\site-packages\redminelib\resources\base.py", line 266, in encode
return attr, manager.new_manager(cls._resource_map[attr]).to_resource(value)
File "C:\Python27\lib\site-packages\redminelib\managers\base.py", line 29, in to_resource
return self.resource_class(self, resource)
File "C:\Python27\lib\site-packages\redminelib\resources\base.py", line 130, in __init__
self._decoded_attrs = dict(dict.fromkeys(relations_includes), **attributes)
TypeError: type object argument after ** must be a mapping, not str
I am trying to set some default assignee, for issues where the assignee is not set. The code fails at the line, where I print the attribute I just set. My code is given below:
redmine = Redmine('http://redmine_url', username='uname', password='pwd')
project = redmine.project.get('proj_name')
work_items = project.issues
for item in work_items:
assignee_not_set = getattr(item,'assigned_to',True)
if assignee_not_set == True:
print item.id
setattr(item,'assigned_to','Deepak')
print (item.assigned_to)
I also tried using the update() method,
redmine.project.update(item.id, assigned_to='Deepak')
That also fails with another error - redminelib.exceptions.ResourceNotFoundError: Requested resource doesn't exist.
I verifed that the issue id exists in Redmine.
You have several problems here:
The attribute name is assigned_to_id and not assigned_to
It accepts user id which is int and not a username which is str
No need to use setattr() here, just use item.assigned_to_id = 123
You need to call item.save() after setting assigned_to_id otherwise it won't be saved to Redmine
When you're trying to use update() method, you're using in on a Project resource and not on Issue resource, this is why you're getting ResourceNotFoundError
All this information is available in the docs: https://python-redmine.com/resources/issue.html

Django 'str' object is not callable when deleting a foreign key object

I have a model with a foreign key to another model and when I try to delete an object (in this example the object with id=0 that exists).
Models.py
class MyModel(models.Model):
example = models.ForeignKey(OtherModel,related_name='example',on_delete=models.SET_NULL ,blank=True,null=True)
class OtherModel(models.Model):
name = models.CharField(max_length=250)
shell
>>> import project
>>> from project import models
>>> project.models.OtherModel.objects.get(id=0).delete()
Traceback (most recent call last):
File "console", line 1, in "module"
File ".../lib/python3.5/site-packages/django/db/models/base.py"
, line 890, in delete collector.collect([self], keep_parents=keep_parents)
File ".../lib/python3.5/site-packages/django/db/models/deletion.py", line 222, in collect
field.remote_field.on_delete(self, field, sub_objs, self.using)
TypeError: 'str' object is not callable
You are trying to create Foreign Key relation with a model which is not defined yet.
example = models.ForeignKey(OtherModel,related_name='example',on_delete=models.SET_NULL ,blank=True,null=True)
Here Other model is defined below this Line, so it can't identify what OtherModel is.

Custom filter field test doesn't work

I have the next test for a filter field.
Running the test i have this bug:
======================================================================
ERROR: test_related_field_ajax_list_filter (jet.tests.test_filters.FiltersTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/salahaddin/Proyectos/tiempoturco/lib/python3.5/site-packages/jet/tests/test_filters.py", line 42, in test_related_field_ajax_list_filter
list_filter = RelatedFieldAjaxListFilter(field, request, lookup_params, model, model_admin, field_path)
File "/home/salahaddin/Proyectos/tiempoturco/lib/python3.5/site-packages/django/contrib/admin/filters.py", line 176, in __init__
self.empty_value_display = model_admin.get_empty_value_display()
TypeError: get_empty_value_display() missing 1 required positional argument: 'self'
======================================================================
ERROR: test_related_field_ajax_list_filter_with_initial (jet.tests.test_filters.FiltersTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/salahaddin/Proyectos/tiempoturco/lib/python3.5/site-packages/jet/tests/test_filters.py", line 55, in test_related_field_ajax_list_filter_with_initial
list_filter = RelatedFieldAjaxListFilter(field, request, lookup_params, model, model_admin, field_path)
File "/home/salahaddin/Proyectos/tiempoturco/lib/python3.5/site-packages/django/contrib/admin/filters.py", line 176, in __init__
self.empty_value_display = model_admin.get_empty_value_display()
TypeError: get_empty_value_display() missing 1 required positional argument: 'self'
I can't understand what the problem is, I investigate digging in the filter and I can find the problem: the line 176 in django. admin filters
How can I fix this problem, which is the better way for initialize model_admin parameter? What's the correct way for make this test?
Your problem is higher up, in line 30:
model_admin = ModelAdmin
Here you are not instantiating the object, you simply create another reference to the class itself. Calling a method directly on a class will give the error you see.
You need to call the class to instantiate it, passing it any required arguments.

Why does my use of NDB's `populate()` not accept `id` or `parent`, but only `key`?

I want to create an entity object and after its construction, before writing it into the datastore, I want to set parent and id.
According to App Engine docs, the constructor accepts these keyword arguments:
- id
- key
- parent
You cannot easily define a property named "key", "id", "parent", or
"namespace". If you pass, for example, key="foo" in a constructor or
populate() call, it sets the entity's key, not a property attribute
named "key".
For populate(), it says it would accept the same keyword arguments as the constructor. However, it seems I'm doing something wrong, because the only keyword argument that works is key. Using id and/or parent gives me errors.
class Foo(ndb.Model):
pass
foo = Foo()
foo.populate(key=ndb.Key('Bar', 1, 'Foo', 123))
foo.key == ndb.Key('Bar', 1, 'Foo', 123) # True
When instead I use the keyword parent...
f.populate(parent=ndb.Key('Bar', 1))
...I get this traceback:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2960, in _populate
self._set_attributes(kwds)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2970, in _set_attributes
prop = getattr(cls, name) # Raises AttributeError for unknown properties.
AttributeError: type object 'Foo' has no attribute 'parent'
or sometimes this (not sure what makes the difference):
File "<console>", line 1, in <module>
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2960, in _populate
self._set_attributes(kwds)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2972, in _set_attributes
raise TypeError('Cannot set non-property %s' % name)
TypeError: Cannot set non-property parent
If I use id...
f.populate(id=123)
I get again an attribute error:
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2960, in _populate
self._set_attributes(kwds)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2970, in _set_attributes
prop = getattr(cls, name) # Raises AttributeError for unknown properties.
AttributeError: type object 'Foo' has no attribute 'id'
Shouldn't all of my populate() examples above work with any of the keyword arguments?
I know, I could only use key to achieve the same as with parent and id together, but I would like to know what I'm missing here.
parent is a property of a Key when using ancestor paths. The constructor accepts it as a convenience but since it is not its own property, populate() will complain that it does not exist. Same goes for id. The constructor uses id to construct a Key using _get_kind() and the value of id.
An example is worth 1000 comments. See how id and parent are used to construct a key
>>> from google.appengine.ext import ndb
>>>>
>>> class Foo(ndb.Model):
... pass
...
>>> foo = Foo(id=123, parent=ndb.Key('Bar', 1))
>>> foo.key
Key('Bar', 1, 'Foo', 123)
>>> foo.id
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'id'
>>> foo.parent
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'Foo' object has no attribute 'parent'
The docs may not be clear enough on this issue, but you're only supposed to use populate to update properties of the model (actual data).
This is clear looking at the source code, for example this line of the model constructor:
Note: you cannot define a property named key; the .key attribute always refers to the entity's key. But you can define properties named id or parent. Values for the latter cannot be passed through the constructor, but can be assigned to entity attributes after the entity has been created.
Suggesting we could use id and parent as properties/attributes, thus populate calls will try to set them.
It gets even clearer once we get to the populate implementation, where the inline documentation has a provision for your exact question:
Each keyword argument will be used to set a corresponding property. Keywords must refer to valid property name. This is similar to passing keyword arguments to the Model constructor, except that no provisions for key, id or parent are made.
Maybe the docs should be updated with this information to avoid the confusion. I never ran into this issue myself, maybe because I've been following the recommendation of "only setting the key when instantiating a model", however I can't find a quote for this statement; I take it as a rule of thumb, and am under the impression that trying to assign it afterwards should raise exceptions everywhere.
And as if the previous references weren't enough, look at this line in the constructor:
self._key = _validate_key(key, entity=self)
You won't find that anywhere else, so this is the only instance of a key being assigned [properly] to a model (as you can imagine, populate only iterates and sets values).

SQLAlchemy Error when filtering

I'm using using SQLAlchemy to fiter but getting an error:
user = session.query.filter(User.id == 99).one()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'function' object has no attribute 'filter'
Does someone know how to filter because on SQLAlchemy Page, I saw this:
query = session.query(User).filter
query is a function, you need to pass in the User class to call it:
user = session.query(User).filter(User.id == 99).one()
^^^^^^
SQLAlchemy cannot divine from the filter alone what type of object you want returned otherwise.

Categories