How to call a function inside a function ?Odoo9 Validation - python

I have a added a boolean field in product.pricelist.item
class product_pricelist_item(models.Model):
_inherit = 'product.pricelist.item'
myfield = fields.Boolean(string="CheckMark")
Now there are multiple lines in product.pricelist.item.
(Validation)
I want that the user is not allowed to make True multiple myfield one one field can be True at a time.
I tried doing this in product.pricelist.item by giving it a counter and passing the counter the number of myfields which are True.
But this is giving me error.
global name '_get_counter' is not defined
def _get_counter(self):
for r in self:
p=[]
p= r.env['product.pricelist.item'].search_read([('myfield', '=', True)], ['myfield'])
counter = len(p)
return counter
#api.constrains('myfield')
def _check_myfield(self):
counter = _get_counter(self)
for r in self:
if counter > 1:
raise exceptions.ValidationError("Multiple myfield In a PriceList of a Product is not allowed.")
Now the second question is :-
When you create a pricelist-item and click save in pricelist then it does not reflect the data in the database. When you click the pricelist save it reflects the data...why is this so ?

With self we can call method of current class.
Try with following code:
Replace code
counter = _get_counter(self)
with
counter = self._get_counter()

The loop in _get_counter does not affect the result and the search did not depend on records so you can use:
def _get_counter(self):
pricelist_obj = self.env['product.pricelist.item']
counter = len(pricelist_obj.search_read([('myfield', '=', True)], ['myfield']))
return counter
#api.constrains('myfield')
def _check_myfield(self):
counter = self._get_counter()
if counter > 1:
raise exceptions.ValidationError("Multiple myfield In a PriceList of a Product is not allowed.")

Related

invoking user_name variable outside function and class

I want to access the user_name variable outside function and class also how to do this?
Here is my Code
def DocumentCreateView(request):
user_name = request.user.email
print(user_name)
int_rep = int(rep_no)
flag = 1
count = 0
i = 1
j = 0
This is code where i want to access user_name outside class and function
path_to_piepline1 = "lazy-test/users/"+**user_name**+"/input"
print("--- first argument ---", path_to_piepline1)
You should return it:
def DocumentCreateView(request):
user_name = request.user.email
print(user_name)
int_rep = int(rep_no)
flag = 1
count = 0
i = 1
j = 0
return user_name
And then call this function:
user_name = DocumentCreateView(<pass your argument here>)
path_to_piepline1 = "lazy-test/users/"+ user_name +"/input"
If, however, you don't return it in any form (on its own or alongside other data), and it remains local, there will be no way to access it after the function returns.
Create an object of the class and use it to call the function and return the value of username.

Loop through One2Many records Odoo 10

I am trying to loop through my One2Many records to avoid duplication.
class sales_target(models.Model):
_name = 'sales.target'
_description = 'Sales Target'
name = fields.Char(string='Name',required=True)
from_date = fields.Date(string='From Date',required=True)
to_date = fields.Date(string='To Date',required=True)
sales_team = fields.Many2one('crm.team',required=True)
sales_record_ids = fields.One2many('sales.target.record','sales_target_rec_id',string='Sales Record')
#api.one
def check_duplication(self,result):
count = 0
if self.sales_record_ids:
for record in self.sales_record_ids:
if result.id == record.sales_person_p_id:
count = 1
if count == 0:
self.write({'sales_record_ids':[(0,0,{'sales_person':result.name})]})
#api.one
def get_sales_person(self):
for res in self.sales_team.member_ids:
self.check_duplication(res)
The other class is as:
class sales_target_record(models.Model):
_name = 'sales.target.record'
sales_target_rec_id = fields.Many2one("sales.target")
sales_person = fields.Char(string='Sales Person',readonly=True,required=True)
sales_person_p_id = fields.Char(compute='get_value',store=True)
#api.onchange('sales_person')
#api.depends('sales_person')
def get_value(self):
res = self.env['res.partner'].search([('name','=',self.sales_person)])
self.sales_person_p_id = res[0].id
Now when I am hitting the button i still have duplicate records. However I tried to compare with name and things work good but I cannot compare with names since its not correct because names can be same but id cannot. That function was as:
#api.one
def check_duplication(self,result):
count = 0
if self.sales_record_ids:
for record in self.sales_record_ids:
if result.name == record.sales_person:
count = 1
if count == 0:
self.write({'sales_record_ids':[(0,0,{'sales_person':result.name})]})
Hope for guidance on this.
Can you try like this
#api.multi
def check_duplication(self,result):
if self.sales_record_ids:
for record in self.sales_record_ids:
if not result.name == record.sales_person:
self.write({'sales_record_ids':[(0,0,{'sales_person':result.name})]})
Concluding from the fact that for name it works properly, something might be wrong with your if condition.
sales_person_p_id is of type char, however you seem to compare it with an integer: result.id.
Have you made sure that both objects in your if condition are of the same type?
Try to make sales_person_p_id an integer field (e.g. via sales_person_p_id = fields.Integer(compute='get_value',store=True) or do some kind of type casting before comparing the objects.

Setting up a counter to know in which number to start

I want the following counter to check the order num class inside a dictionary thats inside a list.
...code...
self.counter = count(1)
def submit(self):
if Database.xoomDatabase[0]["Num Orden"] == next(self.counter):
self.counter = Database.xoomDatabase["Num Orden"]
Database.xoomDatabase.append(ordenOrganiz)
The reason I'm doing this type of counter is because I'm dumping a pickle file everytime the app closes, that contains Database.xoomDatabase. When the app is executed, the pickle dump gets loaded and all the dictionaries inside of it get pushed back into Database.xoomDatabase. This is the dictionary that's saved on Database.xoomDatabase:
global ordenOrganiz
ordenOrganiz = {"Num Order": nicenum,
"Nombre": nombre,
"Email": email,
"Num Tel/Cel": num,
"Orden Creada:": fechacreacion1,
"Fecha de Entrega": fechaentrega}
print(ordenOrganiz["Nombre"])
return dict(ordenOrganiz)
My questions is: How can I start the counter in exactly the last "Order Num" the is loaded from the pickle dump file?
EDIT:
This is how, with the help of Anand S Kumar, I got it it to work:
if len(Database.xoomDatabase) == 0:
newCount = 0
else:
newCount = max(Database.xoomDatabase, key = lambda x:x['Num Orden'])["Num Orden"]
nombre = contents1
nicenum = int(newCount) + 1
This loop checks if there are any saved dictionaries on the list. If there ar no dics., the count starts at 1. If there are already saved dics., the count will start from the last "Orden Num"(Order Number) saved into the pickle dump.
xoomDatabase = []
if path.isfile(file_path) == False:
open(file_path, "w").close()
else:
loadLis = open(file_path, "rb")
dalis = pickle.load(loadLis)
loadLis.close()
xoomDatabase.extend(dalis)
This loops check if there is any file to load, if there isn't, it cretes one. If there's already a saved pickle dump, then it will load the list with previously saved dicts.
You can create a class variable directly inside the class, and then access it using Class.<variable> and also in __init__() function use this Class.<variable> to initialize the counter for each variable and increment the counter.
Example -
class TempClass
counterInit = 0
def __init__(self):
self.counter = TempClass.counterInit
TempClass.counterInit += 1
...
And then at the start of the program, read back the data from the pickle dump and then take the largest counter and set it to counter as given in below example.
Example -
TempClass.counterInit = max(Database.xoomDatabase, key = lambda x:x['Num Orden'])
The above max() gives the largest Num Orden from the list of dictionaries.

Django-tables2: Provide a list of dictionary, how to generate a column for each dictionary entry

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...

Run condition in GAE datastore

class ModelCount(db.Model):
type = db.StringProperty(required=True,default='Default-type')
count = db.IntegerProperty(required=True, default=0) #Current counter
def to_dict(self):
d = dict([(p, unicode(getattr(self, p))) for p in self.properties()])
d["id"] = self.key().id()
return d
#Increments counter
#staticmethod
def increment_counter(en_name):
modelCount = ModelCount.all().filter('type',en_name).get()
if modelCount:
modelCount.count += 1
modelCount.put()
else:
modelCount = ModelCount(type=en_name, count=1)
modelCount.put()
In the above code (increment_counter), I am reading the count from ModelCount and incrementing it by one. I face run condition in increment_counter method when the server receives multiple requests. So I want to make increment_counter atomic. If I use #db.transactional on increment_counter, I get "Only ancestor queries are allowed inside transactions" error.
How can I fix this and make it atomic?
you could try to use sharding https://developers.google.com/appengine/articles/sharding_counters
full source available at https://github.com/GoogleCloudPlatform/appengine-sharded-counters-python

Categories