I fear I may be overlooking something very obvious, but I'd be grateful for any suggestions. I have a plain text file called 'settings' in a Ploneformgen form folder in Plone. The code below successfully alters the text in this file when I put it in a Python script called when the form is viewed using an override in one of the form's fields (e.g. Default Expression in a string field).
obj = context['settings']
obj.setText('Some text:2;More text:2')
obj.reindexObject()
My problem is that I would like to be able to modify the text in 'settings' using either a Custom Script Adapter or a script called using the After Validation Script override of the form. Neither of these work (and overrides in individual fields for validating the field don't seem to allow this either).
Is there some reason why setText() works in some places and not in others (the line obj = context['settings'] doesn't appear to be a problem)? What am I missing?
As far as I can see this isn't a problem of permissions, and I'm a bit baffled that code that works if called when the form is viewed doesn't work if called when the form has been submitted.
I can create a new text file and add text to it using scripts called in these ways no problem: it seems to be a specific problem with calling setText() on an existing file.
The solution is to set the mimetype explicitly when calling setText():
obj.setText("Some text", mimetype='text/plain')
or
obj.setText("Some text", mimetype='text/html')
as appropriate. I don't know why this works, but it does.
Related
I am trying to to implement a button in LuCI which, when clicked , runs a shell script in the backend. This is the model code for this:
field_var_36 = section_var_7:option(Button,"buttonkk36",translate("ButtonKK"))
field_var_36.inputstyle = "apply"
field_var_36.rmempty = true
function field_var_36.write(self, section)
luci.sys.call('echo "ABCDEFG123" >/dev/null')
end
Though this is working it has some unwanted side-effects. All the unsaved modifications in the page are getting saved and I get a "n unsaved changes" notifications at the top. My guess is the the button if of type "submit" and all the fields inside the html "form" are getting "sumbitted". I dont want this to happen. The button needs to be standalone. Can this be done?
One other option I tried was using a template with button implemented in html. But I dont know how to connect this to the backend script. Is there a javascript API function in LuCI which takes the script as argument?
Thanks in advance for any help.
I did that using a view template.
You must set up an "entry(...)" in an "index()" function in the "controller/" directory.
The entry associates a path (last part of the LuCI URL's) with either a template view, cbi or LUA function, which is just what you want.
Pay attention that when you change by hand a controller file on the target openwrt device, you must delete /tmp/luci-indexcache so that the LuCI dispatcher does not use the older version.
Then in the template you can use "luci.dispatcher.build_url()" to create the URL that will make the controller call the function, and you put this as the target URL for your button (through either or or onClick="document.location=..."> and so on)
Plone/Zope's z3cforms inherit from BrowserPage, and therefore should be able to be rendered without the use of an additional View and View Class. When I try to do this, the form renders fine, but none of the form's fields appear. I am trying to solve why this occurs. Keep in mind this example is using collective.z3cform.wizard, which essentially provides two classes, a Wizard and a Step. A Wizard is a Form (capital F) that mostly provides the machinery to glue the Steps together and maintain state with sessions, and a Step is just a Form.
To me, it feels like either the macro is incorrect, the context is wrong, or there needs to be some wrapping/unwrapping of the form. Basically, I feel like there's some one magic line of code or piece of information I'm missing, which is often the case with Plone.
When the form is wired up to use a separate view (which is redundant), the form renders fine with all the fields showing.
Since I understand this is complex, I've built an example-only standalone package on GitHub that showcases the problem. If you install this package into a stock Plone site with buildout, you will get three views:
http://localhost:8080/Plone/working
http://localhost:8080/Plone/almost
http://localhost:8080/Plone/broken
The working view requires a separate view and a whole-template-wrapping TAL tag, which is both kludge and redundant...but it works and renders the form with all of its fields.
The broken view is wired up how it should be, with the form instance representing the view itself, with the template defined in the Wizard class.
The almost view is identical to the broken view, except that the template is associated with the Wizard's Step rather than the Wizard itself. This results in a broken render, but the form renders with all of its fields.
I hope someone can help me trace down why exactly it is that the broken view renders the form, complete with buttons, but none of the form's fields.
Thank you in advance.
Your broken view does not render the fields because it does not try to render the current step. The default wizard template has something like this in it:
<div tal:define="form nocall:view/currentStep"
tal:replace="structure form/render" />
which looks up the current step and renders it. But you've overridden that with your own template which just calls the ploneform-macros, which is a generic z3c.form thing that knows nothing about the existence of steps.
You should stick with the default wizard template instead of overriding it, or if you need to customize it you should copy the default wizard.pt from collective.z3cform.wizard as a starting point.
Meanwhile, your 'almost' view is indeed almost working. The problem here is that the wizard's default template renders the step's template in the middle...but your step's template is set up to produce a full html page (because it uses the master macro from main_template). If you need to customize this template, I would again recommend starting by copying the default step template from c.z.wizard (wizard-step.pt)
I have my views setup to pre-compile, and therefore, at runtime if I were to try and read the view file (e.g. "~\Views\User\Report.cshtml") I'd get the following dummy-text, as opposed to the contents of my view:
This is a marker file generated by the precompilation tool, and should not be deleted!
Problem is, I'd like to re-use the cshtml view, and rerender it another way at runtime, but I cannot due to the above restriction.
The scenario:
An admin can see a list of users in a /User/Report route. It outputs some HTML that has a list of all users, and their information in an HTML table. These admins frequently want to download this html file (styles and all) to email it as an attachment to someone else. They could, of course, go to File->Save in their browser, but I wanted to simplify that action by adding a link to the page "Download this report as HTML" that would simply return the same page's content, as a forced-downloaded HTML file (2012-07-11_UserReport.html).
So, what I tried to do was re-render the view by running the Report.cshtml file's contents through ASP.NET's File() method, like this:
var html = System.IO.File.ReadAllText(Server.MapPath(#"~\Views\User\Report.cshtml"));
var bytes = System.Text.Encoding.UTF8.GetBytes(html);
return File(bytes,"text/html",string.Format("{0}_UserReport.html",DateTime.Now.ToString("yyyy-MM-dd")));
But, like I mentioned earlier, the file comes back as the dummy-text, not the view, since I'm pre-compiling the views.
I understand that to get around the pre-compilition, I could simply copy the Report.cshtml file, and rename it to Report.uncompiled (adding it to the csproj as of course) and read the contents of it, that's an ok solution, but not good enough.
What I would really like to know is: Is there a way I can get at that pre-compiled content? I looked in the Assembly's embedded resources, and they are not there. Any ideas/suggestions?
Updated with current solution
So after searching around some more, and trying to use WebClient/WebRequest to just make a request to the route's URL and send the response back down to the user to download while at the same time trying to pass the user's .ASPXAUTH cookie (that made WebClient/WebRequest time out for some reason? I even tried to create a new ticket, same result) I ended up going with what I didn't want to do: duplicate the view file, and rename it so it's not precompiled.
The view file (Report.uncompiled) had to be modified a bit as it was, and then I ran it through RazorEngine's Razor.Parse method and got what I needed, but it just felt hackey. Would still like a way to access the view file (Report.cshtml) even after it's compiled.
var templateHtml = Razor.Parse(System.IO.File.ReadAllText(Server.MapPath(#"~\Views\User\Report.uncompiled")),model);
var bytes = System.Text.Encoding.UTF8.GetBytes(templateHtml);
return File(bytes, "text/html", string.Format("{0}_UserReport.html", DateTime.Now.ToString("yyyy-MM-dd")));
Would the WebClient class work?
using System.Net;
using (WebClient client = new WebClient ())
{
client.DownloadFile("http://yourwebsite.com/test.html", #"C:\directory.html");
// If you just want access to the html, see below
string html = client.DownloadString("http://yourwebsite.com/test.html");
}
Just have this fire whenever your user clicks a button and then it will save the current content of the page wherever? You could probably also have a directory selector and feed whatever they select into that second parameter.
It essentially does the same thing as the browser save as, if that's what you want.
I have a web application with a form that has disabled fields in it. It allows a "Save As" function which basically means the settings can be copied into a new configuration (without being modified) and in the new configuration they can be changed to something else. The problem I am running into with this is that since the fields are disabled, they are not getting posted through and do not appear in the context object on the server side.
When I removed the logic to disable the fields, that part works fine. So the remaining problem is, how to "disable" the fields (not allow any change of the data in any of the entry fields) without really "disabling" them (so that the data gets posted through when saving)?
I was originally looking for a way to do this in CSS but not sure if it exists. The best solution is of course, the simplest one. Thanks in advance!
(Note: by 'disabled' I mean "The textboxes display but none of the text inside of them can be modified at all". It does not matter to me whether the cursor appears when you click inside it, though if I had a preference it would be no cursor...)
http://www.w3schools.com/TAGS/att_input_readonly.asp
readonly attribute is what you want.
i would suggest that instead of using the non-updateable field values from the page's inputs, you retrieve the original object from the DB and copy them from there. It's pretty trivial using something like Firebug to modify the contents of the page whose form will be posted back to modify the values, even if they are marked as readonly. Since you really want the values from the original, I would simply reget the object and copy them. Then you don't need to worry about whether the original (and non-updateable) properties get posted back at all.
I am currently having troubles figuring out how to handle a filepath to be (dynamicly) passed out to a HyperLink control's NavigateUrl property.
Let's say that I'm trying to refer to a file named jäynä.txt at the root of C:.
Passing "file:///C:/jäynä.txt" result to a link to file:///C:/jäynä.txt, as does HttpUtility.UrlPathEncode("file:///C:/jäynä.txt").
Replacing the ä**s with **%E4, which gives the string "file:///C:/j%E4yn%E4.txt", does give a working link to file:///C:/jäynä.txt, but I have not been able to find a way to make the replacement without defining it myself. With Replace("ä", "%E4"), for example.
Is there a way to automaticly handle the filepath string so that the HyperLink would display it correctly, without manualy listing what characters to replace in the string?
Additional Note:
There may be a way to work around this by spesifying the character encoding in which the page is rendered, because debugging shows that the HyperLink at least saves the string "file:///C:/jäynä.txt" unchanged, but somehow mangles it around the time of rendering.
However, this seems only be the case in rendering of the NavigateUrl because other components as well as HyperLink's Text-property are all quite capable of rendering the character ä unchanged.
The NavigateUrl property of a Hyperlink will encode unicode chars in the url.
Instead you can set the href attribute property of the Hyperlink like this:
hyperlink1.Attribute("href") = "file:///C:/jäynä.txt"
This is due to how the browser starts to interpret the path, typically individuals will avoid using characters such as that in the urls of pages.
In your case, I believe you have struck upon the best case scenario, as I am not aware of any way to change the behavior of HttpUtility and/or the NavigateUrl property. At least not without creating a custom control for it.
Don't use HyperLink control. Instead use HtmlAnchor control. It will solve your problem. I don't know why Microsoft designed like this.
Thank you!
The post using the 'attributes' solved my problem. In my case it was
HyperLink6.Attributes["href"] = "http://høgstedt.danquah.dk/";
The problem of using special danish characters in a url seem to have been troubling a lot of programmers - a search provides several very complicated approaches. This one is SIMPLE and it SIMPLY WORKS.
So once again, thank you