How to set domain with a many2one - python

I have a many2one that links to event.event called xx_event_id. In event.event I made a link to xx_weeks that is a separate model that keeps a list of weeks. Then the name of those weeks also links to a model called xx_week_name.
I'm trying to make a domain on xx_week_name. When I select an event I only want it to show the week names that are in the event.
So my xml looks like this:
<field name="xx_week_name" domain="[('id', 'in', xx_event_id.xx_weeks.name)]"/>
Yet it gives an error:
Uncaught Error: AttributeError: object has no attribute 'xx_weeks'

The domain is implemented in the javascript side and over there you cannot use Odoo's smart records (the 'dot' notation).
What you can do if you want to set a domain using a relational field is the following:
1) Declare a related field that will "pull" the name as a string from your relational field
week_name = fields.Char(related='xx_event_id.xx_weeks.name')
2) Insert that field in your view as invisible. In that way it will not change our view and we can still have access to it.
3) Change the filter in your relational field
That should work, but there is a chance that you have made a logical error in your domain. You check for [('id', 'in', xx_event_id.xx_weeks.name)] possibly you want something different there such as [('id', 'in', xx_event_id.xx_weeks.name)] If so modify the example above accordingly.

Related

get most recent rows stored in related tables using django [duplicate]

I've got 2 questions, but they are related to the same topic.
I know how to retrieve data from a for loop using template tags
{% for status in status %}
<tr>
<td>{{ status.status}}</td>
</tr>
{% endfor %}
However when I want to retrieve a single object i get an error even when i use:
po = Status.objects.latest('id')
and remove the for loop.
I get:
'Status' object is not iterable
My questions are:
How can I get the latest entry from the database for a given model?
How can I setup my templates tags to allow for just a single record?
You have two different questions here:
How do I retrieve the latest object from the database.
You can do this using the latest() queryset operator. By reading the docs you will note that this operator works on date fields, not integers.
Status.objects.latest('date_added') # or date_updated
If you want to do this off the ID you will need to order by ID and select the first result. (this will only work if you are using incrementing primary keys, it will not work with UUID's or randomly generated hashes).
Status.objects.order_by('id')[0]
Side note: I would personally use the date_added / date_updated way of doing this.
Iterating over a single object
A single object cannot be iterated over. For this you will need to use a different template. Or, you will need to add the single object into a list.
# note the [] around the query
result = [Status.object.latest('date_added')]
Personally I have a different views for listing single / multiple result. I have a ListView for many result objects and a DetailView for single objects.
TableName.objects.filter(key=value).order_by('-date_filed').first()
The "-date_filed'" field will reverse the order and the first will give you the latest element.
Let us assume I have a Model named "OneOfTheModelsUsed"
and there is a field called "car_name" and "date" within this model.
The following code worked for me while I was using Django FormWizard. After going through all the steps in the form and it gets saved. I used
last_entry = OneOfTheModelsUsed.objects.latest("date")
This gives all the entries in that model
last_car_name = last_entry.car_name
This gives the specific field entry you want in the given form.
return render(request, 'reference.html', {'last_car_name':last_car_name,}
passed the data to a template.
for the display in the template I used
{{last_car_model}}
and if you need the id for that entry.. use this {{last_car_model.id}} in the template.
PS:I'm fairly new to Django and Web development as a whole so I don't know much of the technical terms for all this
This is because latest returns a single instance rather than a queryset (which is iterable). So:
1) Latest is not working because it works with Date Fields. Read more at: https://docs.djangoproject.com/en/1.8/ref/models/querysets/#latest. 'id' is not a valid field to use with the latest filter.
2) You can't use for template tag with a single instance because it is not iterable.
To solve your situation, I would specify the ordering = ('id',) field in the Meta class of the model and then do a po = Status.objects.all()[:1] so you will obtain a queryset (which is iterable) with a single object in it. Then you will be able to use the for template tag with your po variable.
Hope it helps.
comments = usercomment.objects.order_by('-id')[:100]
I Did By This Method
First "comment" Is The Variable Name, "usercomment" Is Model Name, "id" is generated by django when make a model, [:100] is from 0 to 100 you can increase the number to x

jira python customfield

How do you determine the name of a custom field in jira-python?
When I retrieve an issue, my custom fields show up as customfield_xxx
The names on my screen are 'project', 'name', 'due date', etc.
Short of putting a value in each field, then seeing where it appears
when I re-read the issue.
That is I can put 'a' in one of my fields, then read the issue, and find that
customfield_10801 (or whatever) has the value 'a'. But is there a general
way to find, for example, if my custom field is 'due date', which customfield_xxx
does it get mapped to?
Or, in the JIRA GUI, how would I look up these customfield #'s.
From the GUI you can see the custom field id in the html code or url:
On the admin page where all the custom fields are listed on the row of the custom field you are interested to the right click the gear and click/hover over "Configure". You should see the custom field ID in the URL.
Another way is via the REST API:
{jira-base-url}/rest/api/2/field
It's a GET request so just put that url in your browser.
Update:
Based on the comments it can be done something like this:
# Fetch all fields
allfields=jira.fields()
# Make a map from field name -> field id
nameMap = {field['name']:field['id'] for field in allfields}
# Fetch an issue
issue = jira.issue('ABC-1')
# You can now look up custom fields by name using the map
getattr(issue.fields, nameMap[custom_name])

HP Quality Center field names

I am interacting with HP QC using python and referring to HP ALM OTA documentation.
What I need is to access fields in different places (particularly now I am trying to access Test Set description field). As far as I know it is done by following: TestSet['description field name'] = 'I am description' The problem is - I don't know this field name and I can't find it in documentation mentioned.Up until now I was wondering around examples in hope to find these names (the way I found that Actual field in test step is named 'ST_ACTUAL').
Could you please help me find some kind of list of these field names. Or the way to retrieve them.. (Or at least give me the name of this Test Set description field)
When you get an entity field value, the field must be the underlying database column name for that entity. You can discover this using the project customization UI in HP ALM: select project entities then explore the system or user fields. Beware that the Design Step says the column name begins ST_... it doesn't. It's actually DS_...
You can also get this information programmatically. Given a factory instance use the equivalent of:
private void ExploreFactoryFieldDefinitions(IBaseFactory factory)
{
List fields = factory.Fields;
foreach (TDField field in fields)
{
FieldProperty field_property = (FieldProperty)field.Property;
if (field_property.IsRequired)
{
Log(String.Format("User Label: {0}\n", field_property.UserLabel));
Log(String.Format("User Column Type: {0}\n", field_property.UserColumnType));
Log(String.Format("DB Column Name: {0}\n", field_property.DBColumnName));
Log(String.Format("DB Column Type: {0}\n", field_property.DBColumnType));
Log(String.Format("DB Table Name: {0}\n", field_property.DBTableName));
}
}
}
field_property.UserLabel gives you the user friendly field name. field_property.DBColumn name gives you the database column name that should be used with entity[field_name].
BTW - don't forget to call entity.Post() to have your changes saved. When working with a versioned project you have a few more hoops to jump through too. Good luck!
I think, the field you are looking for is CY_COMMENT (hint). Maybe there is a better way—but you can find the names of the fields in the Query Builder. If you create an Excel Report and open the Query Builder, there is an Entities View which shows all the fields of the tables (even the user-defined fields). Maybe there is some kind of database documentation which gives you the same thing.

OpenERP 7: relational fields in client-side domain filters

here shows my error
2013-04-23 05:36:03,877 17001 ERROR demo openerp.sql_db: bad query: SELECT "res_company".id FROM "res_company" WHERE "res_company".id = 'deduction_id.bpl_company_id.id' ORDER BY "res_company"."name"
Traceback (most recent call last):
File "/home/bellvantage/Documents/openerp-7.0/openerp-7/openerp/sql_db.py", line 226, in execute
res = self._obj.execute(query, params)
DataError: invalid input syntax for integer: "deduction_id.bpl_company_id.id"
LINE 1: ...y".id FROM "res_company" WHERE "res_company".id = 'deduction...
^
2013-04-23 05:36:03,878 17001 ERROR demo openerp.osv.osv: Uncaught exception
Traceback (most recent call last):
here shows my code which i trying to add domain filter
class estate_bank_deductions(osv.osv):
_name = 'bpl.estate.bank.deductions'
_description = 'Estate Bank Deductions'
_columns = {
'deduction_id':fields.many2one('bpl.deduction.estate.data', 'Bank Deductions', ondelete='cascade'),
'name': fields.many2one('bpl.deduction.registration', 'Deduction', domain="[('type','=','bank'),('bpl_company_id.id','=','deduction_id.bpl_company_id.id')]"),
'bank_id': fields.many2one('bpl.bank.registration', 'Bank Name'),
'branch_id': fields.many2one('bpl.branch.registration', 'Branch'),
}
here is part of my parent class of estate bank deduction class
_name = 'bpl.deduction.estate.data'
_description = 'BPL Deduction Estate Data'
_columns = {
'bpl_company_id':fields.many2one('res.company', 'Company', help='Company'),
please help me to sort out this.?
is there anything missing in my domain filtering mechanism or is that way is incorrect.?
Dear odony,
one more thing to clarify,
now need to define my field as fields.function ?
but the issue is after adding the domain filter also other irrelevant records also loaded to my drop down (after i added the widget="selection" attribute).
then how to restrict them. i already posted that issue
hope you will advice me on this...again thanks u soo much
It won't work either way. Model fields support only two kind of domain filters:
Server-side (list) domains, specified as a list of tuples: can only be static and are meant to be used for one2many and many2many fields mostly. These filters will be applied on the server-side when reading the list of values for the field, and will never be used on the client-side. The domain can only contain constants on the right side of each domain element. An example of a valid server-side domain is:
# filter deductions based on an imaginary "confirmed" boolean field
deduction_ids = fields.one2many('bpl.estate.bank.deductions', 'bank_id',
string="Confirmed Deductions",
domain=[('confirmed', '=', True)])
Client-side (string) domains, specified as the string representation of a server-side domain: can be static or dynamic, and are meant to be used for many2one fields mostly, and never evaluated on the server-side. They are simply copied in any view where the field is used, and interpreted on the client-side to filter the list of available choices for that field. The right hand side of each domain element can be made dynamic by referring to the name of any other field included in the view, and will be replaced by the field value when the domain is evaluated. The field value will be returned in the same format that it would be passed to write() when saving the changes. An example of a valid client-side domain is:
# only allow choosing a branch that belongs to the right bank registration
# (here `branch_id` refers to the current value of the `branch_id` field
# in the form view
'branch_id': fields.many2one('bpl.branch.registration', 'Branch',
domain="[('branch_id','=',branch_id)]")
UPDATE: watch out, you cannot use widget="selection" in combination with client-side domains because this option converts your many2one field into a fake fields.selection whose options are statically evaluated server-side. In this case your client-side domain will be ignored and the list of available values will never change. Now if you simply want to avoid users creating new values you can restrict access rights to prevent that, and if you want to avoid showing an icon to view/edit the target object you can add options='{"no_open": True}' to the field in the form view.
Problem
In your case it seems you want to use a client-side domain to filter based on the current value of the deduction_id field. But your domain expression ('bpl_company_id.id','=','deduction_id.bpl_company_id.id') is incorrect:
The left hand side must refer to a field or a field path, and the .id suffix is useless here, bpl_company_id is sufficient to filter on that many2one field.
The right hand side can be dynamic or static, depending if you make it a constant or a variable. If you quote the value as 'deduction_id.bpl_company_id.id' then you're comparing the m2o ID (or the m2o name if your remove the .id suffix) to the literal string value "deduction_id.bpl_company_id.id", certainly not what you want.
If you remove the quoting as suggested by user2310008 you will make it dynamic indeed, but the value of the deduction_id will be the ID of the selected "deduction"! You cannot treat it as a browse_record (ActiveRecord-like object) like on the server-side, so when you do "deduction_id.bpl_company_id.id" you'll get an error because an integer has no bpl_company_id attribute.
Solution
The usual way to implement this kind of filtering is to add an on_change method on the deduction_id field, and use it to dynamically alter the domain of the name column, via the domain key that onchange methods can return. Something like this:
<!-- in the XML view -->
<field name="deduction_id" on_change="onchange_deduction_id(deduction_id)"/>
<field name="name"/>
# in the python model
def onchange_deduction_id(self, cr, uid, ids, deduction_id, context=None):
if deduction_id:
deduction = self.pool['bpl.deduction.estate.data'].browse(cr, uid,
deduction_id,
context)
return {'domain': {'name': [('bpl_company_id', '=',
deduction.bpl_company_id.id)]}
return {} # or perhaps a default domain?
Try this.
('bpl_company_id','=',deduction_id.bpl_company_id.id)
Without quotes the second part, and the field can not be done recursively.

unique python/django issue with variable column/field name in form

I have quite unique problem with django.
Im providing website users interface for editing large data. Each row on this data represents a row in database. Or one object of certain Type.
Users click on cells in the table and form opens where they can edit this fields/column value.
In essence it works like this:
1) based on where user clicks, query is sent to server containting object id and the field that he is editing.
2) based on this information form is created on the fly:
class FieldEditorForm(forms.ModelForm):
class Meta:
model = MyObject
fields = ['id', field ]
Notice the field there is Variable not name of the field.
3) this field passes its own modelform validation and all is fine. in save method Model.save() is enough to update the value.
But now to the problem. Sometimes empty value is sent to server in this form. Empy value such as u'' or almost emtpty like u' '. I want to repace this with None so NULL would be saved to database.
There are two places where i could do that. In field validation modifying the cleaned_data or in form save method.
Both approaches raise unique problem as i dont know how to create variable function names.
def clean_%(field)s():
or in case of form save method
r.%(field)s = None
is what i need, but those methods dont work. So how can i create method name which is variable or set objects variable parameter to something. Is it even possible or do i have to rethink my approach there?
Alan
In the latter case, setattr(r, field + 's', None).

Categories