I'd like to shorten the following code from
if field == 'favorite_food':
model_instance.update(favorite_food=value)
elif field == 'favorite_drink':
model_instance.update(favorite_drink=value)
elif field == 'favorite_color':
model_instance.update(favorite_color=value)
to something like:
if field in list:
model_instance.update(field=value)
So I'm just wondering if it's possible.
You can just unpack into keyword arguments:
model_instance.update(**{field: value})
There is also an option to set the model field value and then save (there are though differences):
setattr(model_instance, field, value)
model_instance.save()
You can do this
fields = ["favorite_food", "favorite_drink", "favorite_color"]
field = "favorite_food"
if field in fields:
model_instance.update(field=value)
Related
I know I can filter Many2one fields, from python code, or even xml views, with the domain flag, but I have a slightly different scenario right now,
Consider having a model like this:
class MyModel(models.Model):
_name = 'mymodel'
fieldsel = fields.Selection([('sheet', 'Sheet'),('reel','Reel')], string='Printing PPT Type',
track_visibility='onchange', copy=False,
help=" ")
fieldmany = fields.Many2one('text.paper', string="Text Paper")
The text.paper model has another Selection field, which has the same values as fieldsel, however, I cannot use domain since it will filter every text.paper statically.
My issue is, that I need to filter text.paper depending on which option I choose from fieldsel, so, let's say text.paper looks something like this:
class text_paper(models.Model):
_name = 'text.paper'
name = fields.Char(string="Code")
paper_type = fields.Selection([('sheet', 'Sheet'),('reel','Reel')], string="Paper Type")
I need to filter from mymodel the text.paper depending on the fieldsel field, if reel selected, filter text.paper which are reel, and if sheet selected, filter text.paper accordingly.
I hope I've explained myself.
Any ideas?
what you need is dynamic domain for many2one you can achive this by onchange event
class MyModel(models.Model):
_name = 'mymodel'
....
...
#api.onchange('fieldsel ')
def change_domain(self):
"""change the domain of fieldmany whenever the user changes the selected value."""
self.fieldmany = False # may be you want to reset the value when the user changes the selected value
if self.fieldsel : # make sure the user has selected a value
return {'domain': {fieldmany: [('paper_type', '=', self.fieldsel)]}}
else: # remove domain
return {'domain': {fieldmany: []}}
I want to get the field names in a model to be an option in a selection field in another model. Is it possible?
class ExportEmplWizard(models.TransientModel):
_name = 'hr.empl.exp.wizard'
empl_ids = fields.Many2many('hr.employee', string="Karyawan")
hr_field = fields.Selection(hr_field_choice, string="Pilih Kolom")
def empl_to_exp(self):
fields = self.env['hr.employee'].fields_get()
hr_field_choices = []
for key, val in fields.items():
choice = (key, val['string'])
hr_field_choices.append(choice)
I'm trying get fields name on other model using:
sel.self.env['hr.employee'].fields_get()
The problem is, i don't know how to make it as selection options (multiple selection actually).
Thank you for the help.
As per docstring for fields.Selection()
:param selection: specifies the possible values for this field.
It is given as either a list of pairs (value, string), or a
model method, or a method name.
Basically, the selection argument should work like the compute argument. And code of fields.Selection.get_values() confirms this.
So you should try something like this :
hr_field = fields.Selection(selection='empl_to_exp', string="Pilih Kolom")
def empl_to_exp(self):
fields = self.env['hr.employee'].fields_get()
return [(k, v['string']) for k, v in fields.items()]
You may have/want to use getattr(v, 'string', 'DEFAULT_VALUE') instead of simply v['string']. Fields should always have a string though.
def get_selection_name(env, model, field, value):
return dict(env[model].fields_get(field, 'selection').get(field, {}).get('selection',{})).get(value)
# usage
get_selection_name(request.env, 'sale.order', 'general_status', 'draft') # 'Draft'
get_selection_name(self.env, 'sale.order', 'general_status', 'draft') # 'Draft'
I use this!
Here is some field in a Document using mongoengine
_id = f.ObjectIdField(db_field="i", required=True)
name = f.StringField(db_field="n")
I would like to loop through each field in the Document and see if they are type XField and is_required is True, is there a way of doing that?
I know you can list out all fields using _fields
but
for field in SomeDocument._fields:
print type(field) # always return 'str' not 'StringField' or 'ObjectField'
# Don't know how to check is_required
Any help would be appreciated.
You can simply use this
field_dict = SomeDocument.get_fields_info()
for field_name, field in field_dict.iteritems():
print field_name, field.required, field.__class__
The issue you were having is that SomeDocument._fields is a dictionary, so iterating on it is giving you the keys (which are strings). For instance if you have a field foo, you can do SomeDocument._fields['foo'].required. And of course you can do something like:
for field in SomeDocument._fields:
print '{} {} required.'.format(SomeDocument._fields[field], 'is' if SomeDocument._fields[field].required else 'is not')
I am trying to iterate over form results and I can't help but think that I am re-inventing the wheel here.
filterlist = []
if request.POST:
form = FilterForm(request.POST)
if form.is_valid():
for key, value in form.cleaned_data.iteritems():
filterlist.append(key)
filterlist.append(value)
This works, but seems very awkward and creates lots of other problems. For example the values come back with u' so I have to use value.encode("utf8") but then if a value is None it throws in error. So now I have to check if it is None, if not then encode. There has to be a better way.
EDIT: What I am trying to do.
I am trying to filter what is shown on a page. The problem I am running into is that if a value is empty (the user don't fill the box because they only want to filter against one object) then I get no results. For example a user wants to search for all books by the author name "Smith" but doesn't want to search against a genre.
results = Books.objects.filter(author=author, genre=genre)
The user would get no results because this is an AND search. But, if a user put in "Smith" for the author and "mystery" for the genre then it works exactly like I want it to, only giving results where both are true.
So, I am trying to eliminate the empty stuff by iterating over the form results. Like I said I am probably re-inventing the wheel here.
In Python 3 use:
for key, value in form.cleaned_data.items():
If the field names are the same in the model and the form, try this:
filter = {}
if request.method == 'POST':
form = FilterForm(request.POST)
if form.is_valid():
for key, value in form.cleaned_data.iteritems():
if value:
filter[key] = value
results = Books.objects.filter(**filter)
Python is one of the few languages having named parameters. You can assemble a dict with the non-empty form fields and pass it to the filter method using the kwargs unpacking operator **.
For example:
kwargs = {"author": "Freud"}
results = Books.objects.filter(**kwargs)
Is the same as:
results = Books.objects.filter(author="Freud")
I think the problem is that by default the Model form is not valid if a form field does not have a value entered by the user, if you don`t require the field every time from the user you need to set the required field to false in the ModelForm class in forms.py as shown in the code below. Remember that the field is set false only in the model form not in the model itself
class myForm(forms.ModelForm):
myfield_id = forms.CharField(required=False)
myfield_foo = forms.CharField(required=False)
myfield_bar = forms.CharField(required=False)
myfield_name = forms.CharField(required=False)
class Meta:
model = myModel
exclude = ('myfield_ex','myfield_file')
fields = ['myfield_id','myfield_foo','myfield_bar','myfield_name',]
After you have the form entered by the user what you need is use the Q object which can be used to create complex queries as described in the manula page here
https://docs.djangoproject.com/en/1.7/topics/db/queries/#complex-lookups-with-q
A simple example code would look like
if form.is_valid():
qgroup = []
for key,value in form.cleaned_data.iteritems():
if value:
q_name = Q(**{"%s"%format(filterKey[key]) : value})
qgroup.append(q_name)
q = None
# can use the reduce as shown here qgroup = reduce(operator.or_, (Q(**{"{0}".format(filterKey[key]): value}) for (key,value) in form.cleaned_data.iteritems()))
for key,value in form.cleaned_data.iteritems():
if value:
q_name = Q(**{"%s"%format(filterKey[key]) : value})
qgroup.append(q_name)
for x in qgroup:
q &= x ### Or use the OR operator or
if q:
resultL = myModel.objects.filter(q).select_related()
The filterKey can look something on the lines of
filterKey = {'myfield_id' : "myfield_id",
'myfield_foo' : "myfield_foo__icontains",
'myfield_bar' : "myfield_bar__relative_field__icontains",
}
I have the following code in Django for a Form.
class ProductAddToCartForm(forms.Form):
quantity = forms.IntegerField(widget=forms.TextInput(attrs={'size':'2', 'value':'1', 'class':'quantity', 'maxlength':'5'}), error_messages={'invalid':'Please enter a valid quantity.'}, min_value =1)
product_slug = forms.CharField(widget=forms.HiddenInput())
sizes_available = []
sizes_available.append(7)
sizes_available.append(9)
size = forms.ChoiceField(widget=forms.Select, choices=sizes_available)
However when I compile this the ChoiceField, CharField and the IntegerField doesn't show up. When I comment out the line with size = ... then IntegerField and CharField shows up. I think there is something wrong with my ChoiceField declaration but I'm not sure what exactly.
https://docs.djangoproject.com/en/1.4/ref/forms/fields/#choicefield
Choices must be
An iterable (e.g., a list or tuple) of 2-tuples to use as choices for
this field.
Try to .append((7,7))