openerp7 - Return tree view from class with no new fields - treeview

I'm new to OpenERP 7, what is the correct way to return a tree view? How can i return the data i obtained from my function?
Here's my class code:
class albaranes_fallidos(osv.osv):
_name = 'albaranes_fallidos'
_inherit = 'stock.picking'
_columns = {}
def find(self, cr, uid, ids, context=None):
stock_picking = self.pool.get('stock.picking')
exist_state = stock_picking.search(cr, uid, [('state','=','confirmed'),('origin','ilike','SO')])
###
exist_lines = stock_picking.browse(cr, uid, exist_state, context)
###
exist_IN = stock_picking.search(cr, uid, [('type','=','in'),('origin','ilike',':SO')])
for SO in exist_lines:
exist_PO = stock_picking.browse(cr, uid, exist_IN, context)
for POSO in exist_PO:
if SO.origin in POSO.origin:
_logger.info(POSO.origin)
break

You need to use a domain to specify which record to load in tree view:
return {
'type': 'ir.actions.act_window',
'name': _('Stock picking'),
'res_model': 'stock.picking',
'view_type': 'form',
'view_mode': 'tree,form',
'target': 'current',
'domain': [('id', 'in', exist_IN)]
}

Related

Return view with activated filter in Odoo

I'm trying to return a tree view in Odoo filtered by a parameter. Some one knows how to code the variable my_context of the view?
I need to apply the filter with the field: father_competence_id
The filter is defined as:
<filter name="groupby_fathercompetence"
context="{'group_by' : 'father_competence_id'}"
string="Father competence" />
academic_record_lines = self.env['education.record']
for line in self:
academic_record_lines = academic_record_lines + line.env['education.record'].search([('n_line_id', '=', line.id)])
return {
'name': _('Academic records for {} [{}]').format(
description, self.planification_id.teacher_id.name),
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'education.record',
'type': 'ir.actions.act_window',
'context': **my_context**,
'domain': [('id', 'in', academic_record_lines.ids)],
}
Please use the below code
my_context = dict(self._context or {})
my_context.update({'':})
Using my_context.update you can add filters through context.
return {
'name': _('Academic records for {} [{}]').format(
description, self.planification_id.teacher_id.name),
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'education.record',
'type': 'ir.actions.act_window',
'context': my_context,
'domain': [('id', 'in', academic_record_lines.ids)],
}
If you know the filter name, which is normally set by attribute name on the search <filter> entries, you can automatically activate them by an action by providing the filter name with search_default_ in front of it and as value a truthy value like True or 1.
academic_record_lines = self.env['education.record'].search(
[('n_line_id', 'in', self.ids)])
context = dict(self.env.context or {})
context['search_default_groupby_fathercompetence'] = True
return {
# self.pla... only working with singleton!!!
'name': _('Academic records for {} [{}]').format(
description, self.planification_id.teacher_id.name),
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'education.record',
'type': 'ir.actions.act_window',
'context': context,
'domain': [('id', 'in', academic_record_lines.ids)],
}

Return any data from a query using GraphQL, Graphene and Python

I am receiving the following error:
{
"errors": [
{
"message": "Unknown argument \"project_id\" on field" +
\"get_project_detail_summary\" of type \"Query\".",
"locations": [
{
"line": 2,
"column": 30
}
]
}
]
}
With the following query:
query GetProjectDetailSummary($project_id: Int) {
get_project_detail_summary(project_id: $project_id) {
comments {
... on ManagerCommentNode {
id
text
created
}
... on VendorCommentNode {
id
text
created
}
... on TenantCommentNode {
id
text
created
}
}
}
}
With the following backend code, How can I get to the breakpoint?, or how do I send back custom data given a number?:
class CommentsUnion(graphene.types.union.Union):
class Meta:
name = 'CommentsUnion'
types = (ManagerCommentNode, VendorCommentNode, TenantCommentNode, )
class ProjectSummaryInput(graphene.InputObjectType):
project_id = graphene.Int()
class ProjectSummaryNode(graphene.ObjectType):
Input = ProjectSummaryInput
project_id = graphene.Int()
comments = graphene.List(CommentsUnion)
#classmethod
def resolve_comments(self, *args, **kwargs):
import pdb;pdb.set_trace()
return ProjectSummary.select_related('comments').objects.filter(comments__created__lt=dt)
class Query(graphene.ObjectType):
get_project_detail_summary = Field(ProjectSummaryNode)
In regards to the error.
Be sure to add a kwarg ( e.g. project_id in this example, it is the reason for the "unknown argument on field" error ) to the graphene.Field for get_project_detail_summary.
Like so:
class Query(graphene.ObjectType):
get_project_detail_summary = Field(ProjectSummaryNode, # see below for example
project_id=graphene.Int() # kwarg here
)
def resolve_get_project_detail_summary(self, info, **kwargs):
return ProjectSummary.objects.get(id=kwargs.get('project_id'))
In regards to returning any data.
This is a way ( returning a graphene.String ), but it untypes the response by putting everything inside a String:
from django.core.serializers.json import DjangoJSONEncoder
class ProjectSummaryRecentUpdatesNode(graphene.ObjectType):
Input = ProjectSummaryInput
recent_updates = graphene.String()
def resolve_recent_updates(self, resolve, **kwargs):
instance = Project.objects.get(id=resolve.variable_values.get("project_id"))
things = instance.things.all()
# these are all from different models, and the list is a bit longer than this.
querysets = (
("scheduled", get_scheduled(things, resolve, **kwargs)),
("completed", get_completed(things, resolve, **kwargs)),
("invoices", get_invoices(things, resolve, **kwargs)),
("expenditures", get_expenditures(things, resolve, **kwargs)),
("comments", get_comments(things, resolve, **kwargs)),
("files", get_files(things, resolve, **kwargs)),
)
recent_updates = []
for update_type, qs in querysets:
for item in qs:
item.update(
{
"recent_update_type": update_type
}
)
recent_updates.append(item)
return json.dumps(recent_updates, cls=DjangoJSONEncoder)
And on the frontend, with an import { Query } from "react-apollo"; element we can JSON.parse the field ... which has "any" (json serialized) data inside of it:
<Query
query={GET_PROJECT_DETAIL_SUMMARY_RECENT_UPDATES}
fetchPolicy="network-only"
variables={{ project_id: this.props.projectId }}
>
{({ loading, error, data }: QueryResult) => {
if (
data &&
data.get_project_detail_summary_recent_updates &&
data.get_project_detail_summary_recent_updates.recent_updates
) {
console.log(JSON.parse(data.get_project_detail_summary_recent_updates.recent_updates))
}
}}
</Query>
Side note:
If there isn't a large list of data types create a Union like object which has all of the fields needed from different models, or an actual Union, which seems like the correct way, as then types are not lost:
class ProjectSummaryNode(graphene.ObjectType):
# from FileNode graphene.ObjectType class
file__id = graphene.Int()
file__brief_description = graphene.String()
file_count = graphene.Int()
last_file_created = graphene.String()
last_file = graphene.String()
# from UploaderNode graphene.ObjectType class
uploader__first_name = graphene.String()
uploader__last_name = graphene.String()
# from CommentNode graphene.ObjectType class
comment = graphene.String()
class Meta:
name = "ProjectSummaryNode"
# example of Union, the above fields would be commented out, as they are part of
# the different graphene.ObjectType classes, and this line below would be uncommented
# types = ( FileNode, UploaderNode, CommentNode, )
Still open to suggestions on a better way to do this.

How to delete any filed in ViewSet

class DepartSerializer(serializers.HyperlinkedModelSerializer):
attrs = AttrSerializer(source="depattr", many=True)
people = PeopleSerializer(source='perdepart', many=True)
class Meta:
model = Departs
fields = ('url', 'name', 'describe', 'pinyin', 'attrs', 'people')
class DepartsViewSet(viewsets.ReadOnlyModelViewSet):
"""
i want delete people field in List , and Retain people fieled in retrieve.
"""
queryset = Departs.objects.filter(disabled=False).order_by('-uptime')
serializer_class = DepartSerializer
1.I want the result like this:
2.get /depart
[
{"name":"depart1","id":1},
{"name":"depart2","id":2},
]
3.get /depart/1
{
"name": "depart1",
"id": 1,
"people": [{
"id": 1,
"name": "per1"
},
{
"id": 2,
"name": "per2"
}
]
}
You can use different serializers in your viewset depending on the action by overriding the viewset's get_serializer_class:
def get_serializer_class(self):
if self.action == 'retrieve':
return DepartSerializerWithoutPeople
return DepartSerializer
retrieve is the action called by get /depart/1/. And then you can define your DepartSerializerWithoutPeople like this:
class DepartSerializerWithoutPeople(serializers.HyperlinkedModelSerializer):
attrs = AttrSerializer(source="depattr", many=True)
class Meta:
model = Departs
fields = ('url', 'name', 'describe', 'pinyin', 'attrs',)

Why do I get this error?: Expected singleton: spray.action(1, 2)

I have a button in a form that when clicked is supposed to update the current model mrl with data from the spray.action model. Then I do further processing but it raises the error
ValueError("Expected singleton: %s" % self) ValueError: Expected singleton: spray.action(1, 2)
#api.multi
def mrlCreateSprayRecords(self):
spray_ids = []
vals = []
spray_obj = self.env['spray.action'].search([])
print("spray_obj \n\n\n\t %s ", spray_obj)
for obj in spray_obj:
print("Spray Action Objects \n\n %s \n\t ", obj)
vals = {
'ref': obj.ref,
'farm': obj.farm.farm,
'block': obj.block.block,
'valves': obj.valves.valve,
}
print("Spray Action Data Browse , \n\n\t %s ", vals)
res = super(Mrl, self).create(vals)
res.update(vals)
print("object in mrlCreateSprayRecords \n\n\t %s", res)
return {
'name': 'Update Mrl Operations',
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'mrl',
'views': [(spray_obj.id, 'form')],
'view_id': spray_obj.id,
# 'target': 'new',
'res_id': self.id,
'context': self.env.context,
}
I think you are getting the error in the row 'view_id': spray_obj.id, you must write the view id there. The spray_obj recordset has many record, so you cannot use it like that (spray_obj.id). You can also remove the view_id parameter in order to user the default view.
#api.multi
def mrlCreateSprayRecords(self):
self.ensure_one()
spray_obj = self.env['spray.action'].search([]) # recordset of all records of the model????
for obj in spray_obj:
vals = {
'ref': obj.ref,
'farm': obj.farm.farm,
'block': obj.block.block,
'valves': obj.valves.valve,
}
self.create(vals)
view_id = self.env.ref('module.xml_view_id').id
return {
'name': 'Update Mrl Operations',
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': 'mrl',
'view_id': view_id,
'res_id': self.id,
'context': self.env.context,
}
I have added self.ensure_one() because res_id has to be only one id as well.
I have remove the res.update(vals) line because it does not make any sense to me haha
More things
Instead of print you should use the logger:
import logging
_logger = logging.getLogger(__name__)
_logger.info('Hello')
Instead the line res = super(Mrl, self).create(vals) I think you should use this one
res = self.create(vals) # if you are in the mrl model
In short you get this kind of error when you acces a field direclty of a recordSet that contains more than one record.
You performed a search on the spray.action that search returnd 2 record (1, 2)
So when you do spray_obj.id odoo will be confused what id he should return 1 or 2. And here odoo throw this error.
So dont access a field a search result, or a x2many fiels they may have more than one record inside.
#ChesuCR has improved your code and corrected it

How to filter records based on nested data using django rest framework

I have this json response from my customer api based on django rest framework.
When I hit api
http://localhost:8000/api/customers
I receive following response
[
{
'name': 'Daniel',
'group': 'BK',
'user_id': 102,
'user_details': {
'username': 'dan1',
'active': true,
}
},
{
'name': 'John',
'group': 'BK',
'user_id': 103,
'user_details': {
'username': 'john1',
'active': true,
}
}
]
Now I need to filter record whose username=john1, how do I do that?
I have tried using this in my customer viewset by defining filter backend
filter_fields = ('user_details__username',)
and tried hitting the api as
http://localhost:8000/api/customers?user_details__username=john1
but it gives error as
'Meta.fields' contains fields that are not defined on this FilterSet:
user_details__username
Its happening because user_details is not the field of my customer serializer, its basically SerializerMethodField which manipulates user information to display under customer api.
Here is my customer serializer
class CustomerSerializer(serializers.HyperlinkedModelSerializer):
user_details = serializers.SerializerMethodField('get_serialized_target_object')
class Meta:
model = Customer
fields = '__all__'
def get_serialized_target_object(self, obj):
usr_id = obj.user_id
if usr_id:
instance = User.objects.filter(pk=usr_id)
if instance:
instance = instance[0]
return UserSerializer(instance=instance).data
else:
return None
and here is my viewset
class CustomerViewSet(viewsets.ModelViewSet):
queryset = Customer.objects.all()
serializer_class = CustomerSerializer
filter_fields = ('user_details__username',)
Please help me how do I filter my record from customer api with username=john1
You should not use SerializerMethodField.
Try the serializer below:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'active',)
class CustomerSerializer(serializers.ModelSerializer):
user_details = UserSerializer(many=True)
class Meta:
model = Customer
fields = '__all__'
Then you can define your field as filter_fields = ('user_details__username',)

Resources