insert a data into mysql database if the field valus is change - django

I have developed a code for update a database,but right now I want to code if the value is change the database insert the data not update the database.Here is my code:-
def update_Sprint(self, ps):
id = ps.projectid
data=requests.get('https://example.com/api/v1/xyz/'+str(ps.projectid)+'/Iterations?include=[Id,Name,StartDate,EndDate,UserStories-Effort-Sum,UserStories-EffortCompleted-Sum]&token='+settings.AUTH_TOKEN+'&format=json')
data=json.loads(data.text)
data=data['Items']
if len(data)>0:
for data_ in data:
sprint_id=str(data_['Id']
sps = Day.objects.filter(sprintid=sprint_id, project__projectid=ps.projectid)
print ' creating new sprint '+str(sprint_id)
sp = Day(sprintid=sprint_id, project=ps)
sp = update_model(sp, sprint_name = Name,sprint_end_date = EndDate, sprint_start_date = StartDate, usesteff_sum = Effor_Sum,usesteffc_sum = Effort_Com,)
#self.update_story(sp)
#self.update_Bug(sp)
def update_model(obj, **params):
"""
:param obj: generic model object
:param params: fields, value dict of the obj's model
:return: updated object
"""
is_updating = False
for key in params:
try:
field = getattr(obj, key)
value = params[key]
if field==value:
print 'same value'
elif ((not value) and (not field)): print 'No value for '+key
else:
print 'updating value'
is_updating = True
setattr(obj, key, value)
# obj.field = value
except AttributeError as ex:
print ex
if is_updating:
obj.save()
return obj
How can I insert the data into database if the field and value are not same.I don't want to update the table.

Related

Odoo on write() method check many2many relation

I have 2 classes:
class my_request(models.Model):
_name = 'my.request'
_inherit = ['mail.thread', 'ir.needaction_mixin']
supply_ids = fields.Many2many(comodel_name='supply.conditions',
relation='purchase_supply_rel',
column1='purchase_requests_id', column2='supply_conditions_id',
string='Supply Conditions')
and
class SupplyConditions(models.Model):
_name = 'supply.conditions'
vendor = fields.Char(string='Vendor', required=True)
quantity = fields.Char(string='Quantity', required=True)
request_id = fields.Many2one('my.request', 'My request')
name = fields.Many2one('my.request.line', string='Product', required=True)
currency_id = fields.Many2one('res.currency', string='Currency', default=_get_default_currency)
supply_rel_id = fields.Boolean(string='Relation field', default=False)
my.request class part of form view xml:
<page string="Order">
<field name="supply_ids" domain="[('purchase_id', '=', id)]"/>
</page>
When I select values from my.request form view and click on Save button I call write() method and at that time insert m2m values (if there is selected values) into relational table (purchase_supply_rel).
I want to add check if purchase.request id is in purchase_supply_rel table in purchase_requests_id field when I click on Save button. My function. Changes after # my new code coment:
#api.multi
def write(self, vals):
res = super(PurchaseRequest, self).write(vals)
for request in self:
if request.state != 'draft':
if vals.get('assigned_to'):
self.message_subscribe_users(user_ids=[request.assigned_to.id])
# my new code
test = self.env['purchase.request'].search([(self.id,'in','supply_ids')])
_logger.warning("test " + str(test));
return res
But I got an error:
File "/opt/odoo/openerp/osv/expression.py", line 586, in check_leaf
raise ValueError("Invalid leaf %s" % str(self.leaf))
ValueError: Invalid leaf (348, 'in', 'supply_ids')
How else I can check this? And what I am doing wrong?
UPDATE:
I need to get test value smth like this: purchase_request(245,352)
245,352 - ids of purchase.request class
You can not add dynamic value in domain in place of field name.
Domain is a list of tuples. Domain contains three portions in tuple.
Domain:
[('field_name','operator','values')]
So dynamic value is not allowed in field name in domain.
#api.multi
def write(self, vals):
res = super(PurchaseRequest, self).write(vals)
for request in self:
if request.state != 'draft':
if vals.get('assigned_to'):
self.message_subscribe_users(user_ids=[request.assigned_to.id])
# my new code
test = self.env['purchase.request'].search([('supply_ids','in',self.ids)])
_logger.warning("test " + str(test));
return res

django - compare two objects [using fields dynamically]

I need compare two objects, to determine if a field has changed or not
class Country(models.Model): # country code 'MX' -> Mexico
code = models.CharField(max_length=2)
name = models.CharField(max_length=15)
class Client(models.Model): # id=1, name=pedro, country.code=MX, rfc=12345
name = models.CharField(max_length=100)
country = models.ForeignKey(Country)
rfc = models.CharField(max_length=13)
> obj_db = Client.object.get(id=1)
> country = Country.objects.get(code='MX')
obj_no_db = Client(**{'id':1, 'name':'pedro', 'country': country, 'rfc':12345})
> obj_db == obj_no_db # True
> obj_no_db = Client(**{'id':1, 'name':'pedro', 'country': country, 'rfc':1})
> obj_db == obj_no_db # True # but isn't True because the rfc has change, how can compare field by field
> obj_db.rfc == obj_no_db.rfc # False I expected this result
I need to build a function to do it generic, the problem i don't found information about it, i think i can use the ._meta options, but i'm not sure.
I developed this function but i can't discover the way to compare field by field.
def get_insert_update(obj, key, obj_list, fields=None, exclude_fields=None):
"""
:param obj: The object for compare
:param key: a the key for compare to determine if we need to update or insert
:param obj_list: list objects to compare
:return: to_insert, _update
"""
db = {}
to_insert = []
to_update = []
if key == 'pk': # the field pk doesn't exists so we change to id, because its the same
key = 'id'
exclude_fields = exclude_fields or []
fields = fields or []
if 'pk' in fields:
fields[fields.index('pk')] = 'id' # we change the field pk, because it doesn't exists
if 'pk' in exclude_fields:
exclude_fields[exclude_fields.index('pk')] = 'id' # we change the field pk, because it doesn't exists
meta = obj._meta # we define meta object
if fields is None:
fields = meta.get_all_field_names()
fields = [f for f in meta.fields if f.attname in fields]
# dumping db into memory
for _obj in obj.objects.all():
if isinstance(key, list): # first check if is a list to create a custom key
_key = _get_key(_obj, key)
else:
_key = _obj.__dict__[key]
# if exclude fields exists
if exclude_fields:
d = {f.attname: _obj.__dict__[f.attname] for f in fields if f.attname not in exclude_fields}
db[_key] = obj(**d)
else: # we save the full object
db[_key] = _obj
# read local objects to determine if the record will be insert or update
for _obj in obj_list:
if isinstance(key, list): # first check if is a list to create a custom key
_key = _get_key(_obj, key)
else:
_key = _obj.__dict__[key]
if _key in db: # if the key is in db so we check if it equal
# if _obj.pk == 6: # debug
# print(_obj.__dict__, db[_key].__dict__, _obj.__dict__ == db[_key].__dict__)
if _obj != db[_key]: # HERE i need the determine if the fields are equal or not.
to_update.append(_obj) # if the object has changed, we update it
else:
pass # if the object is equal, we didn't do it anything
else:
to_insert.append(_obj) # because we didn't found into the database, we create it
return to_insert, to_update
def _get_key(obj, lst):
"""
create a string key using multiples keys
Example: obj.id -> 1, obj.name -> 'foo'
lst['id', 'name']
:param lst: list of keys
:return: 1_foo
"""
k = []
for t in lst:
k.append(str(obj.__dict__[t]))
return "_".split(k)
Django's Model class defines the __eq__ method to compare based on the value of the pk attribute, which is why your models compare equal.
One simple way to do this would be to override that method on your own model to compare the value of the __dict__, which contains all the instance's values.
There's a slight gotcha with this, in that __dict__ also contains a hidden _state object that will be compared by ID, so you'd need to filter that out of the comparison.
def __eq__(self, other):
values = [(k,v) for k,v in self.__dict__.items() if k != '_state']
other_values = [(k,v) for k,v in other.__dict__.items() if k != '_state']
return values == other_values

Many to one relation not working in fields.selection() in openerp

I need to create a selection field in openerp , it's values should load from a function and also this field needs many2one relation with another table.I have created the selection field and values are loaded from the function but many2one relation not working in it.below given is my code.
def _sel_proj(self, cr, uid, context=None):
cr.execute("""SELECT project.id,account.name FROM project_project project
LEFT JOIN account_analytic_account account ON
account.id = project.analytic_account_id
LEFT JOIN project_user_rel rel ON rel.project_id = project.id
WHERE (account.user_id = %s or rel.uid = %s)
GROUP BY project.id,account.name"""%(uid, uid))
return [(r[0],r[1]) for r in cr.fetchall()]
_name = 'mat.mgmt'
_columns = {'project_id':fields.selection(_sel_proj,string='Project',type="many2one",relation="project.project",select="true",required="true"),}
change the field project_id to many2one and in the view for the field add widget='selection'.
in python:
_columns = {'project_id':fields.many2one('project.project','Project',select="true",required="true"),}
in xml:
<field name="project_id" widget="selection"/>
then override the fields_view_get function and add the filter condition for project_id. For example
def fields_view_get(self, cr, uid, view_id=None, view_type=False, context=None, toolbar=False, submenu=False):
if context is None:context = {}
res = super(<your_class_name>,self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu)
for field in res['fields']:
if field == 'project_id':
cr.execute("""SELECT project.id,account.name FROM project_project project
LEFT JOIN account_analytic_account account ON
account.id = project.analytic_account_id
LEFT JOIN project_user_rel rel ON rel.project_id = project.id
WHERE (account.user_id = %s or rel.uid = %s)
GROUP BY project.id,account.name"""%(uid, uid))
project_select = [(r[0],r[1]) for r in cr.fetchall()]
res['fields'][field]['selection'] = project_select
return res

Django Form Validation Problem

I have a form that seems to never validate. The form is just three drop-down boxes. When the form is rendered, all of the boxes have values populated and the first is selected, so no matter what, the user cannot submit bad values, yet form.is_valid() always returns false. Please help!
The form
CLUSTER_TYPES = (
('ST', 'State'),
('CNT', 'County'),
('FCD', 'Congressional District'),
('GCC', 'Circle Clustering'),
);
MAP_VIEWS = (
('1', 'Single Map'),
('2', 'Two Maps'),
('4', 'Four Maps'),
);
class ViewDataForm (forms.Form):
def __init__ (self, sets = None, *args, **kwargs):
sets = kwargs.pop ('data_sets')
super (ViewDataForm, self).__init__ (*args, **kwargs)
processed_sets = []
for ds in sets:
processed_sets.append ((ds.id, ds.name))
self.fields['data_sets'] = forms.ChoiceField (label='Data Set', choices = processed_sets)
self.fields['clustering'] = forms.ChoiceField (label = 'Clustering',
choices = CLUSTER_TYPES)
self.fields['map_view'] = forms.ChoiceField (label = 'Map View', choices = MAP_VIEWS)
The view
def main_view (request):
# We will get a list of the data sets for this user
sets = DataSet.objects.filter (owner = request.user)
# Create the GeoJSON string object to potentially populate
json = ''
# Get a default map view
mapView = MapView.objects.filter (state = 'Ohio', mapCount = 1)
mapView = mapView[0]
# Act based on the request type
if request.method == 'POST':
form = ViewDataForm (request.POST, request.FILES, data_sets = sets)
v = form.is_valid ()
if form.is_valid ():
# Get the data set
ds = DataSet.objects.filter (id = int (form.cleaned_data['data_set']))
ds = ds[0]
# Get the county data point classifications
qs_county = DataPointClassification.objects.filter (dataset = ds,
division = form.cleaned_data['clustering'])
# Build the GeoJSON object (a feature collection)
json = ''
json += '{"type": "FeatureCollection", "features": ['
index = 0
for county in qs_county:
if index > 0:
json += ','
json += '{"type": "feature", "geometry" : '
json += county.boundary.geom_poly.geojson
json += ', "properties": {"aggData": "' + str (county.aggData) + '"}'
json += '}'
index += 1
json += ']}'
mapView = MapView.objects.filter (state = 'Ohio', mapCount = 1)
mapView = mv[0]
else:
form = ViewDataForm (data_sets = sets)
# Render the response
c = RequestContext (request,
{
'form': form,
'mapView_longitude': mapView.centerLongitude,
'mapView_latitude': mapView.centerLatitude,
'mapView_zoomLevel': mapView.zoomLevel,
'geojson': json,
'valid_was_it': v
})
return render_to_response ('main.html', c)
You have overridden the signature of the form's __init__ method so that the first positional parameter is sets. However, when you instantiate it, you pass request.POST as the first positional argument - so the form never gets any data, so doesn't validate.
Don't change the signature of __init__. In fact, you have everything set up correctly so you don't need to: just remove the sets=None from the method definition, and it should all work.

Control Query set in Django (filter,object Q)?

Base On URL
querydict = {customer_type:val1,tag:[], city:[],last_contact:valdate}
show/?customer_type=All&tag=2,3&city=3&last_contact=29/12/2009
I am going to filter by made the method:
def get_filter_result(customer_type, tag_selected, city_selected, last_contact_filled):
if customer_type=has value:
I filter by this
#queryset = Customer.objects.filter(Q(type__name=customer_type))
if tag = has value :
I filter by this
#queryset = Customer.objects.filter(Q(type__name=customer_type)
Q(type__name=tag))
if city = has value:
I filter by this
#queryset = Customer.objects.filter(Q(type__name=customer_type)
Q(type__name=tag),
Q(type__name=city))
if last_contact = has value:
I filter by this
#queryset = Customer.objects.filter(Q(type__name=customer_type)
Q(type__name=tag),
Q(type__name=city),
Q(type__name=last_contact))
Anybody Help give an idea to implement my method more simple and flexible than this?
if value of them are missing or equal None(No value is passed)
so if... else.... condition will control alots of time and code will be larger..
for example :
show/?customer_type=All&tag=&city=&last_contact=
show/?customer_type=All&tag=2,3&city=3&last_contact=29/12/2009
show/?customer_type=&tag=2,3&city=3&last_contact=
show/?customer_type=All&tag=2,3&city=&last_contact=29/12/2009
thanks
def get_filter_result(customer_type=None, tag_selected=None, city_selected=None, last_contact_filled=None):
qdict = {}
if customer_type is not None:
qdict['type__name'] = customer_type
if tag is not None:
<repeat as appropriate>
queryset = Customer.objects.filter(**qdict)
If you want to AND all your queries (like in your example), you can create dictionary of parameters, and then call filter method with this dictionary as an argument:
def get_filter_result(**kwargs):
params = {}
#delete items with empty strings
for key in kwargs:
if kwargs[key]:
params[key] = kwargs[key]
queryset = Customer.objects.filter(**params)