How to assign group after the ldap parameter? - python

I would like to assign to group after specific ldap parameter.
In Django I have other groups then in ldap.
I do something in signals.py, but i want do do the same effect in settings.py, because when I create a new groups i want change something in settings.py
I do this in signals.py ant it works
global group_name
if (gidNumber =='201'):
goup_name = 'a '
elif (gidNumber == '202'):
user.is_staff = True
group_name = 'b'
else:
group_name = 'c'
if(user.groups.filter(name=group_name).exists()!= True ):
group = Group.objects.get(name=group_name)
user.groups.add(gruop)
but i would ilke do this like smoething like this what i try do this in my settings.py
AUTH_LDAP_USER_FLAGS_BY_GROUP = {
"groups.filter(name='a')":
"gidNumber=201,uid=%(user)s,ou=People,dc=yy,dc=xx ",
}

The simplest answer is to do own dictionary in settings.py
LDAP_DICTIONARY = {
'201':'a',
'202':'b',
'203':'c'
}
AUTH_LDAP_USER_ATTR_MAP = {
'first_name' : 'gecos',
'last_name' : 'gidNumber',
}
and in signals.py assign property, but I have only first_name and last_name paremeters, so I gidNumber assign to last_name and clean this paremeter
gidNumber = user.last_name
user.last_name=' '
group_name =LDAP_DICTIONARY[gidNumber]
group = Group.objects.get(name=group_name)
user.groups.add(group)

Related

Resolver Not Receiving Arguments when Nested

I have a list of classes stored in memory that I am trying to parse through various types. It is referenced through the method get_inventory().
When I call the classes individually, they resolve as I would expect.
But when I try to nest one in the other, the value is returning null.
The code, followed by some examples:
class Account(graphene.ObjectType):
account_name = graphene.String()
account_id = graphene.String()
def resolve_account(
self, info,
account_id=None,
account_name=None
):
inventory = get_inventory()
result = [Account(
account_id=i.account_id,
account_name=i.account_name
) for i in inventory if (
(i.account_id == account_id) or
(i.account_name == account_name)
)]
if len(result):
return result[0]
else:
return Account()
account = graphene.Field(
Account,
resolver=Account.resolve_account,
account_name=graphene.String(default_value=None),
account_id=graphene.String(default_value=None)
)
class Item(graphene.ObjectType):
item_name = graphene.String()
region = graphene.String()
account = account
def resolve_item(
self, info,
item_name=None
):
inventory = get_inventory()
result = [Item(
item_name=i.item_name,
region=i.region,
account=Account(
account_id=i.account_id
)
) for i in inventory if (
(i.item_name == item_name)
)]
if len(result):
return result[0]
else:
return Item()
item = graphene.Field(
Item,
resolver=Item.resolve_item,
item_name=graphene.String(default_value=None)
)
class Query(graphene.ObjectType):
account = account
item = item
schema = graphene.Schema(query=Query)
Let's assume I have an account foo that has an item bar. The below queries return the fields correctly.
{
account(accountName:"foo") {
accountName
accountId
}
}
{
item(itemName: "bar") {
itemName
region
}
}
So if I wanted to find the account that has the item bar, I would think I could query bar and get foo. But it returns the account fields as null.
{
item(itemName: "bar") {
itemName
region
account {
accountId
accountName
}
}
}
Recall that as part of resolve_item, I am doing account=Account(account_id=i.account_id) - I would expect this to work.
If I alter the last return statement of resolve_account to the below, accountId always returns yo.
...
else:
return Account(
account_id='yo'
)
So this tells me that my resolver is firing, but the invocation in resolve_item is not passing account_id properly.
What am I doing wrong?
This is because the arguments on a field are only available to its immediate children. If you need to retrieve the argument in nested elements, your top level resolver needs to return the argument as part of the source and your nested element can access it arguments now from the source object.
From what I am seeing, it looks like rather than being passed in as an argument, account_id is being stored already as part of account in the ObjectType.
So if I add the below, I can get to the result that I want.
account_id = account_id if getattr(self, "account", None) is None else self.account.account_id

api.constrain for give condition if one of field is empty

I tried to use api.constrain in odoo. The case is, I want to give condition to odoo if user missing one field, odoo will give some warning like alert, and user have to give some input to the previous field. This is my code :
class Provinc(models.Model):
_name = 'provinsi.model'
_rec_name ='prov'
prov = fields.Char(
string='Provinsi',
)
res_partner_ids = fields.One2many(
'res.partner',
'provinsi'
city_id = fields.One2many(
'city.model',
'provinsi_id'
)
class city(models.Model):
_name = 'kota.model'
_rec_name ='city'
city = fields.Char(
string='City',
)
res_partner_city = fields.One2many(
'res.partner',
'city'
)
provinsi_id = fields.Many2one(
'provinsi.model',
string='provinsi',
)
class Master_data(models.Model):
_inherit = 'res.partner'
provinsi = fields.Many2one(
'provinsi.model',
'provinsi',
)
city = fields.Many2one(
'city.model',
'city',
)
#api.onchange('provinsi')
def show_provinsi(self):
return {'domain': {'city': [('provinsi_id', '=', self.provinsi.id)]}}
#api.constrains('provinsi')
#api.onchange('city')
def show_kota(self):
for record in self:
if record.provinsi == False:
raise ValidationError("is gonna be error")
I have tried 2 ways. First, I put the api.constrain insode class City, and it's doesn't work,second ways I tried put the api.constrain like the code inside class master, and the result remains the same.
you only need onchang not any constrains to display warning!
#api.onchange('city')
def show_kota(self):
if self.city and not self.provinsi:
raise ValidationError("is gonna be error")
now if you select value in city field and provinsi missing value then it will display error msg
guessing field "city" and "provinsi" is in 'res.partner' form view!
If you want to check a field value is empty or not, just use required ="1" like:
<field name="provinsi" required="1"/>

Odoo : Value in one2many doen't change in api.depends

I have 3 models, here is the interesting part of each:
vote:
class vote(osv.osv)
_name = 'vote'
_columns = {
name = fields.many2one('res.partner',
'Member of enterprise',
select=True),
type = fields.interger('Type'),
}
history_line:
class history_line(osv.osv)
_name = 'history_line'
_columns = {
fieldsA = fields.integer('First field'),
fieldB = fields.integer('Second field'),
this_id = fields.many2one('res.partner', 'link to res'),
}
res_partner:
class res_partner(osv.osv)
_inherit = 'res.partner'
_columns = {
vote_partner_ids = fields.one2many('vote',
'name',
'Voted peoples',
select=True),
vote_history_ids = fields.one2many('history.line',
'this_id',
compute='compute_type',
string='History of votes'),
}
#api.multi
#api.depends('vote_partner_ids.type')
def compute_type(self):
for record in self:
if self.vote_partner_ids.type:
record.vote_history_ids = [(0, 0, {'self.vote_history_ids.fieldA': self.vote_partner_ids.type + 4,
'self.vote_history_ids.fieldB': self.vote_partner_ids.type - 2})]
Their is also a default value for a new history_line (fieldA = 1 when you don't do anything, fieldB = -1 when you don't do anything for exemple)
I can't move my compute function elsewhere because lot of stuffs are computed here.
The problem is : When I modify type in vote, a new history line will be created, but with the defaults values. I can't make the values be anything else. (even If I put directly a value, like 10)
So why are the default values choose, even if I asked them to being computed, but it still understand it has to create a new tuple?
You don't have to make the "PATH" to the fields you'd like to change, remove self.vote_history_ids. in the depends before the fields to change:
#api.multi
#api.depends('vote_partner_ids.type')
def compute_type(self):
for record in self:
if self.vote_partner_ids.type:
record.vote_history_ids = [(0, 0, {'fieldA': self.vote_partner_ids.type + 4,
'fieldB': self.vote_partner_ids.type - 2})]

domain filter for many2one fields in odoo?

Below code is asset inherited class . Here i will add 'place' field with 'Karn/Bang/Kengeri' and 'karn/bang/malleshwaram' for 'Karn/Bang/Kengeri' will add 'asset_catg_id' with A and B. then for 'karn/bang/malleshwaram' with Y and Z.
Now at calander inherited class . if i select 'place' with 'Karn/Bang/Kengeri' then next field 'asset_catg_id' i have to get only A and B drop down list. if again 'karn/bang/malleshwaram' then i have to get only Y,Z options . and previous selected 'asset_catg_id' values should get deleted . i have tried with domain filter option got keyvalue error
class asset_asset(osv.osv):
_inherit = "asset.asset"
#_name = "asset_asset"
_rec_name= "folio_num"
_columns = {
'name': fields.char('Asset Name', size=64),
'place': fields.many2one('asset.parentlocation', 'Location'),
'asset_catg_id' : fields.many2one('asset.catg', 'Asset Catg Selection', select=True, required=True),}
class asset_catg(osv.Model):
_name="asset.catg"
_rec_name='name1'
_description="Define Asset Catgs"
_columns={ 'name1':fields.char('Asset Catg Names',size=64,required=True),}
asset_catg()
class asset_parentlocation(osv.osv):
_name="asset.parentlocation"
_rec_name="location_name"
_columns = {
'location_name' : fields.char('Asset Location', required=True),
'parent_location' : fields.many2one('asset.parentlocation','Parent Location'),
'nameee':fields.many2one('ir.attachment','Attachments'),}
def name_get(self, cr, uid, ids, context=None):
if context is None:
context = {}
if not ids:
return []
reads = self.read(cr, uid, ids, ['location_name','parent_location'], context=context)
res = []
for record in reads:
name = record['location_name']
if record['parent_location']:
name = record['parent_location'][1]+' / '+name
res.append((record['id'], name))
return res
**Following code is calendar inherited class**
class calendar_event(osv.osv):
_inherit = "calendar.event"
_rec_name = 'number'
_columns = {
'number' : fields.char('Meeting ID',readonly=1),
#'place' : fields.many2one('stock.location','Substation Location',),
'place' : fields.many2one('asset.parentlocation','Substation Location',),
#'location' : fields.selection(STATUS_SELECTION,'Location', default='Board A'),
'asset_catg_id' : fields.many2one('asset.catg','Asset Catg Selection', domain="[('asset_catg_id', '=',place)]"),}
First your domain is wrong in a principle. Domain is what is "inside" a field, in other words in its model (for example field name or id in asset.catg model). So you should fix that one first.
If domain depends on another field, you can use onchange method to return domain (used placeholder place_id). Like this:
#api.onchange('place')
def onchange_place(self):
res = {}
if self.place:
res['domain'] = {'asset_catg_id': [('place_id', '=', self.place.id)]}
return res
P.S. This is example with new v8 api, but same principle applies to old api (you then don't nee to use decorator, also add cr, uid, ids on method and call it through your view. All of this not needed for new api). As it looks like you are still developing on old api.
Update
For old api:
def onchange_place(self,cr, uid, ids, place, context=None):
res = {}
if self.place: #on old api it will return id, instead of record
res['domain'] = {'asset_catg_id': [('place_id', '=', self.place)]}
return res
And then in your view (don't know what kind of view you are using):
<field name="place" on_change="onchange_place(place)"/>
Still you need to define some field in asset.catg so it would be used to match place field. For example:
'place_id': fields.many2one('asset.parentlocation', 'Place')
And then when you define asset category, you set which Place it should belong to. Then when you choose place calendar.event, onchange method will set domain on asset_catg_id field correctly.

mongoengine OperationError on saving

I'm writing a python script to populate a mongodb database, my models look like the following:
from mongoengine import *
from mongoengine.django.auth import User
class TrackGroup (Document):
name = StringField(required=True)
users = ListField(ReferenceField('User'))
devices = ListField(ReferenceField('Device'))
class Device(Document):
name = StringField(max_length=50, required=True)
grp = ListField(ReferenceField(TrackGroup))
class User(User):
first_name = StringField(max_length=50)
last_name = StringField(max_length=50)
grp = ListField(ReferenceField(TrackGroup))
And my script goes like this:
#Create a group
gName = 'group name'
g = TrackGroup(name=gName)
g.users = []
g.devices = []
g.save()
#create a user
u = User.create_user(username='name', password='admin', email='mail#ex.com')
gRef = g
u.grp = [gRef, ]
u.first_name = 'first'
u.last_name = 'last'
u.save()
gRef.users.append(u)
gRef.save()
#create a device
dev = Device(name='name').save()
gRef = g
dev.grp = [gRef, ]
dev.save()
gRef.devices.append(dev)
gRef.save() #Problem happens here
The problem happens when I call gRef.save() I get the following error:
raise OperationError(message % unicode(err))
mongoengine.errors.OperationError: Could not save document (LEFT_SUBFIELD only supports Object: users.0 not: 7)
I looked around for a while, and here it says that this means I'm trying to set a filed with an empty key, like this: (The example is from the link above, not mine)
{
"_id" : ObjectId("4e52b5e08ead0e3853320000"),
"title" : "Something",
"url" : "http://www.website.org",
"" : "",
"tags" : [ "international"]
}
I don't know where such a field can come from, but I opened a mongo shell and looked at my documents from the three collections, and I couldn't find such a field.
Note: If I add the device first, the same error occurs while saving the group after adding the user.
I had the same error, and this trick work for me:
the_obj_causing_error.reload()
/* make some change */
the_obj_causing_error.price = 5
the_obj_causing_error.save()
just try reload() the object before changing it.

Categories

Resources