Loading a dropdown content dynamically - dropdown

I'm new in the Odoo world and now I'm stuck. I have this (Odoo v11.0):
Model: class Dog()
dog_name = fields.Char()
gps = fields.Many2One(Model Gps)
Model: class Gps()
serial = fields.Char()
I have a Gps list that is show in the Dog's form as a dropdown list, each time a Dog record is created only one Gps can be assigned to it, so the next time I create a Dog those assigned Gps must not appear in the dropdown list.
How to accomplish it?
Thanx in advance

Please add below method in class Gps.
#api.multi
def name_get(self):
if self._context.get('filter_gps'):
gps_records = self.env['Dog'].search([('gps','!=',False)]).mapped('gps')
new_self = self - gps_records
return super(Gps,new_self).name_get()
return super(Gps,self).name_get()

Add this method to Dog class:
#api.one
#api.onchange('gps')
def onchange_gps(self):
If not self.gps:
Res = {}
Ids = []
Dogs = self.env['dog'].search([])
Ids = [d.gps for d in dogs]
Res['Domain'] = {'gps' : [('id', 'not in', ids)]}
Return res

Related

Understanding Full Join in Django

I have two models in my app:
# Create your models here.
class Melody(models.Model):
notes = models.JSONField()
bpm = models.IntegerField()
aimodel = models.CharField(max_length=200)
score = models.IntegerField(default=0)
person = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="melodies")
date_created = models.DateTimeField(default=timezone.now)
def __str__(self):
return str(self.id)
class Vote(models.Model):
user_score = models.IntegerField(validators=[MaxValueValidator(1), MinValueValidator(-1)])
melody = models.ForeignKey(Melody, on_delete=models.CASCADE, related_name="scores")
person = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="voters")
def __str__(self):
return f"{self.person} - {self.melody} - {self.score}"
And I get the melodies of the current user by
# Get melodies of current user
melodies = Melody.objects.all().filter(person=person).order_by('-score')[start:end+1].values()
I would like to add to this results the vote of the user to each melody, if there is one, otherwise just null so I can loop over the melodies and retrieve the values:
melody.notes = ...
melody.bpm = ...
melody.user_score = This is the values I do not know still how to get, Null if user has not voted
I was reading about select_related but when I use it it always says
"Invalid field name(s) given in select_related: 'xxxx'. Choices are: (none)"
What am I missing?
EDIT
I solved it based on the answer of #Fnechz by making two queries and then looping over the elements so I can add the user_score to the melody:
# Get melodies of current user
melodies = Melody.objects.all().filter(person=person).order_by('-score')[start:end+1].values()
# Get votes of the user
votes = Vote.objects.all().filter(person=person)
for i, m_melody in enumerate(melodies):
for m_vote in votes:
if (m_vote.melody.id == m_melody['id']):
melodies[i]['user_score'] = m_vote.user_score
return JsonResponse({"melodies": list(melodies)})
Not sure if this is the best way to achieved it
I do not know if there is a direct method to accomplish what you want with a single query. But I guess concatenating the queryset results might work.
from itertools import chain
melodies = Melody.objects.all().filter(person=person).order_by('-score')[start:end+1].values()
votes = #query your vote model here to get the user_score
result_list = list(chain(melodies,votes))
If I have understood your question that might work

Odoo 10 selection fields value

How can i get selection fields value in odoo 10?
def compute_default_value(self):
return self.get_value("field")
I tried this,
def compute_default_value(self):
return dict(self._fields['field'].selection).get(self.type)
Also tried this,but it is not working.
Please help me, i could not find the solution.
Thank you.
You can do this in a following manner:
self._fields['your_field']._desription_selection(self.env)
This will return the selection list of pairs (value, label).
If you just need possible values, you can use get_values method.
self._fields['your_field'].get_values(self.env)
But it's not a common way. Most of the time people define selections differently and then use those definitions. For example, I commonly use classes for those.
class BaseSelectionType(object):
""" Base abstract class """
values = None
#classmethod
def get_selection(cls):
return [(x, cls.values[x]) for x in sorted(cls.values)]
#classmethod
def get_value(cls, _id):
return cls.values.get(_id, False)
class StateType(BaseSelectionType):
""" Your selection """
NEW = 1
IN_PROGRESS = 2
FINISHED = 3
values = {
NEW: 'New',
IN_PROGRESS: 'In Progress',
FINISHED: 'Finished'
}
You can use this class wherever you want, just import it.
state = fields.Selection(StateType.get_selection(), 'State')
And it's really handy to use those in the code. For example, if you want to do something on a specific state:
if self.state == StateType.NEW:
# do your code ...
I don't get the question fully, but let me try to answer. Why not just define the selection as method and use it for both situations:
from datetime import datetime
from odoo import models, fields
class MyModel(models.Model):
_name = 'my.model'
def month_selection(self):
return [(1, 'Month1'), (2, 'Month2')]
def compute_default_value(self):
selection = self.month_selection()
# do whatever you want here
month = fields.Selection(
selection=month_selection, string='Month',
default=datetime.now().month, required=True)

Django - id null - foreign key error

Error:
app_a.desc_id may not be NULL
I believe my problem is I'm not passing the id from formB to formA when I save. please please lead me to a solution for this problem.
Here's my view:
def form(request):
if request.method == 'GET':
formB = BForm()
formA = AForm()
return render(request,r'app/form.html',{'formA':formA,'formB':formB})
elif request.method == 'POST':
formA = AForm(request.POST)
formB = BForm(request.POST)
formB.save()
formA.save()
return HttpResponseRedirect('/log')
Here are my models:
# Descprition
class B(models.Model):
id = models.AutoField(primary_key=True)
description = models.CharField(max_length=50)
# Title
class A(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField('Name',max_length=20)
desc = models.ForeignKey(B)
and here is my form:
class BForm(forms.ModelForm):
class Meta:
model = B
fields = ['description']
class AForm(forms.ModelForm):
class Meta:
model = A
fields = ['name']
Your program has multiple errors but the main problem for this is because desc is a foreign key in class A that points to class B, and you don't have null=True on it, meaning you never want that field to be empty. In other words, each instance of A should have a foreign key desc.
If you just save() both forms, formA tries to save an instance of A, without having a value for desc field, hence the error. You should assign the instance that formB creates to the instance that formA creates:
new_b = formB.save()
new_a = formA.save(commit=False)
new_a.desc = new_b
new_a.save()
Other problems in your program including never called form.is_valid(), having redundant id fields(django would create one for you). I suggest you read django tutorial first before jumping into coding. It would save a lot of time like figuring out errors like this.

Increment integer fileds Odoo

I have added this fields under account.invoice in order to get an autoincrement number but it doesn't work.
Help me please to figure out my error
Example Code
class invoice(osv.osv):
_inherit = 'account.invoice'
def _get_increment(self, cr, uid, ids, fields, arg, context=None):
if context is None: context = {}
res = {}
if type == 'out_invoice':
ids = self.search(cr,uid,[('id','!=',False),('type','in',('out_invoice','out_refund'))])
if ids:
last_id = ids and max(ids)
print 'last_id',last_id
for invoice in self.browse(cr, uid, last_id, context):
print 'invoice', invoice
if invoice.name1:
res[invoice.id] = invoice.name1
else :
res[invoice.id] = invoice.name1 + 1
return res
_columns={
'name1':fields.function(_get_increment, type='integer', string='Name1'),
}
First of all. Your function never returns a value since type is never set.
Which means the if condition is never triggered.
At second. I'd suggest that you'd use the new Odoo API.
function fields are replaced by the compute attribute on fields and the declaration no longer takes place in the _columns dictionary.
New API
instead of importing from openerp.osv you should import the following:
from openerp import fields, models, api
The code would look like this:
from openerp import fields, models, api
class invoice(models.Model):
_inherit = 'account.invoice'
name1 = fields.Integer('Name1', compute='_get_increment')
#api.one
def _get_increment(self):
self.name1 = 1 + 1 #This value should be the value that you've calculated
the only thing you need to do in the method _get_increment is set self.name1.
In the new API self is a record. So self.id would get you the id of the record and so on.

How to create object of one Model after creating another Model's object using serialization and modelViewSet

These are MODELS:
class Event (models.Model):
status = models.CharField(max_length = 30, blank = True)
time = models.DateTimeField()
point = models.ForeignKey(Point)
person = models.ForeignKey(Person)
device = models.ForeignKey(Device)
organization = models.ForeignKey(Organization)
class Presence(models.Model):
point = models.ForeignKey(Point)
person = models.ForeignKey(Person)
date_from = models.DateTimeField()
date_to = models.DateTimeField()
This is SERIALIZERS:
class EventSerializer(serializers.ModelSerializer):
person = serializers.SlugRelatedField(queryset=Person.objects.all(), slug_field='card_tag')
class Meta:
model = Event
fields = ['id','time','point','person','device','organization']
this is API:
class EventAPI(viewsets.ModelViewSet):
serializer_class = cs.EventSerializer
This is URL:
url(r'^event/', api.EventAPI.as_view({'post':'create'}), name='event_create'),
so I want these:
after every creation of Event object, check it by %2 (getting number of objects by card_tag, which is in body of request), if it's number
of events %2 == 0 => create object of Presence, how can I do it ?
Thanks and sorry
You should be able to use the perform_create method, which by default looks something like:
def perform_create(self, serializer):
serializer.save()
Now you can override it and do pretty much anything you want.
def perform_create(self, serializer):
serializer.save()
if ..something.. % 2:
Presence.objects.create(...)