Get url in body_html odoo 9 - odoo

Is it possible get web page url in xml template?
<field name="body_html">
<![CDATA[
<p>Get url here</p>
]]>
</field>
Note: ${object.id}
return id eg. 10

In my opinion, QWeb has some fallbacks when it comes to doing what would otherwise be a simple thing in Python, such as accessing env to browse, search, or get other data like dbname or the company parameters like base_url.
What I've done in the past is just create a helper to have Python do the dirty work for you so that you can keep QWeb simple.
your_module/helpers/mixins.py
class CanGenerateUrl:
def generate_url(self):
"""
Build the URL to the record's form view.
- Base URL + Database Name + Record ID + Model Name
:param self: any Odoo record browse object (with access to env, _cr, and _model)
:return: string with url
"""
self.ensure_one()
base_url = self.env['ir.config_parameter'].get_param('web.base.url')
if base_url and base_url[-1:] != '/':
base_url += '/'
db = self._cr.dbname
return "{}web?db={}#id={}&view_type=form&model={}".format(base_url, db, self.id, self._model)
your_module/models/model.py
from openerp.addons.your_module.helpers.mixins import CanGenerateUrl
class YourModel(models.Model, CanGenerateUrl):
your_module/views/report.xml
<p><a href="${object.generate_url()}">${object.name or 'None'}<a/></p>
Reports Documentation
QWeb Documentation

Related

How to update a value from a field without refreshing the page Odoo

I'm creating a new sector on the settings page of my module, where I have a value and an update icon, which aims to update the field value when I click on the icon.
But when I call the function to execute the function, the page is reloaded and I never get the value, but the value is printed in the terminal with a logger, does anyone have any suggestions?
My XML code:
<button type="object" name="refresh_credits" class="btn-link" icon="fa-refresh"/>
<span class="btn-link">Credits</span>
<field name="new_credits"/>
My python code inside a class:
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
new_credits = fields.Integer()
def refresh_credits(self):
data_details_credits = self.env['show.credits'].content_credits_info()
_logger.info(self.env['show.credits'].content_credits_info()[4])
self.new_credits = data_details_credits[4]
You have to override set_values and get_values method to update the values in settings. We cannot directly update the values in general settings.
Below is the example:
def set_values(self):
super(ResConfigSettings, self).set_values()
self.env['ir.config_parameter'].sudo().set_param('MODULE_NAME.new_credits',
self.new_credits)
#api.model
def get_values(self):
res = super(ResConfigSettings, self).get_values()
config = self.env['ir.config_parameter'].sudo()
config_key = config.get_param('MODULE_NAME.new_credits')
if config_zoom_key:
res.update(
field_name=config_key
)
return res
And also for better understanding, watch this video:
Add fields general settings

If-else and for loops not working in HTML for new XBlock in OpenEdX

I've created a new XBLock and trying to pass data from python file to HTML file, but the standard template syntax is throwing error, HTML file code below
<p>EdlyCarouselXBlock: count is now
<span class='count'>{self.count}</span> (click me to increment).
{{ self.count }}
{% if self.count%}
<p>Simple If</p>
{%endif%}
</p>
<p id="decrement">(click me to Decrement).</p>
</div>
It is supporting a single bracket to access values {self.name}, for loops & if-else it throws an error. Tried using python 3.6.5 & 3.8.0, the same issue on both versions, any help would be appreciated, same issue in the lms/cms as well.
Solve the issue, posting the solution for future references.
Default xblock is created without using Django templating so we need to configure it manually.
Following default student_view function is added
def student_view(self, context=None):
"""
The primary view of the SampleXBlock, shown to students
when viewing courses.
"""
html = self.resource_string("static/html/sample.html")
frag = Fragment(html.format(self=self))
frag.add_css(self.resource_string("static/css/sample.css"))
frag.add_javascript(self.resource_string("static/js/src/sample.js"))
frag.initialize_js('SampleXBlock')
return frag
so in order to involve Django template rendering make the following changes.
include template and context
from django.template import Context, Template
# Add this method in your xblock class
def render_template(self, template_path, context={}):
template_str = self.resource_string(template_path)
template = Template(template_str)
return template.render(Context(context))
def student_view(self, context=None):
"""
The primary view of the SampleXBlock, shown to students
when viewing courses.
"""
frag = Fragment()
html = self.render_template("static/html/sample.html", {'count': self.count})
frag.add_content(html)
frag.add_css(self.resource_string("static/css/sample.css"))
frag.add_javascript(self.resource_string("static/js/src/sample.js"))
frag.initialize_js('SampleXBlock')
return frag

Get a database value in QWeb PDF report (Odoo 10)

I would like to retrieve a config parameter from database in a custom QWeb Report.
What shall I do?
Specifically, I want to get the equivalent (in the model):
self.env['ir.config_parameter'].get_param('my_param', '')
Could someone highlight where to start?
As additional information, the report I am trying to use inherits report.minimal_layout:
<?xml version="1.0"?>
<odoo>
<data>
<template id="report_saleorder_css" inherit_id="report.minimal_layout">
<xpath expr="html/head/*[position() = last()]" position="after">
<style>
body {
color: <t t-esc="color"/>;
}
</style>
</xpath>
</template>
</data>
</odoo>
And this is the custom render function I have tried:
class CustomReport(models.AbstractModel):
_name = 'report.mymodule.report_saleorder_css'
#api.model
def render_html(self, data=None):
report_obj = self.env['report']
report = report_obj._get_report_from_name('mymodule.report_saleorder_css')
docargs = {
'doc_ids': self._ids,
'doc_model': report.model,
'docs': self,
'color': 'red'
}
return report_obj.render('mymodule.report_saleorder_css', docargs)
without success
In simple word you want to retrieve a config parameter whenever you print qweb report.
we can not directly use self.env in qweb report, but we can call a function which do that operation and return config parameter value. To do that first create python function in your model.
#api.model
def get_system_para(self):
para_value = self.env['ir.config_parameter'].get_param('web.base.url','')
return para_value
Now call this function in your qweb report
<span t-esc="docs.get_system_para()"/>
You have to retrieve the value beforehand and pass it to your template for usage.
You can do this by defining your own parser for your report, check the documentation.
See under Custom Reports on how you can create your own parser (Python class) and how you can use the docargs. Basically within the render_html method you search for your value, insert it on docargs and then pass it on the render method. Then you can use it from your template like:
<t t-esc="my_param" />

Using Scrapy to scrape data after form submit

I'm trying to scrape content from listing detail page that can only be viewed by clicking the 'view' button which triggers a form submit . I am new to both Python and Scrapy
Example markup
<li><h3>Abc Widgets</h3>
<form action="/viewlisting?id=123" method="post">
<input type="image" src="/images/view.png" value="submit" >
</form>
</li>
My solution in Scrapy is to extract form actions then use Request to return the page with a callback to parse it for for the desired content. However I have hit a few issues
I'm getting the following error "request url must be str or unicode"
secondly when I hardcode a URL to overcome the above issue it seems my parsing function is returning what looks like a list
Here is my code - with reactions of the real URLs
from scrapy.spiders import Spider
from scrapy.selector import Selector
from scrapy.http import Request
from wfi2.items import Wfi2Item
class ProfileSpider(Spider):
name = "profiles"
allowed_domains = ["wfi.com.au"]
start_urls = ["http://example.com/wps/wcm/connect/internet/wfi/Contact+Us/Find+Your+Local+Office/findYourLocalOffice.jsp?state=WA",
"http://example.com/wps/wcm/connect/internet/wfi/Contact+Us/Find+Your+Local+Office/findYourLocalOffice.jsp?state=VIC",
"http://example.com/wps/wcm/connect/internet/wfi/Contact+Us/Find+Your+Local+Office/findYourLocalOffice.jsp?state=QLD",
"http://example.com/wps/wcm/connect/internet/wfi/Contact+Us/Find+Your+Local+Office/findYourLocalOffice.jsp?state=NSW",
"http://example.com/wps/wcm/connect/internet/wfi/Contact+Us/Find+Your+Local+Office/findYourLocalOffice.jsp?state=TAS"
"http://example.com/wps/wcm/connect/internet/wfi/Contact+Us/Find+Your+Local+Office/findYourLocalOffice.jsp?state=NT"
]
def parse(self, response):
hxs = Selector(response)
forms = hxs.xpath('//*[#id="area-managers"]//*/form')
for form in forms:
action = form.xpath('#action').extract()
print "ACTION: ", action
#request = Request(url=action,callback=self.parse_profile)
request = Request(url=action,callback=self.parse_profile)
yield request
def parse_profile(self, response):
hxs = Selector(response)
profile = hxs.xpath('//*[#class="contentContainer"]/*/text()')
print "PROFILE", profile
I'm getting the following error "request url must be str or unicode"
Please have a look at the scrapy documentation for extract(). It says : "Serialize and return the matched nodes as a list of unicode strings" (bold added by me).
The first element of the list is probably what you want. So you could do something like:
request = Request(url=response.urljoin(action[0]), callback=self.parse_profile)
secondly when I hardcode a URL to overcome the above issue it seems my
parsing function is returning what looks like a list
According to the documentation of xpath it's a SelectorList. Add extract() to the xpath and you'll get a list with the text tokens. Eventually you want to clean up and join the elements that list before further processing.

Django - URL template tag breaks with subdomains

I use a custom middleware for mapping subdomains to applications' urls.py by assigning the relevant urls.py to the request.urlconf variable.
This works fine, with the exception of the {% url %} template tag.
I'm getting a NoReverseMatch and can't figure out why.
The debug page shows that the reverse function receives a value in the view_name parameter, so it should work.
This happens to every {% url %} tag in the template.
If I switch to folder-like urls (eg myproject.com/sub, instead of sub.myproject.com), the tags work fine.
Any ideas on why this happens and how can this be fixed are much appreciated.
Well, after not finding what I needed, I came to the following solution.
I discarded the request.urlconf mapping and went for rewriting request.path_info.
I'm posting my solution here, in case someone runs into this problem.
First step, add the following middleware to your project:
class SubdomainMiddleware:
"""Subdomain for Django"""
def process_request(self, request):
domain_parts = request.get_host().lower().replace('www.', '').split('.example.com', 1)
if len(domain_parts) > 1 and domain_parts[0]:
subdomain = domain_parts[0]
else:
subdomain = None
if subdomain:
if request.path_info[-1] != '/':
request.path_info += '/'
request.path_info = '/%s%s' % (subdomain, request.path_info)
Next, add the following code that overrides the reverse function:
from django.conf import settings
from django.core import urlresolvers
_reverse = urlresolvers.reverse
def reverse(*args, **kwargs):
# In case reversing a full url
if args[0].startswith('http'):
return args[0]
# In case reversing a url name
if '/' not in args[0]:
url = _reverse(*args, **kwargs)
else:
# In case reversing a url path
url = args[0]
parts = url.strip('/').split('/', 1)
subdomain = parts[0]
path = parts[1] if len(parts) > 1 else ''
protocol = 'http://' if settings.DEBUG else 'https://'
return '%s%s%s/%s' % (protocol, subdomain, '.example.com', path)
urlresolvers.reverse = reverse
I placed it in the same file the custom middleware sits.
That's it!
As far as I know and tested, everything works: reversing, redirecting, template {% url %} tags etc.
Note:
I made three assumptions in this code:
The domain name is example.com. Change it as you need, place it in settings.py, whatever suits you.
The subdomain maps to a subfolder. E.g. sub.example.com will be converted to example.com/sub.
My site uses SSL anywhere. So I simply check for settings.DEBUG value in the custom reverse function to see if it should use http or https.
Hope it helps.