How to Use Many2one Field as selection? - python

on Odoo, I want to create a many2one field which show some items created according to another field(named 'A') and can be changed once field 'A' is changed.
I have tried to use field.Selection, but failed and I switch to field.Many2one; and until now I don't complete this.
class Selection(models.Model):
_name = 'selection.model'
_rec_name = 'select'
select = fields.Char(string='selections', required=True)
class Checks(models.Model):
_name = 'buy.goods'
strs = fields.Char()
results = fields.Many2one('selection.model', string='Selections')
#api.onchange('strs')
def _get_results(self):
goods = self.strs.split(',')
I want to use the list of words of 'goods' as items of 'results' field and once content of 'strs' field is changed, the list of 'goods' is changed and items of 'results' should be changed automaticly.

When you define the form view in XML you need to add a widget called selection. Through this way you can use your many2one field as a selection field.
For example:
<field name='results' widget='selection'/>
ps: clear cache and try it !

Related

Altering model after field validation

I'm implementing a tagging system. Currently, the models look like this:
class Tag(models.Model):
label = models.CharField(max_length=MAX_TAG_LENGTH)
class TagManager(models.Model):
tags = models.ManyToManyField(Tag, related_name="referrers")
def associate_tag(self, tag_label: str):
. . .
And I have a custom field that cuts its input on commas so the user can enter tags as a comma-separated list:
class TagsField(forms.CharField):
def to_python(self, value):
if not value:
return []
return [tag.strip() for tag in value.split(',')]
Finally, I have the model and form where these are used:
class Thing(models.Model):
tags = models.OneToOneField(TagManager, on_delete=models.SET_NULL, null=True)
class ThingForm(forms.ModelForm):
tags = TagsField(widget=forms.TextInput(attrs={"placeholder": "Tags", "required": False}))
class Meta:
model = Thing
fields = ["tags"]
Problem
My issue is that if I populate and validate the form:
form = ThingForm(data={"tags": ["One", "Two"]})
form.is_valid()
I get errors:
{'tags': ["“["One", "Two"]” value must be an integer."]}
Which I'm guessing is because it's trying to place the stringified list in the OneToOneField, which isn't going to work.
What I really need to do is after validating the field, I need to iterate the results of to_python, and call thing_instance.tags.associate_tag on each of the validated tag strings.
Is there a "hook" method on forms that will allow me to do this cleanly? I've read over the docs and Form source and can't find any obvious candidates.
I realized as I was writing this that it's a clean_* method that I need. This didn't strike me as "cleaning" on first brush, so I ignored it.
The solution was to add a clean_tags method to the ThingForm class:
def clean_tags(self):
tags = self.cleaned_data["tags"]
for tag in tags:
self.instance.tags.associate_tag(tag)
return self.instance.tags.pk
It associates the cleaned tags, and then returns the PK of the TagManager they were added to.

How to set default value to Many2one field in odoo10?

I created a many2one field that has relationship custom model. I want to know how to self default value. My default value is "Head/Branch".
Here is my code. Thank You.
from odoo import models, fields, api
import logging
class CrmnNewTask(models.Model):
_inherit = 'res.partner'
head_branch=fields.Many2one('head.branch', string='Head/Branch',index=True, ondelete='cascade')
class Headbranch(models.Model):
_name='head.branch'
name=fields.Char('Head/Branch')
Please implement this example in your code :
user_id = fields.Many2one('res.users','User', default=lambda self: self.env.user)
Here I have set current user name in many2one field. You can also set default value using function. This one another example :
*
tax_group_id = fields.Many2one('account.tax.group', string="Tax Group", default=_default_tax_group, required=True)
#api.model
def _default_tax_group(self):
return self.env['account.tax.group'].search([], limit=1)
*
Try this:
Go to your form where is field head_branch
Active developer mode
Populate field and save as default https://imgur.com/a/fQd03

Is there any way to forcefully import data into readonly fields in Odoo 9 or 10?

We have created a custom module in Odoo by inheriting res.partner view and some custom fields, which are readonly, were added. Fields such as customer_since_date and customer_id.
We want to import data to these fields but Odoo does not allow import info into readonly fields.
Is there any way to import data in those fields forcefully?
The simple way to make a field read only by view definition is like ,
<field name="phone" readonly="True" />
If you make the field read only by hard way , you can still update the value of such fields by code.
Simply inherit the model
`_inherit = 'res.partner' `
and create a custom function in which you pass a variable with value you want to assign to the field
In my case i was getting data from Point Of Sale module which is mainly javascript i call a rpc query and send a list of values ( contains customer_name & points
def updating_points(self, data):
que = self.env['res.partner'].search([('name', '=', data['customer_name'])])
que.points_earned = data['update_points']
I simply search the res.partner model for specific user update the field i created points_earned

Python WTForms: How to dynamically set options of a SelectField in FieldList of FormFields?

I am currently trying to use WTForms's FieldList and FormField enclosures to allow users to add a custom subset of locations with corresponding coverage amounts.
The form presents a user with some standard inputs and then initializes with a single set of fields (FormField) each with a location select input and a coverage amount input.
Javascript allows the user to add or remove additional location coverage field sets as needed to reflect the accurate document information.
The Problem: As a workaround, I have been setting the location options by passing a template variable in the form handler's GET request and manually creating my own form fields. This isn't updating the actual WTForms location field choices though, so when I submit the form an exception is raised for the location field ('Not a valid choice').
How can I dynamically add location choices to the location field of the LocationForm when I instantiate MyForm?
This is basically how my code looks:
Note: I have omitted the code that creates a locations template variable in the GET request since that is not the desired design. I want to be more in line with the intended WTForms methodology:
class LocationForm(Form):
location = SelectField('Location', [], choices=[])
coverage = FloatField('Coverage', [])
class MyForm(BaseForm):
# other fields omitted for brevity
location_coverage = FieldList(FormField(LocationForm), [], min_entries=1)
class AddDocument(BaseHandler):
def get(self):
params = {
"cid": cid
}
return self.render_template("form.html", **params)
def post(self):
cid = self.request.get('cid')
if not self.form.validate():
return self.get()
company_key = ndb.Key('Company', cid)
doc = Document(parent=company_key)
self.form.populate_obj(doc)
doc.put()
params = {
"cid":
}
return self.redirect_to('view_company', **params)
#webapp2.cached_property
def form(self):
f = MyForm(self)
# HERE is where I would normally do something like:
# company = ndb.Key('Company', int(self.request.get('cid')))
# locations = ndb.Location.query(ancestor=company).fetch()
# f.field_name.choices = [(loc.key, loc.name) for loc in locations]
# but this doesn't work with Select Fields enclosed in
# FormFields and FieldLists.
return f
Edit:
I created a solution but this isn't the answer I am looking for. In my case, I simply changed the LocationForm.location form field from a SelectField to a StringField. Doing this bypasses the validation of the select field choices and allows the form to submit. This is not ideal as it is not the intended design, but if anyone can steer me toward a more proper way to use WTForms in this particular scenario I would greatly appreciate it.
If your BaseForm class populates the form from the post data on instantiation, you should see the nested forms populated at the point where you'd normally add the choices into a SelectField directly on the form.
Therefore something like:
for entry in f.location_coverage.entries:
entry.location.choices = [(loc.key, loc.name) for loc in locations]
Should populate the choices into each subform select field.

Django - how to set forms.FileField name

I'd like to set custom name to a FileField object in my admin form so that it's html name attribute will not be equal to my instance field name.
class MyAdminForm(forms.ModelForm):
file_field = forms.FileField()
def __init__(self, *args, **kwargs):
if kwargs.has_key('instance'):
instance = kwargs['instance']
self.initial['image_file'] = instance.file_field
With this code I get <input type="file" name="file_field" /> and what I want to do is set it's name attribute to something else.
EDIT:
I accepted the answer below, but I have another question. Is it possible to construct variable number of FileField objects? I mean - what if I'd like to have 4 of those now, but under some circumstances only one? Will I have to declare all of those as a class fields, like file_field1, file_field2 and so on, or is it possible to add them to a dictionary, like that: { 'file_field1: FileField(), 'file_field2' : FileField() } - I actually tried it and got an error...
The name attribute in the HTML is the same as the name in the form definition so if you don't want it to be file_field then don't call it file_field.
class MyAdminForm(forms.ModelForm):
new_field = forms.FileField()
# Rest of the form goes here

Categories