How can I get a list of ticket fields (like milestone, version, and all the custom fields) in Trac via Python?
In the Trac documentation I have found the TicketSystem class, but it is a component and I cannot instantiate it. So how do I access its methods if I need an instance for it?
Edit: I found out how I can access the default fields. E.g. for milestones, it is model.Milestone.select(self.env). Now the problem is, how can I access custom ticket fields? There must be a way to do it without having to access the database manually, since the method get_custom_fields() in the TicketSystem class exists.
Edit 2: I just found out that get_custom_fields() only returns the available fields, but not their values. What I want to do is get all available values of a specific custom field.
In the Trac documentation I have found the TicketSystem class, but it is a component and I cannot instantiate it.
You can obtain a reference to the Component, which is a singleton, with the statement ts = TicketSystem(self.env).
I just found out that get_custom_fields() only returns the available fields, but not their values. What I want to do is get all available values of a specific custom field.
That is incorrect. You can obtain the possible values of a ticket custom field with the statements:
fields = TicketSystem(self.env).get_custom_fields()
options = fields[idx].get('options', [])
where idx is the index of the field in the list for which you wish to retrieve the options. The list will only be non-empty if field['type'] is select or radio. See trac.ticket.api.TicketSystem.customfields.
I found out how I can access the default fields. E.g. for milestones, it is model.Milestone.select(self.env).
You should access all fields using TicketSystem(self.env).get_ticket_fields(). That statement will return all fields, including custom fields.
Related
I'm using Odoo 10. After a new user sign up (through localhost:8069/web/signup) i want him to be automatically allocated inside a group i created on my very own custom module (the user will need authentication from an admin later on so he can be converted to a regular portal user; after signup he will receive restricted access).
I have tried many things. My latest effort looks like this:
class RestrictAccessOnSignup(auth_signup_controller.AuthSignupHome):
def do_signup(self, *args):
super(RestrictAccessOnSignup, self).do_signup(*args)
request.env['res.groups'].sudo().write({'groups_id': 'group_unuser'})
Note that I have import odoo.addons.auth_signup.controllers.main as auth_signup_controller so that I can override the auth_signup controller.
I have located that method as the responsible for doing the signup. So I call it in my new method and then try to change the newly created user's group_id.
What i miss is a fundamental understanding of how to overwrite a field's value from another model inside a controller method context. I'm using the 'request' object although i'm not sure of it. I have seen people using 'self.pool['res.users'] (e.g.) for such purposes but i don't understand how to apply it inside my problem's context.
I believe, also, that there is a way to change the default group for a user after it is created (i would like to know), but i also want to understand how to solve the general problem (accessing and overwriting a field's value from another module).
Another weird thing is that the field groups_id does exist in 'res.users' model, but it does not appear as a column in my pgAdmin interface when i click to see the 'res.users' table... Any idea why?
Thanks a lot!
i don't know if after calling :
super(RestrictAccessOnSignup,self).do_signup(*args)
you will have access to user record in request object but if so just add
the group to user like this, if not you have to find where the user record or id is saved after calling do_signup because you need to update that record to ad this group.
# create env variable i hate typing even i'm typing here ^^
env = request.env
env.user.sudo().write({'groups_id': [
# in odoo relation field accept a list of commands
# command 4 means add the id in the second position must be an integer
# ref return an object so we return the id
( 4, env.ref('your_module_name.group_unuser').id),
]
})
and if changes are not committed in database you may need to commit them
request.env.cr.commit()
Note: self.env.ref you must pass the full xmlID.
This is what worked for me:
def do_signup(self, *args):
super(RestrictAccessOnSignup, self).do_signup(*args)
group_id = request.env['ir.model.data'].get_object('academy2', 'group_unuser')
group_id.sudo().write({'users': [(4, request.env.uid)]})
In the get_object i pass as arguments the 'module' and the 'xmlID' of the group i want to fetch.
It is still not clear to me why 'ir.model.data' is the environment used, but this works as a charm. Please note that here we are adding a user to the group, and not a group to the user, and to me that actually makes more sense.
Any further elucidation or parallel solutions are welcome, the methods aren't as clear to me as they should be.
thanks.
I have two models which I want to relate: User and Group.
Each user belongs to a group. I've tried to create a default user by using in get_or_create():
group = models.ForeignKey(Group.objects.get_or_create(name="Free")[0])
But it raises the following error:
(fields.E300) Field defines a relation with model 'Group', which is either not installed, or is abstract.
What can I do to fix this issue?
Each user must have a non-null group value. So I've read about this get_or_create() method. But I've also seen that it can return more than one object... and I don't want it to happen. I thought about creating a unique name parameter but is there a better solution for it?
Can you help me, please? I appreciate your help.
A more comprehensive answer can be found here: How to set a Django model field's default value to a function call / callable (e.g., a date relative to the time of model object creation)
You need to specifify the related Model and set the default.
class User(models.Model):
def default_group(self):
return Group.objects.get_or_create(name="Free")[0]
group = models.ForeignKey('app_name.Group', default=default_group)
Your default value would be evaluated at model definition time, but Django allows you to provide a callable as default, which is called for each instance creation.
To explain the error - code that is not inside a function, such as the line in your question, is executed as soon as your models.py file is loaded by Python. This happens early in the start-up of your Django process, when Django looks for a models.py file in each of the INSTALLED_APPS and imports it. The problem is that you don't know which other models have been imported yet. The error here is because the Group model (from django.auth.models) has not been imported yet, so it is as if it doesn't exist (yet).
Others have suggested you could put the Group.objects.get_or_create(name="Free")[0] in a function so that it is not executed immediately, Django will instead call the function only when it needs to know the value. At this point all the models in your project, and Django's own models, will have been imported and it will work.
Regarding the second part of your question... yes, any time you use get or get_or_create methods you need to query on a unique field otherwise you may get MultipleObjectsReturned exception.
In fact I think you should not use get_or_create for what you are trying to do here. Instead you should use an initial data fixture:
https://docs.djangoproject.com/en/1.9/howto/initial-data/
...to ensure that the default group already exists (and with a known primary key value) before you run your site.
That way you will know the unique pk of the default Group and you can do a get query:
def default_group():
return Group.objects.get(pk=1)
class YourModel(models.model):
group = models.ForeignKey(Group, default=default_group)
I started using the new API of Odoo v8.0 but I cannot find useful information about store trigger in computed fields like this (for v7.0 and v6.1): Store Parameter in Odoo v6
In Odoo v8.0, I tried to use the same syntax of v7.0 but I couldn't get it to work because the JSON response cannot be returned back to the web client:
<function _store_trigger> is not JSON serializable.
I read then that store parameter had been converted to Boolean only field (no dict for triggers): Odoo store function: JSON not serializable
So how can I set trigger to store values in database for computed (and related) fields? I want to make filters and groups mainly for them so search function won't be useful.
In V8, you can use any fields as computed fields. In V8 store is a parameter which is a boolean and by default it is false.
If you set explicitly "store=True", the dependent field you mentioned in #api.depends('name'), will acts as a triggering field.
You can specify, the other object field as a triggering field which will be must in accounting module like #api.depends('other_object.field_name')
upper = fields.Char(compute='_compute_upper', store=True)
#api.depends('name')
def _compute_upper(self):
for rec in self:
self.upper = self.name.upper() if self.name else False
If it "false", then the value is not stored in database and will be computed everytime.
upper = fields.Char(compute='_compute_upper')
A mongoengine.DynamicEmbeddedDocument can be used to leverage MongoDB's flexible schema-less design. It's expandable and doesn't apply type constraints to the fields, afaik.
A mongoengine.DictField similarly allows for use of MongoDB's schema-less nature. In the documentation they simply say (w.r.t. the DictField)
This is similar to an embedded document, but the structure is not defined.
Does that mean, then, the mongoengine.fields.DictField and the mongoengine.DynamicEmbeddedDocument are completely interchangeable?
EDIT (for more information):
mongoengine.DynamicEmbeddedDocument inherits from mongoengine.EmbeddedDocument which, from the code is:
A mongoengine.Document that isn't stored in its own collection. mongoengine.EmbeddedDocuments should be used as fields on mongoengine.Documents through the mongoengine.EmbeddedDocumentField field type.
A mongoengine.fields.EmbeddedDocumentField is
An embedded document field - with a declared document_type. Only valid values are subclasses of EmbeddedDocument.
Does this mean the only thing that makes the DictField and DynamicEmbeddedDocument not totally interchangeable is that the DynamicEmbeddedDocument has to be defined through the EmbeddedDocumentField field type?
From what I’ve seen, the two are similar, but not entirely interchangeable. Each approach may have a slight advantage based on your needs. First of all, as you point out, the two approaches require differing definitions in the document, as shown below.
class ExampleDynamicEmbeddedDoc(DynamicEmbeddedDocument):
pass
class ExampleDoc(Document):
dict_approach = DictField()
dynamic_doc_approach = EmbeddedDocumentField(ExampleDynamicEmbeddedDoc, default = ExampleDynamicEmbeddedDoc())
Note: The default is not required, but the dynamic_doc_approach field will need to be set to a ExampleDynamicEmbeddedDoc object in order to save. (i.e. trying to save after setting example_doc_instance.dynamic_doc_approach = {} would throw an exception). Also, you could use the GenericEmbeddedDocumentField if you don’t want to tie the field to a specific type of EmbeddedDocument, but the field would still need to be point to an object subclassed from EmbeddedDocument in order to save.
Once set up, the two are functionally similar in that you can save data to them as needed and without restrictions:
e = ExampleDoc()
e.dict_approach["test"] = 10
e.dynamic_doc_approach.test = 10
However, the one main difference that I’ve seen is that you can query against any values added to a DictField, whereas you cannot with a DynamicEmbeddedDoc.
ExampleDoc.objects(dict_approach__test = 10) # Returns a QuerySet containing our entry.
ExampleDoc.objects(dynamic_doc_approach__test = 10) # Throws an exception.
That being said, using an EmbeddedDocument has the advantage of validating fields which you know will be present in the document. (We simply would need to add them to the ExampleDynamicEmbeddedDoc definition). Because of this, I think it is best to use a DynamicEmbeddedDocument when you have a good idea of a schema for the field and only anticipate adding fields minimally (which you will not need to query against). However, if you are not concerned about validation or anticipate adding a lot of fields which you’ll query against, go with a DictField.
I am currently using Django forms with the Google App Engine and I have a model which is as follows:
class Menu(db.Model):
name = db.StringProperty(required=True)
is_special = db.BooleanProperty()
menu_items = db.ListProperty(MenuItem)
I have a MenuForm which is the following:
class MenuForm(djangoforms.ModelForm):
class Meta:
model = Menu
exclude = ['added_by','menu_items']
When I run this I get the following error:
Exception Type: ValueError
Exception Value: Item type MenuItem is not acceptable
I want to crate the form and have it omit the menu_items property as for one I don't think there is an in built control for the multiple choice, like a group of check boxes. Either way I cannot understand with this property in the exclude items why it is throwing this error.
TIA
Andrew
Your problem comes well before the "create a form" task begins: ListProperty does not allow a list of model entities (although I can't find this clearly documented in the app engine docs, I'm still looking in the docs for a good, clear, unambiguous statement about that). Try changing it into (say) a list of strings, and you'll see everything works (I believe a dropdown is what you get if you don't exclude such a property).
Edit: found the spot in the docs where the issue is mentioned, although it's quaintly phrased -- quoting with added emphasis:
The list can contain values of any of
the value types supported by the
datastore.
...point is, you can have in the list objects of any of the value types... not reference ones, i.e., entities that are instances of some model.
Could you use a list of key strings, instead...?