I have this class in a module1:
class A(models.Model):
_name="a"
b_id = field.Many2one("b")
tax_old = fields.Float()
tax_value = fields.Float(string="Tax", related = 'b_id.tax_value', store=True)
all_taxes = fields.Float(_compute='compute_all')
#api.depends('tax_value')
def compute_all(self):
self.all_taxes = self.tax_value + self.tax_old
self.update()
In module2 I have this class:
class B(models.Model):
_name="b"
a_ids = fields.One2many("a","b_id")
tax_value = fields.Float(string="Tax")
Now in A view when I change b_id value, tax_value works fine and compute_all works fine, but when I save this record, all_taxes doesn't take tax_value field, only tax_old. And when I open the record form view again and manually write a value in tax_value, it works totally fine.
It should be enough to use b_id on your compute method, because it's related:
#api.multi
#api.depends('b_id')
def compute_all(self):
for record in self:
record.all_taxes = record.b_id.tax_value + record.tax_old
The compute method can be called with a multi record recordset. So use a for loop inside it. And you don't have to do an update() at the end.
You can try it
#api.one
#api.depends('b_id', 'b_id.tax_value')
def compute_all(self):
self.all_taxes = self.tax_value + self.tax_old
Two things:
It ist compute not _compute and you don't need to use self.update().
Try this instead:
# You'll need this
from django.db.models import F
#api.depends('tax_value')
def compute_all(self):
self.update(all_taxes=F('tax_value') + F('tax_old'))
You're missing the self. What you've done is defined a local variable called all_taxes, not the instance variable.. which is what you're after
Related
models.py
class club(models.Model):
name = models.CharField(max_length=30)
city = models.CharField(max_length=30)
premiere_leauge = models.BooleanField(default=False)
def __str__(self):
return self.name
Views.py
...
a = request.POST['club']
b = request.POST['city']
result = club.objects.all.get(name__exact=a, city__exact=b)
....
All is fine, however I believe result returns me:
def __str__(self):
return self.name
Whatsover, I would like an equivalent of 'SELECT * FROM APP_CLUB where name='something and city='something'; so i would be able to do further manipulation in django like:
if result[3] is True:
do_something()
As suggested in the offical documentation:
club.objects.filter(name='something')
It will return exactly the same as:
'SELECT * FROM APP_CLUB where name='something';
Example:
clubs = club.objects.filter(name__exact='something')
for club in clubs:
if club.premier_league:
do_something()
If you want to get only one club, then do it like this:
club = club.objects.get(name='something')
premier_league_value_of_club = club.premier_league
Use filter instead of get.
results = club.objects.filter(name__exact=a, city__exact=b)
You can then iterate over it to access all the model attributes like below
for result in results:
print result.name, result.city, result.premier_league
Also, according to PEP-8, you should name your class name should ideally be titlecase Club instead of lowercase club.
You're nearly there, I think you're missing the filter function here. You can use it like this :
a = request.POST['club']
b = request.POST['city']
result = club.objects.filter(name__exact=a, city__exact=b)
It will return you a query set with the actual database entries.
The __str__(self) function is used in transforming your query set entry into a string, whether you string-cast it or print it.
Then about this :
if result[3] is True:
do_something()
I don't get well what you mean about this, but if 3 is the id of the entry in the database, you then can do this :
if result.get(id=3).premiere_leauge:
do_something()
But you might want to check if the entry with the id exists first to avoid errors :
if result.filter(id=3).exists() and result.get(id=3).premiere_leauge:
do_something()
You should modify you query as shown below
result = club.objects.filter(name__exact=a, city__exact=b)
Good Luck !!
I am attempting to push data from a DJANGO view into the Tables object, passing it through as an argument. In this case, I would like to pass a variable called doc_id into a Tables2 object called tableName
In this example, I have set doc_id as 1, and pass it into the
View
def editorView(request):
doc_id = 1
table = tableName(UserProfile.objects.filter(), doc_id=doc_id)
Table
class tableName(tables.Table):
tbl_doc_id = None ## Creating a temporary variable
def __init__(self, *args, **kwargs):
temp = kwargs.pop("doc_id") ## Grab doc_ID from kwargs
super(tableName, self).__init__(*args, **kwargs)
self.tbl_doc_id = temp ## Assign to self.tbl_doc_id for use later
### Do something with tbl_doc_id
modelFilter = model.objects.filter(pk = tbl_doc_id)
When running the debugger, I can see that tbl_doc_id is still assigned as None, rather than 1.
What is the correct way to pass arguments into a Tables2 instance? Is it possible?
EDIT: Adding more information for context.
In the real world scenario, I have a view. That view takes an argument from the URL called doc_id. That doc_id is used to grab an object from a model called 'MaterialCollection', and return it as 'mc'.
'mc' is then passed into the table
View
def editorView(request, doc_id):
try:
mc = MaterialCollection.objects.get(pk = doc_id)
except Material.DoesNotExist:
raise Http404("Document does not exist")
config = RequestConfig(request)
unnassigned_User_Table = unassignedUserTable(UserProfile.objects.filter(), mc=mc)
... Other code + Render ...
From my table, I create a custom LinkColumn. That linkColumn is used to construct a URL based upon a number of Attributes from the model 'UserProfile', and from mc.
Table
class unassignedUserTable(tables.Table):
mc = None
def __init__(self, *args, **kwargs):
temp_mc = kwargs.pop("mc")
super(unassignedUserTable, self).__init__(*args, **kwargs)
self.mc = temp_mc
current_Assignment = "NONE"
new_Assignment = "AS"
assign_Reviewer = tables.LinkColumn('change_Review_AssignmentURL' , args=[ A('user'), current_Assignment, new_Assignment, mc, A('id')], empty_values=(), attrs={'class': 'btn btn-success'})
class Meta:
model = UserProfile
... Setup excludes/sequence/attributes...
In this particular instance. mc has a FK to UserProfile (in a 1:M) relationship.
I see that the name of your table class is tableName so if you want __init__ to work as expected please change the line:
super(unassignedUsers, self).__init__(*args, **kwargs)
to
super(tableName, self).__init__(*args, **kwargs)
Beyond this obvious problem, there are some more issues with your code:
Your classes must start with a capital letter (TableName instead of tableName)
Your table classes should end end with -Table (for example NameTable)
I am using django-tables2 for many years and never needed to pass something in __init__ as you are doing here. Are you sure that you really need to do this?
If you want to filter the table's data the filtering must be done to your view - the table will get the filtered data to display.
Here is Customer class:
class Customer:
def __init__(self, timestamp, cid, item_count):
self.time_stamp = timestamp
self.customer_name = cid
self.item_count = item_count
def checkout(self, new_timestamp):
self.time_stamp = new_timestamp
def get_cus_name(self):
return self.customer_name
If I create an empty list of Customer objects like:
customers = [Customer]
And then somewhere else I try to call Customer methods in a loop like:
def checkout_customer(self, cid):
for cus in self.customers:
if cus.get_cus_name == cid:
cus.checkout(self.cur_num_customers + 7)
why do I get an error when I try to call cus.checkout? My ide tells me that it expects a Customer but got an int. Why doesn't it pass itself into the 'self' arg here?
However if I just create a Customer object and directly call its methods, it works fine:
def foo(self):
cus = Customer(1,'pop',2)
cus.checkout(23)
This is my first time learning python, and ive been stuck trying to figure out lists, and accessing its members. Perhaps my initialization of self.custormers = [Customer] is incorrect?
EDIT:
In my constructor of tester class I create an empty list like this:
self.customer = [Customer]
I am able to add customers no problem:
def add_custormer(self, customer):
self.customers.append(customer)
My problem is not adding customers, but accessing their methods once they are in a list. Doing something like this self.customers[0].checkout(1,'pop',2) gives me an error "Expected type 'Customer' got int".
I am not sure of the class where checkout_customer lives but I am assuming you declare the list self.customers somewhere in it.
self.costumers = []
If you intend to add an element Customer to the list you should use something like: self.customers.append(Customer(x,y,z)) since you want to add a new customer to the list and when doing so you are required to initialize the Customer class.
I didn't try the code but I believe something like this should work:
def foo(self):
self.customers.append(Customer(1,'pop',2))
self.checkout_customers(23)
I know if we have a model class, we can make a generate table and use:
class Meta:
model = MyModel
To display every field.
Now say if I have a list of dictionaries, instead of model, is there a similar way to do so?
(Since there are so many different dictionaries, which might be dynamically created, I don't wanna create a customized one each time :-))
You can create your own class that inherits from Table and define the fields you want there.
class JsonTable(Table):
json_key_1 = Column()
json_key_2 = Column()
Also django tables2 have a fields attribute but you can't use it if your data is an array of dicts.
I've been doing this too, here's a rough sketch.
Piggy-backing on top of django_tables2 is miles ahead of rolling your own!
Plus, I hook up the results to jquery FooTable plugin.
import django_tables2 as tables
counter = 0
def generate(li_dict):
#unique classname.
global counter
counter += 1
table_classname = "MyTableClass%s" % (counter)
class Meta:
#ahhh... Bootstrap
attrs = {"class": "table table-striped"}
#generate a class dynamically
cls = type(table_classname,(tables.Table,),dict(Meta=Meta))
#grab the first dict's keys
li = li_dict[0].keys()
for colname in li:
column = tables.Column()
cls.base_columns[colname] = column
return cls
#now, to make use of it...
li_dict = [dict(a=11,b=12,c=13),dict(a=21,b=22,c=23)]
cls = generate(li_dict)
table = cls(li_dict)
# below didn't work, wanted a whole bunch of django setup done first.
# but I fairly confident it would...
print table.as_html()
>>>django.core.exceptions.ImproperlyConfigured: {% querystring %} requires django.core.context_processors.request to be in your settings.TEMPLATE_CONTEXT_PROCESSORS in order for the included template tags to function correctly.
#this did...
print "%s" % table
>>><django_tables2.tables.MyTableClass1 object at 0x1070e1090>
i am sorry for poor english :), but a think which can help, actually with this we can transforme a numpy (matrix) in a generic django table2. By the way, thanks Pyeret for your help.
def convert_array_list_dict(arr):
_list = []
for i in xrange(0, arr.shape[0]):
_list.append(dict(enumerate(arr[i,:])))
for i in xrange(0,len(_list)):
for key in _list[i].keys():
_list[i]["col_" + str(key)] = _list[i].pop(key)
return _list`
This function above convert numpy array to list of dict
counter = 0
def list_dict(dict_):
global counter
counter += 1
table_classname = "MyTableClass%s" % (counter)
class Meta:
attrs = {"class": "paleblue", 'width': '150%'}
cls = type(table_classname, (tables.Table,), dict(Meta=Meta))
list_ = dict_[0].keys()
for colname in list_:
column = tables.Column()
cls.base_columns[colname] = column
return cls
This code make a generic table...and
t = np.loadtxt(doc.document)
tab = convert_array_list_dict(t)
table = list_dict(tab)
table_content = table(tab)
RequestConfig(request, paginate={'per_page': 30}).configure(table_content)
return render(request,'app/snippets/upload_file.html',{'document':document,'table_content':table_content})
Above we can see how use all code...
Here's the class:
class MinerNotFullAction:
def __init__(self, entity, image_store):
self.entity = entity
self.image_store = image_store
def miner_to_ore(self, world, ore):
entity_pt = entities.get_position(self.entity)
if not ore:
return ([entity_pt], False)
ore_pt = entities.get_position(ore)
obj = point.Point(0, 0)
if obj.adjacent(entity_pt, ore_pt):
entities.set_resource_count(self.entity,
1 + entities.get_resource_count(self.entity))
remove_entity(world, ore)
return ([ore_pt], True)
else:
new_pt = next_position(world, entity_pt, ore_pt)
return (worldmodel.move_entity(world, entity, new_pt), False)
And here's the function that's in the same file, but it's outside of the class:
def miner_not_full_action(world, action, ticks):
entity = action.entity
entity_pt = entities.get_position(entity)
ore = find_nearest(world, entity_pt, entities.Ore)
(tiles, found) = MinerNotFullAction.miner_to_ore(world, entity, ore)
if found:
entity = try_transform_miner(world, entity, try_transform_miner_not_full)
schedule_action(world, entity,
create_miner_action(entity, action.image_store),
ticks + entities.get_rate(entity))
return tiles
If you look at the function, def miner_not_full_action, you'll see the line: (tiles, found) = miner_to_ore(world, entity, ore). Notice that inside this function, it is calling the method, miner_to_ore (from the class that I've provided above).
My question is, what is the correct way to rewrite this line of code so that the function can use this method from the class (even though the function itself is outside of the class)? Thanks!
You can only call methods of a class from outside if you either have an object of this class or can construct one. Except, if it is a static method or a class method.
In your example, you want to use something from
class MinerNotFullAction:
def __init__(self, entity, image_store):
self.entity = entity
self.image_store = image_store
def miner_to_ore(self, world, ore):
...
in
def miner_not_full_action(world, action, ticks):
entity = action.entity
entity_pt = entities.get_position(entity)
ore = find_nearest(world, entity_pt, entities.Ore)
(tiles, found) = MinerNotFullAction.miner_to_ore(world, entity, ore)
...
So, the question is: Do you have an appropriate ection object here?
If so (action sounds like an appropriate candidate), you can do
(tiles, found) = action.miner_to_ore(world, ore)
in order to perform your task.
See it from the other side: If you call this method, you must have something to be seen as self. This should be an instance of this class. If you don't have anything like that, you have to create one. Otherwise, self would make no sense in that method.
Easy example:
def miner_not_full_action(world, action, ticks):
# 1. call it via the class. That may or may not work, but you have to provide an action object as the first argument.
try1 = MinerNotFullAction.miner_to_ore(action, world, ore)
# 2. call it regularly (as already mentioned), equivalent to 1.
try2 = action.miner_to_ore(world, ore)
# If we don't have such an object? Then we create one:
ac = MinerNotFullAction()
# and use it to call:
try3 = ac.miner_to_ore(world, ore)