Odoo dynamic many2one domain - field

I want to apply dynamic filter to a many2one field (F1) based on another field (F2). I've done that using #api.change decorator, and it works but not as expected.
When i create a new entity, i change the value of F2, then go to F1, i find it filered, Oki no problem.
When i close the form, and then edit it again, and i go directly to the F1 field, i get again all available possibilities (not filtered), i need first to go to F2 and then choose the same value (already chosen previously) and then come back to F1.
Any idea ? (below the code: F1 = product_id which is inherited, and F2 = bom_id)
class ProductionLot(models.Model):
_inherit = "stock.production.lot"
company_id = fields.Many2one(default=lambda self: self.env['res.company']._company_default_get('account.invoice'))
bom_serial_number_line_ids = fields.One2many("mrp.bom.serialnumber.line", "parent_lot_id", "BoM Serial Numbers")
bom_id = fields.Many2one("mrp.bom", "BoM")
#api.onchange('product_id')
def update_bom_id_from_product_id(self):
for record in self:
if (record.product_id):
bom_complex_kit = record.product_id.env['mrp.bom']._bom_find(
product_tmpl=record.product_id.product_tmpl_id,
bom_type='complex_kit')
self.bom_id = bom_complex_kit
return {"domain": {"bom_id": [('product_tmpl_id.id', '=', record.product_id.product_tmpl_id.id),
('type', '=', 'complex_kit')]}}

As onchange filter will only be applied when the function is a trigger so it will only work when you change the on change value I guess what you need to do is this or combination of both onchange and default domain on field
def get_domain(self):
ids = self.env['stock.production.lot'].browse(self._context.get('active_ids'))
print("Here see all ids and use them accordingly",ids)
bom_id = fields.Many2one("mrp.bom", "BoM", domain = lambda self:self.get_domain())

Related

How to solve the wxGrid class no "findWindowById" function?

In the wxframe, there is one button and one "wxGrid" object.
I want to "click“ the function to change the "wxGrid".
But wxStaticText hasn't function for "findWindowById". Now I solve as follows
-record(wx_ref, {ref, type, state=[]}).
button_debug_a_click(Event,Object)->
A = wxWindow:findWindowById(?CONST_EQUIPMENT_GRID_ID),
B = A#wx_ref{type = wxGrid},
lager:debug("find equipment grid object:\t~p\t~p",[A,B]),
wxGrid:hide(B),
ok.
Only after it is converted to {wx_ref,45, wxGrid,[]}, it can be used.
But “wx_ref” record's header file can't be visited.
Is there a better way to solve the problem (convert id to object)

Django admin custom search on custom column

Question:
How can I add the ability to search for items in my custom column Help Text?
FooAdmin View
Code:
Here is a simplified version of the code that I am working with:
models.py (yes this is how the models need to be set up)
class HelpText(models.Model):
help_text = models.CharField(max_length=1000)
def __str__(self):
return self.help_text
class Foo(models.Model):
job_name = models.CharField(max_length=200, blank=False, null=False)
env = models.CharField(max_length=200, blank=False, null=False)
def __str__(self):
return self.job_name
class FooHelpText(models.Model):
foo = models.OneToOneField(Foo, on_delete=models.DO_NOTHING)
help_text = models.ForeignKey(HelpText, on_delete=models.DO_NOTHING)
def __str__(self):
return str(self.help_text)
admin.py
class FooHelpTextInline(admin.TabularInline):
model = models.FooHelpText
#admin.register(models.Foo)
class FooAdmin(admin.ModelAdmin):
search_fields = ['env', 'job_name',]
list_display = ['pk', 'job_name', 'env', '_get_help_text', ]
inlines = [FooHelpTextInline]
def _get_help_text(self, obj):
return obj.foohelptext.help_text
Current behavior:
The current code above allows me to see the associated help_text in a column on FooAdmin. However, I am not able to search by anything in that column.
Not the answer I am looking for:
I know if it was the other way around where the help_text was a ForeignKey on Foo I could do something like foo__help_text, but that is not how my models are set up (and can not change).
Desired behavior:
Use the search box to search for help text (not just env and job_name).
Possible Solution (that I need help with):
I suspect that get_search_results might be what I need, but I don't understand how to implement it for my use case.
UPDATE:
The closest I can get is searching for a number(aka a specific PK that I know exists) and getting that search result. But the query doesn't really make sense. And obviously that is not the desired functionality of a search.
def get_search_results(self, request, queryset, search_term):
queryset, use_distinct = super().get_search_results(request, queryset, search_term)
try:
search_term_as_int = int(search_term)
except ValueError:
pass
else:
queryset |= models.Foo.objects.select_related(
'foohelptext').filter(fooshelptext=search_term_as_int)
return queryset, use_distinct
I just don't understand the Python |= (bitwise OR operator) and why it has to be an integer.
Much easier than I thought. No need for get_search_results.
Simply needed to add it as foohelptext__help_text__help_text as an other item in the search fields.

Referencing another field in a domain function (Odoo12)

I want to restrict the account lookup (domain) based on the value entered in GL Prefix (I'll actually use some wildcards and some other logic which I'm comfortable adding later), the problem is that I'm getting a logical True or False value returned by self.x_poLineGLprefix rather than the value in the field. How do I get the actual data value of x_poLineGLprefix?
class QuickPOLine(models.Model):
_name = 'purchase.order.line'
_inherit = 'purchase.order.line'
x_poLineGLprefix = fields.Char(string='GL Prefix')
x_poLineGLaccount = fields.Many2one(
'account.account', string="Line Item Expense Account",
domain=lambda self: [('code', '=', self.x_poLineGLprefix)])
Try this
#api.onchange('x_poLineGLprefix')
def onchange_x_poLineGLprefix(self):
if self.x_poLineGLprefix:
return {'domain': {
'x_poLineGLaccount': [('code', '=', self.x_poLineGLprefix)]
}}
You can add dynamic domain to achieve this based on any field. In #api.onchange() function you can return domain for many2one. To add dynamic domain you can refer this link. If you are using both many2one fields refer this link.

How to dynamically set Datatables search and column filters state via url params?

Let's say I have two models: customers and orders.
Every order belongs to a customer.
I also set a orders (index) view with a Datatable showing all the orders.
If I want to see all the orders for a given customer all I have to do is to filter the results for that customer writing the concerning customer name in the "search" field or selecting that customer from its column filter field.
Now I'd like to implement a customer-orders link which automatically shows the orders Datatable with those settings.
In other words, I'd like that a link to /orders?isearch='customer_name+customer_surname' will show the Datatable with the customer full name already written in the search field (or the customer column filter set accordingly).
Of course I can fetch the #customer instance variable from the controller and pass it to the view, but then?
Using the oSearch variable in the initialization code I can define an initialization value for the search field, the isearch variable:
$(document).ready( function() {
var isearch = $('#isearch').val()
$('#example').dataTable( {
"oSearch": {"sSearch": isearch}
} );
} )
The isearch value is stored in a proper hidden field in the view:
<%= hidden_field_tag "isearch", #isearch.to_s, { :id => "isearch" } %>
(This is the best way I found so far to pass an instance variable to a .js file in Rails).
Last but not least, the #isearch instance variable is set from the order_controller:
#isearch = params[:isearch]
Of course its value should be passed to the url like:
.../orders?isearch='customer_name+customer_surname'
----ADDENDUM----
I figured out I don't need an instance variable, in fact I can pass as many url params as I want using this javascript function:
function getUrlParam( name )
{
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null )
return "";
else
return results[1].replace("+", " ");
}
Then I can fetch them from my .js file like this:
// fetches url params
var isearch = getUrlParam('isearch');
var customer_name = getUrlParam('customer_name');
var order_status = getUrlParam('order_status');
Accordin to these values I not only can set the oSearch variable but also a column-specific using Datatables aoSearchCols initialization parameter ( http://www.datatables.net/ref#aoSearchCols )
The last problem to solve, given that I am using individual column filtering with select elements (http://www.datatables.net/release-datatables/examples/api/multi_filter_select.html), so set every select element according to the URL-passed params.
I did it with this jQuery instruction:
// sets all select filters according to url passed params
$('select').val([customer_name, preparation_kind, preparation_status]);
From the performance point of view this solution is improvable, but its easy and it works.

Default django-admin list filter

My question is just an extension of this thread [Question]http://stackoverflow.com/questions/851636/default-filter-in-django-admin .
from myproject.myapp.mymodels import fieldC
class Poll(models.Model):
fieldA = models.CharField(max_length=80, choices=CHOICES.MyCHOICES)
fieldB = models.ForeignKey(fieldC)
admin.py
list_display = ('fieldB__fieldc1')
Now my list filter shows four criteria All, A ,B ,C .
What I want is if the superuser is logged in ,the filter should show all four criteria All,A,B,C and if the user is other than superuser filter should only show All, A, B.
How can i acheive this ?
Here is my actual piece of admin.py
def changelist_view(self, request, extra_context=None):
referer = request.META.get('HTTP_REFERER', '')
test = referer.split(request.META['PATH_INFO'])
if test[-1] and not test[-1].startswith('?'):
if not request.GET.has_key('patient__patient_type__exact'):
q = request.GET.copy()
q['patient__patient_type__exact'] = 'Real'
request.GET = q
request.META['QUERY_STRING'] = request.GET.urlencode()
if not request.user.is_superuser:
q['patient__patient_type__exact'] = 'Real'
return super(VisitAdmin, self).changelist_view(request, extra_context)
Thanks in advance
I think the new FilterSpec API in Django 1.4 gives you exactly what you need here. Check out the docs on list_filter. In 1.4 you can now make custom list filters that subclass django.contrib.admin.SimpleListFilter and give you the power to write custom lookup and queryset code, and since the request is passed in you can do a simple conditional with is_superuser.
if request.user.is_superuser:
# pass one set of lookups
else:
# pass a different set
read the example code in the docs carefully and I think it will all be clear.

Resources