How to exclude fields in get_fieldsets() based on user type in Django admin - django-admin

I'm trying to use get_fieldsets to organize admin model pages. Using fieldsets is pretty satisfying, but I'm stuck with how to exclude some fields. Currently, I used if condition to check user type, and then return different fieldsets based on user type. I'm having the same codes to be repeated because of that. Is there a way to exclude a few fields in get_fieldsets?
admin.py
class StoreAdmin(admin.ModelAdmin):
...
def get_fieldsets(self, request, obj=None):
fieldsets = copy.deepcopy(super(StoreAdmin, self).get_fieldsets(request, obj))
if request.user.is_superuser:
return (
[
('Basic Information', {
'fields': (
('status', 'review_score', 'typ'),
('businessName', 'relatedName'),
('mKey'),
)
}),
('Additional Options', {
'fields': (
('affiliate_switch', 'is_affiliated', 'affiliate',),
)
}),
]
)
else:
return (
[
('Basic Information', {
'fields': (
('status', 'review_score', 'typ'),
('businessName', 'relatedName'),
('mKey'),
)
}),
]
)

If you only want to exclude fields you can use get_fields instead as following:
def get_fields(self, request, obj=None):
fields = super(ClientAdmin, self).get_fields(request, obj)
if obj:
fields_to_remove = []
if request.user.is_superuser:
fields_to_remove = ['field1', 'field2', 'etc', ]
for field in fields_to_remove:
fields.remove(field)
return fields
Edit:
Same logic could be used for get_fieldsets

My way to solve this:
def get_fieldsets(self, request, obj=None):
fieldsets = super(AccountInline, self).get_fieldsets(request, obj)
fields_to_remove = ['field1', 'field2', 'etc', ]
if request.user.is_superuser:
# select your way, my:[3][1]
fieldsets[3][1]['fields'] = tuple(x for x in fieldsets[3][1]['fields'] if not x in fields_to_remove)
return fieldsets

Related

How to write fields many2one in Odoo with XMLRPC

I want to use the xmlrpc for the model "product.category".
How to write the field "categ_id" with "read and search"in PYTHON ? I have always an error. I need to do that because i have to transfer this informations into another database Odoo.
import xmlrpc.client
import time
url_db1="http://localhost:8069"
db_1='DB_ONE'
username_db_1='username'
password_db_1='password'
common_1 = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url_db1))
models_1 = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url_db1))
version_db1 = common_1.version()
print("details..", version_db1)
url_db2="http://localhost:806972"
db_2='DB_2'
username_db_2='myemail'
password_db_2='mypassword'
common_2 = xmlrpc.client.ServerProxy('{}/xmlrpc/2/common'.format(url_db2))
models_2 = xmlrpc.client.ServerProxy('{}/xmlrpc/2/object'.format(url_db2))
version_db2 = common_2.version()
print("details..", version_db2)
uid_db1 = common_1.authenticate(db_1, username_db_1, password_db_1, {})
uid_db2 = common_2.authenticate(db_2, username_db_2, password_db_2, {})
db_1_categories = models_1.execute_kw(db_1, uid_db1, password_db_1, 'product.category', 'search_read', [[]], {'fields':['id','name', 'parent_id']})
total_count = 0
for category in db_1_categories:
print("category..", category)
total_count +=1
values = {}
values['id'] = category['id']
values['name'] = category['name']
if category['parent_id']:
values['parent_id'] = category['parent_id'][0]
new_lead = models_2.execute_kw(db_2, uid_db2, password_db_2, 'product.category', 'create', [values])
print("Total Created..", total_count)
This is the error :
ValidationError: ('The operation cannot be completed: another model requires the record being deleted. If possible, archive it instead.\n\nModel: Product Category (product.category), Constraint: product_category_parent_id_fkey', None)\n'>
The method name should be search_read
Example:
models.execute_kw(db, uid, password,
'product.template', 'search_read',
[],
{'fields': ['name', 'default_code', 'categ_id']})
It should return a list of dicts, the categ_id field value is a list of two values, the first is the id of the category and the second is the name of the category.
To write categ_id, you just need to provide the category ID to the write method.
Example:
product_template_data = [{'default_code': 'FURN_6666', 'categ_id': [8, 'All / Saleable / Office Furniture'], 'id': 23, 'name': 'Acoustic Bloc Screens'}, ...]
for ptd in product_template_data:
models.execute_kw(db, uid, password, 'product.template', 'write',
[[ptd['id']],
{
'categ_id': ptd['categ_id'][0],
...
}
])
You mentioned that you need to transfer data to another database, the product template is probably not present which means that you can't call the write method instead, you can call the create method.
Example:
id = models.execute_kw(db, uid, password, 'product.template', 'create', [{
'categ_id': ptd['categ_id'][0],
...
}])
Edit:
You will get an invalid syntax error using:
[product,'categ_id': product['categ_id'][0],]
To pass values to the create method, you need to pass args to the execute_kw method as a list then pass values as a dictionary inside that list.
Edit:
values = {}
values['name'] = product['name']
values['categ_id'] = product['categ_id'][0]
...
new_lead = models_2.execute_kw(db_2, uid_db2, password_db_2, 'product.template', 'create', [values])
Edit: Use the parent category id in the new database
When we call the create method it will create a new record and return its ID which is probably different the one passed through the values dictionary.
To avoid the ValidationError you can use a dictionary where the parent ID in the old database is the key and the new ID is the value then you have just to pass that value when creating a new category.
category_ids = {}
for category in db_1_categories:
print("category..", category)
total_count +=1
values = {}
# values['id'] = category['id']
values['name'] = category['name']
if category['parent_id']:
values['parent_id'] = category_ids[category['parent_id'][0]]
category_id = models_2.execute_kw(db_2, uid_db2, password_db_2, 'product.category', 'create', [values])
category_ids[category['id']] = category_id
first of all error in your code
This is your code
db_1_products = models_1.execute_kw(db_1, uid_db1, password_db_1, 'product.template', 'search_read', [[]], {'fields':['id','name', 'categ_id','type', 'default_code', 'list_price', 'website_url', 'inventory_availibility', 'website_description']})
total_count = 0
for product in db_1_products:
print("produt..", product)
total_count +=1
new_lead = models_2.execute_kw(db_2, uid_db2, password_db_2, 'product.template', 'create', [product,'categ_id': product['categ_id'][0],])
print("Total Created..", total_count)
This is updated code
db_1_products = models_1.execute_kw(db_1, uid_db1, password_db_1, 'product.template', 'search_read', [[]], {'fields':['id','name', 'categ_id','type', 'default_code', 'list_price', 'website_url', 'inventory_availibility', 'website_description']})
total_count = 0
for product in db_1_products:
print("produt..", product)
total_count +=1
new_lead = models_2.execute_kw(db_2, uid_db2, password_db_2, 'product.template', 'create', [{product,'categ_id': product['categ_id'][0]}])
print("Total Created..", total_count)
you need to pass dictionary when creating of any model in odoo.

Django - Autocomplete Light in admin for join Model

So I have a join model defined as follow:
class EventTrack(models.Model):
dj = models.ForeignKey(DjProfile, blank=True)
track = models.ForeignKey(Track, blank=True)
event = models.ForeignKey(Event, blank=True)
def __str__(self):
return '%s - %s' % (self.event, self.track)
Is there a way I can use django-autocomplete-light with this model?
I know how to use it with inline models, but I don't get how to use it with standard field (in this case they are fk though).
At the moment I have the follow, which does not include the autocomplete functionality:
class EventTrackAdmin(admin.ModelAdmin):
fields = ['event', 'dj', 'track']
list_display = ('event', 'dj', 'track')
search_fields = ['event', 'dj', 'track']
admin.site.register(EventTrack, EventTrackAdmin)
edit:
I defined a DjForm as follow:
class DjForm(ModelForm):
dj = ModelChoiceField(
queryset=DjProfile.objects.all(),
widget=autocomplete.ModelSelect2(url='dj-autocomplete')
)
class Meta:
model = DjProfile
fields = '__all__'
Views:
#method_decorator(login_required, name='dispatch')
class DjProfileAutocomplete(autocomplete.Select2QuerySetView):
def get_queryset(self):
# Don't forget to filter out results depending on the visitor !
if not self.request.user.is_authenticated():
return DjProfile.objects.none()
qs = DjProfile.objects.all()
if self.q:
qs = qs.filter(name__istartswith=self.q)
return qs
And routing:
from frontend.views import DjProfileAutocomplete
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^dj-autocomplete/$', DjProfileAutocomplete.as_view(create_field='name'), name='dj-autocomplete'),
]
Everything works fine, and if I browse the endpoint I get the json with Djs result. My only problem is to use this in the EventTrack Model, in the admin.
sooo, actually it was easy:
forms.py
class EventTrackForm(ModelForm):
dj = ModelChoiceField(
queryset=DjProfile.objects.all(),
widget=autocomplete.ModelSelect2(url='dj-autocomplete')
)
class Meta:
model = EventTrack
fields = '__all__'
admin.py
class EventTrackAdmin(admin.ModelAdmin):
form = EventTrackForm
...

Dynamic namedQueries

Is their a dynamic namedquery on grails? Im not sure if its the right term but, I mean a namedquery that can be true to all.
Something like:
namedQueries = {
dynamicQuery{ term, name, value ->
term(name, value)
}
}
Then it can be called maybe like but not exactly:
def testClass = TestClass.dynamicQuery('eq', 'lastname', 'Bill').list()
and so you call it too like:
def testClass = TestClass.dynamicQuery('gt', 'id', 12).list()
This one might not work but is their something similar in grails?
UPDATE
The idea is that so I can chained it as many as I want like:
def testClass = TestClass.dynamicQuery('gt', 'id', 12).dynamicQuery('eq', 'stat', 11).list()
This is so that I dont have to create many namedqueries. I was hoping I can create one and use it multiple times.
Grails' createCriteria method generates Grails HibernateCriteriaBuilder instance, within which you can call invokeMethod method to dynamically create query criteria, which usually is defined by the standard DSL.
Here is a example in some controller:
private String dynamicCriteriaTest(String term, name, value) {
def c = TestClass.createCriteria()
def param = []
param << name
param << value
def result = c.list{
c.invokeMethod(term, param as Object[])
}
return result.toString()
}
def test() {
render dynamicCriteriaTest('eq','lastname','Bill')
}
That will get something you want.
update
If you want to call this method multiple times, pass the criteria parameters in an a List then execute the query:
private List dynamicCriteriaTest(List param) {
def c = TestClass.createCriteria()
def paramList = param.collate(3) //split the parameters into groups
def result = c.list{
paramList.each { paramInstance ->
def command = paramInstance[0]
paramInstance.remove(0)
c.invokeMethod(command, paramInstance as Object[])
}
}
return result
}
def test() {
ArrayList param = new ArrayList()
//the 1st criteria
param << 'gt'
param << 'id'
param << (long)12 //you have to check the Grails [HibernateCriteriaBuilder] API to make sure the parameter passed to `invokeMethod` is in the right type (e.g. **long** in this case)
//the 2nd one
param << 'eq'
param << 'stat'
param << (long)11
//even more
param << 'like'
param << 'description'
param << 'some text%'
render dynamicCriteriaTest(param)
}
In Grails you have NamedQueries and also Where Queries. The example you give can possibly be implemented by using a namedqueries and placing this in a abstract domain class. Your domain classes should extend this abstract domain.

django admin - how to override the default <select> view for foreign key?

I have 2 django model
class Location
address = models.CharField(max_length=100)
city = models.CharField(max_length=20)
class Client
location = models.ForeignKey(Location)
name = models.CharField(max_length=100)
And I have the following admin.py
class ClientAdmin(admin.ModelAdmin):
fieldsets = [
('Client Details', {'fields': ['name']}),
('Location Details', {'fields': ['location']}),
]
admin.site.register(Client, ClientAdmin)
When I try to add a Client I like to have a editable "location" fields i.e. address and city text fields. django by default gives a list.. how can I get the fields from the foregin tables?
any way I can do this? I don't wish to register the Location table in the admin.
thanks
You could put an inline table for the location and use the method queryset to handle the field values.
So, this is the ideia of the solution:
class LocationInline(admin.StackedInline):
model = Location
def queryset(self, request):
query = ... #your custom query here
qs = super(LocationInline, self).queryset(request).filter(query)
return qs
class ClientAdmin(admin.ModelAdmin):
inlines = [LocationInline]
fieldsets = [
('Client Details', {'fields': ['name']}),
]
Edit:
There is another way to do it in django 1.1.
class ClientAdmin(admin.ModelAdmin):
fieldsets = [
('Client Details', {'fields': ['name']}),
('Location Details', {'fields': ['location']}),
]
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name = "location":
locations = Location.objects.filter( ... ) #your query
kwargs["queryset"] = Location.objects.filter(query)
return super(ClientAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
The docs are here: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_for_foreignkey
It's an old question, but answering this can help a lot of other people too.
So, I hope it helps! ;)

Using Curry to Define Grails Tags

I have a grails tag library TpTagLib and in it I want to define 4 new tags that differ only in one constant value, so I tried to use curry.
But there is an exception: groovy.lang.MissingPropertyException: No such property: attr for class: TpTagLib
Does anyone have any idea why this exception occurs?
Here is the code:
def ifPermsTag = { permissions, attr, body ->
def user = attr?.user ?: session.userInstance
if( !user ) return false
if( !securityService.hasPermissions(user,permissions) ) return false
out << body()
return true
}
def canAdminRequestmaps = ifPermsTag.curry(Permission.CAN_ADMIN_REQUESTMAPS)
def canAdminCorporations = ifPermsTag.curry(Permission.CAN_ADMIN_CORPS)
def canAdminUsers = ifPermsTag.curry(Permission.CAN_ADMIN_USERS)
def canAdminDevices = ifPermsTag.curry(Permission.CAN_ADMIN_DEVICES)
Cool technique. You just need to make ifPermsTag private so it's not considered a candidate to be a usable tag method:
private ifPermsTag = { permissions, attr, body ->
...
}
Tags can have no parameters, or an 'attr' parameter, or an 'attr' and 'body' parameters but other signatures are invalid.

Resources