manyone field with my own default value, Odoo - python-3.x

I have the sale.order model which has the partner_shipping_id.country_id field of the res.country model, what I want is to know how to have a new many2one field (res.country) but that has the sale_order.partner_shipping_id.country_id field loaded by default .
I have tried two ways without being able to get the result:
def _default_country_edit(self):
return self.partner_shipping_id.country_id
country_edit = fields.Many2one('res.country', string="País", default=lambda self: self._default_country_edit())
or:
country_edit = fields.Many2one('res.country', string="País", default=_default_country_edit())
I need something like this:

What I did is in the read method, if you don't have the new field set it and that's it
if not self.country_edit:
self.country_edit = self.partner_shipping_id.country_id
Obviously, in the write method, the sale_order.partner_shipping_id.country_id field must be set with the new one.

Related

How do I get Django values_list to return value of display override and not the actual value?

I noticed that when calling values() or values_list() one a queryset returns the normal value in the field and not the display value I'd like. Is there a way to manupilate the display value of the field while creating a result that is a list of list of the queryset?
class FooBar(models.Model):
...
foo_bar = models.CharField(_("foo"), choices=[(1, 'foo'), (2, 'bar')])
def get_foo_bar_display(self):
return "something"
def get_foobar(user):
foobar = FooBar.objects.filter(user=user).values_list(.., 'foo_bar')
foobar = list(map(list, foobar))
return foobar
It always returns the foo_bar original value and not the display value.
One way out for you is to get the model instances with only some selected fields (needed for the get_x_display to work correctly) using .only() query set method.
Going from there you can call the get_x_display on the model like you'd normally do.

Can I dynamically set a PXDataFieldAssign parameter of a PXDataFieldParam object?

I have code that sets the PXDataFieldAssign value as follows:
pf = new PXDataFieldAssign<xTACProjectTask.dueDate>(someValue);
I also have a table, holding the DAC field names, such as "xTACProjectTask.dueDate". This table also has a checkbox field to determine whether to use this DAC field as a parameter.
Is there a way to not have the DAC fieldname hard-coded, and instead (maybe using a 'typeof' call?) use the results of the table query to set that field name - like the following?
pf = new PXDataFieldAssign<typeof("xTACProjectTask.dueDate")>(someValue);
or, using my query result:
pf = new PXDataFieldAssign<typeof(query.value)>(someValue);
with query.value being the value in the table holding the DAC field name?
You can create it using Type.GetType and Activator.CreateInstance. Please see the example below:
string typeName = "PX.Objects.IN.InventoryItem+descr,PX.Objects";
Type typeArgument = Type.GetType(typeName);
Type genericClass = typeof(PXDataFieldAssign<>);
Type constructedClass = genericClass.MakeGenericType(typeArgument);
object created = Activator.CreateInstance(constructedClass,new object[] { "Test Description" });
You will get the below wrapped into object in the created

Web2Py list:reference table, Load and set data

Maybe I'm missing something absurd, I'm not seeing, but this is my first app to study web2py.
I am unable to enter the data in Table Movies, which has fields related to other tables.
The list is loaded, but it is not registered in Movies registration.
Under the codes and the results.
db.py
Movie = db.define_table('movies',
Field('title','string', label = 'Title'),
Field('date_release','integer', label = 'Date Release'),
Field('duraction','integer', label = 'Duraction'),
Field('category','string','list:reference categories', label = 'Category'),
Field('actor','list:reference actors', label = 'Actor'),
Field('director','list:reference directors', label = 'Diretor'),
)
Category = db.define_table('categories',
Field('title','string', label = 'Title'),
)
validators.py
Movie.title.requires = [IS_NOT_EMPTY(), IS_NOT_IN_DB(db, 'movies.title')]
Movie.category.requires = IS_IN_DB(db, 'categories.title')
Movie.director.requires = IS_IN_DB(db, 'directors.name')
Movie.actor.requires = IS_IN_DB(db, 'actors.name')
Movie.duraction.requires = IS_INT_IN_RANGE(0, 1000)
Category.title.requires = IS_NOT_EMPTY()
movie.py
def add():
form = SQLFORM(Movie)
if form.process().accepted:
response.flash = "Successful! New movie added!"
redirect(URL('add'))
elif form.errors:
response.flash = 'Error'
else:
response.flash = 'Form, set data'
return dict(form = form)
List Load another tables - ok:
The items of list not record in DB:
The widgets displayed in the form are based on the IS_IN_DB field validators you have specified, and there are three problems with the way you have coded them.
First, list:reference fields, like standard reference type fields, store the record IDs of the records they reference -- they do not store values of other fields within the referenced records. So, the second argument to the IS_IN_DB validator should always be the ID field (e.g., categories.id).
Second, although the field will store record IDs, you want the form widget to show some other more descriptive representation of each record, so you should specify the "label" argument of the IS_IN_DB validator (e.g., label='%(title)s').
Third, list:reference fields allow for multiple selections, so you must set the "multiple" argument of the IS_IN_DB validator to True. This will result in a multi-select widget in the form.
So, the resulting validator should look like this:
Movie.category.requires = IS_IN_DB(db, 'categories.id', label='%(title)s', multiple=True)
The above will allow multiple db.categories IDs to be selected, though the form widget will display category titles rather than the actual IDs.
Now, all of the above can be made much easier if you instead define the referenced tables before the db.movies table and specify a format argument for each table:
Category = db.define_table('categories',
Field('title','string', label = 'Title'),
format='%(title)s')
Movie = db.define_table('movies',
...,
Field('category', 'list:reference categories', label = 'Category'),
...)
With the above code, there is no need to explicitly specify the IS_IN_DB validator at all, as the db.movies.category field will automatically get a default validator exactly like the one specified above (the format attribute of the db.categories table is used as the label argument).
You might want to read the documentation on list:reference fields and the IS_IN_DB validator.
As an aside, you might consider specifying your field validators within the table definitions (via the requires argument to Field()), as this is more concise, keeps all schema-related details in one place, and eliminates the need to read and execute an additional model file on every request.

Django Haystack faceting on the model type

I want to facet the results based on the different model_names (classes) returned. Is there an easy way to do this?
Have you tried adding a SearchIndex field with this information? E.g.
class NoteIndex(SearchIndex, indexes.Indexable):
title = CharField(model_attr='title')
facet_model_name = CharField(faceted=True)
def get_model(self):
return Note
def prepare_facet_model_name(self, obj):
return "note"
class MemoIndex(SearchIndex, indexes.Indexable):
title = CharField(model_attr='title')
facet_model_name = CharField(faceted=True)
def get_model(self):
return Memo
def prepare_facet_model_name(self, obj):
return "memo"
And so on, simply returning a different string for each search index. You could also create a mixin and return the name of the model returned by get_model too.
Presuming you've added this field to each of your SearchIndex definitions, just chain the facet method to your results.
results = form.search().facet('facet_model_name')
Now the facet_counts method will return a dictionary with the faceted fields and count of results for each facet value, in this case, the model names.
Note that the field here is labeled verbosely to avoid a possible conflict with model_name, a field added by Haystack. It's not faceted, and I'm not sure if duplicating it will cause a conflict.
If you just want to filter on the model type, you can use the ModelSearchForm
The Docs have a really good walk-through for this.
The minimum you'll need:
is to add faceted=True to the params of your model_names field.
Rebuild your schema and indices.
add .facet('model_names') to whatever SearchQuerySet you're wanting to facet.
More explanation on the question would enable a more complete answer.

Can I set the default value of a custom list column to be a new Guid?

I tried setting the defaultvalue property of the field to Guid.NewGuid() but every item created has the same guid so I guess the Guid.NewGuid() is being stored as the default rather than being run each time.
Is the only way to achieve this to add an event handler to the list for OnAdded?
I'm assuming you're using a Single Line of Text field for this. The standard default for such a field is always a constant, you can't assign a variable or function via the object model. All that would do is assign the static result of that particular call of the function.
While text fields can support a calculated default value, it uses the same functions that are in Calculated columns, which do not support random numbers.
Your best bet is to use an Event Handler, I would recommend ItemAdding over ItemAdded as well. You'd be assigning to properties.AfterProperties["fieldname"] instead of field.DefaultValue, of course.
If you are creating the field through code and setting the field.DefaultValue = Guid.NewGuid(), this will run the Guid.NewGuid() and store the returned Guid as the default
It is the equlivant of running the folowing code:
Guid newGuid = Guid.NewGuid();
string newGuidString = newGuid.ToString();
field.DefaultValue = newGuidString;
I dont know of any method you can use to set the field to generate a new Guid on item creation other than using an Event handler.
It should be posable to genrate a random number using the field.DefaultValue = "RANDBETWEEN(10,20)"; but i have not tested this

Resources