Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7018 Articles
article-image-building-news-aggregating-site-joomla
Packt
26 May 2010
3 min read
Save for later

Building a News Aggregating Site in Joomla!

Packt
26 May 2010
3 min read
(For more resources on Joomla!, see here.) The completed news aggregation site will look similar to the example shown in the following screenshot: Build Weird Hap'nins Vaughan Pyre is a very ambitious webpreneur. What he really hopes for is a website that is completely self-maintaining, and on which he can place some Google AdSense blocks. Clicks from the visitors to his site will ensure that he makes lots of money. For this, he needs a site where the content updates regularly with fresh content so that visitors will keep coming back to click on some more Google ads. Vaughan's ultimate objective is to create several of these websites. Template The template chosen is Midnight by BuyHTTP, which is a template that fits the theme of this unique website. Extensions This is, surprisingly, a very simple site to build, and much of the requirements can be actually be achieved by using the native News Feeds component. However, the News Feeds component will only list the title links to the external feed items, whereas what Vaughan wants is that the feeds are pulled into the site as articles. Therefore, we will be using an automatic article generator component. There are several of such components on the Joomla! extensions site, but almost all of them are commercial. Vaughan is a skinflint and will not pay to buy any script, so what we are looking for is free component. That is why we have chosen the following: 4RSS—aggregates RSS feeds and creates articles from them JCron Scheduler—used for cron jobs management and scheduling to simulate cron jobs through the Joomla! frontend interface at preset intervals Indeed, were it not for the fact that Vaughan needs the content to automatically be updated, we needn't use any extension other than the 4RSS component. Other extensions The core module that will be used for this site is: Main Menu module—creates the primary navigation functionality for the site pages Sections and categories New sections and categories will need to be created so that incoming article feeds will be correctly routed according to their description. A new section will be created that we will call Feed. Under this section, we shall have three categories—Bad News, More Bad News, and Weird News. Create a new section We intend to create a section that will be named Feed. In order to do this, perform the following steps: Navigate to the Section Manager from the Control Panel, and then click on the New icon at the top right-hand side, in order to create a new section. On the next page, add the name of the section, and then save your changes. Create new categories To create a new category, perform the following steps: Navigate to the Category Manager page from the Control Panel. On the following page, create a new category in the same way as we created the new section. However, remember to set the Section to Feed.
Read more
  • 0
  • 0
  • 2981

article-image-creating-installing-and-tweaking-your-theme-using-plone-3
Packt
26 May 2010
12 min read
Save for later

Creating, Installing and Tweaking your theme using Plone 3

Packt
26 May 2010
12 min read
(For more resources on Plone here.) We will first inspect a few structural changes and install them, and then finally examine the various components and skin layer items that have been changed, one at a time. Where restarting Zope or rerunning your buildout would be required, this will be noted. About the theme This theme and its design are available for personal and professional use to anyone, and can be freely modified. You can (and should) download the files from https://svn.plone.org/svn/collective/plonetheme.guria/trunk using the following command: svn co https://svn.plone.org/svn/collective/plonetheme.guria/trunk plonetheme.guria Note the space between the words trunk and plonetheme.guria. This theme is intended for installation on Plone 3 web sites. The finished theme should look like the following, but we have work to do to make this happen: This theme was created by me, for use by a charity group in India, called Guria (http://www.guriaindia.org), dedicated to ending human trafficking and prostitution. The finished site is currently in development, and is generously hosted free of charge by the talented folks at Six Feet Up (sixfeetup.com). Additionally, most of the code and lessons learned come courtesy of similar themes created by the staff at ONE/Northwest in Seattle, Washington. The design for this theme was created with the assumption that most of the tasks would need to be present in this theme. In fact, the only task not covered here is the creation of a new viewlet manager. Creation of viewlet managers is discussed at http://plone.org/documentation/how-to/adding-portlet-managers and http://plone.org/documentation/manual/theme-reference/elements/viewletmanager/override. Creating a theme product I created a theme product named plonetheme.guria, using the command line syntax paster create –t plone3_theme, while we were located in the src/ directory of our buildout, as seen next: [bash: /opt/mybuildout/src] paster create -t plone3_theme plonetheme.guriaSelected and implied templates: ZopeSkel#basic_namespace A project with a namespace package ZopeSkel#plone A Plone project ZopeSkel#plone3_theme A Theme for Plone 3.0Variables: egg: plonetheme.guria package: plonethemeguria project: plonetheme.guriaEnter namespace_package (Namespace package (like plonetheme)) ['plonetheme']:Enter package (The package contained namespace package (like example)) ['example']: guriaEnter skinname (The skin selection to be added to 'portal_skins' (like 'My Theme')) ['']: Guria Theme for the Plone Theming BookEnter skinbase (Name of the skin selection from which the new one will be copied) ['Plone Default']:Enter empty_styles (Override default public stylesheets with empty ones?) [True]: FalseEnter include_doc (Include in-line documentation in generated code?) [False]:Enter zope2product (Are you creating a Zope 2 Product?) [True]:Enter version (Version) ['0.1']:Enter description (One-line description of the package) ['An installable theme for Plone 3.0']:Enter long_description (Multi-line description (in reST)) ['']:Enter author (Author name) ['Plone Collective']: Veda WilliamsEnter author_email (Author email) ['product-developers@lists. plone.org']: email@email.comEnter keywords (Space-separated keywords/tags) ['web zope plone theme']:Enter url (URL of homepage) ['http://svn.plone.org/svn/collective/']:Enter license_name (License name) ['GPL']:Enter zip_safe (True/False: if the package can be distributed as a .zip file) [False]:Creating template basic_namespaceCreating directory ./plonetheme.guria[snip] You may wish to generate a new Plone theme product yourself, so that you can compare and contrast the differences between the Guria theme and a vanilla Plone theme. Notice that the full name of the theme is plonetheme.guria, and where an item shows as blank, it defaults to the example value in that step. In other words, the namespace package defaults to plonetheme, because there was no reason to change it. The skinname is set to a single lowercase word out of stylistic preference. It's important to also note that you should not use hyphens or spaces in your theme names, as they will not be recognized by your buildout. We've chosen not to override Plone's default stylesheets, and instead, we want to build on top of Plone's default (and excellent!) stylesheets. I prefer this method mostly because the layout needed for Plone's Contents view and other complex structural pieces are already taken care of by Plone's base stylesheets. It's easier than trying to rebuild those from scratch every time, but this is merely a personal preference. Following the creation of the theme, we register the theme product in our buildout.cfg, using the following syntax [buildout] ...develop = src/plonetheme.guria...[instance]eggs = plonetheme.guria...zcml = plonetheme.guria... If we were using the eggtractor egg, there would be no need to add these lines of code to our buildout.cfg; all we would need to do is rebuild our buildout and it would automatically recognize the new egg. eggtractor can be found at http://pypi.python.org/pypi/buildout.eggtractor, and is documented thoroughly. Assuming we are not using eggtractor, we must rebuild our buildout, as we have altered ZCML code and added a new egg: [bash: /opt/mybuildout/src/] ./bin/buildout This would be a good time to check your vanilla theme product into Subversion, so that you can track back to the original version, if needed. However, since this is an existing theme, there is no need to do so. For the purposes of following along, it might be best if you do not yet install the theme. We want to make some changes first. However, we will point out some caveats along the way, in case you installed the theme prematurely. Altering the theme product's structure Several modifications have been made to the theme product's structure to shorten folder names and change the default behavior. Again, this is mostly a personal preference. Let's take a look at these changes and how they were achieved. Renaming the theme In our theme product, you will see a file named profiles.zcml, located at mybuildout/src/plonetheme.guria/plonetheme/guria/profiles.zcml. The code looks like this: <configure i18n_domain="plonetheme.guria"> <genericsetup:registerProfile name="default" title="Guria Theme for the Plone Theming Book" directory="profiles/default" description='Extension profile for the "Guria Theme for the Plone Theming Book" Plone theme.' provides="Products.GenericSetup.interfaces.EXTENSION" /></configure> If you named your theme in a way that was less descriptive, you could alter the title. Naming your theme product properly is important, because you may have different types of products used for a given web site—for example, a policy product for content that might be used in tandem with your theme product. This text is what you see in the portal_quickinstaller at http://localhost:8080/mysite/portal_quickinstaller/manage_installProductsForm, where mysite is the name of your Plone site. You can also see this name if you install your theme product via Site Setup Add-on Products|, found at http://localhost:8080/mysite/prefs_install_products_form. If you change your XML here, and your theme product is already installed, you'll need to start (or restart) your Zope instance, using: [bash: /opt/mybuildout] ./bin/instance fg Shortening folder names Next, we look at the folder structure of our theme product. The standard Plone 3 theme produces folders with names like plonetheme_guria_custom_images, plonetheme_guria_custom_templates, and plonetheme_guria_styles. While there is nothing wrong with keeping this structure, it can be cumbersome to type or tab through (especially when checking items into Subversion). However, you might want to keep the existing folder names to help you distinguish which items of base Plone you modified. This can make migrations easier. If you choose this route, you probably want to create additional folders for non-base-Plone items. I personally prefer the shorter folder names and don't worry too much about the migration issues. In the case of this theme product, I opted to make the folder names shorter. First, I altered the names of the folders in the skins/ folder to guria_images, guria_styles, and guria_templates. Then, in the theme, go to mybuildout/plonetheme.guria/plonetheme/guria/skins.zcml. The code in this file is altered to appear as follows: <configure i18n_domain="plonetheme.guria"> <!-- File System Directory Views registration --> <cmf:registerDirectory name="guria_images"/> <cmf:registerDirectory name="guria_templates"/> <cmf:registerDirectory name="guria_styles"/></configure> One more step is required here. In plonetheme.guria/plonetheme/guria/profiles/default/skins.xml, the code is changed to read as follows: <?xml version="1.0"?><object name="portal_skins" allow_any="False" cookie_persistence="False" default_skin=" Guria Theme for the Plone Theming Book "> <object name="guria_images" meta_type="Filesystem Directory View" directory="plonetheme.guria:skins/guria_images"/> <object name="guria_templates" meta_type="Filesystem Directory View" directory="plonetheme.guria:skins/guria_templates"/> <object name="guria_styles" meta_type="Filesystem Directory View" directory="plonetheme.guria:skins/guria_styles"/> <skin-path name=" Guria Theme for the Plone Theming Book " based- on="Plone Default"> <layer name="guria_images" insert-after="custom"/> <layer name="guria_templates" insert-after="guria_images"/> <layer name="guria_styles" insert-after="guria_templates"/> </skin-path></object> Basically, the steps are the following:   Rename the folders on the filesystem. Modify the skins.zcml file to change the name of the filesystem directory view (what you see in the portal_skins/properties area of the ZMI). Modify the skins.xml file in the profiles/default folder to match. This alters the basic profile of your theme product. If you wanted to add additional folders and filesystem directory views here (a scripts/ folder, for example), you'd just add code by following the conventions given to you in these files and then create additional folders. Making changes to the ZCML file means that you would need to do a restart of your Zope instance. If you installed your theme product before making the changes to the skin layer names, you might want to inspect the skin layers at http://localhost:8080/mysite/ portal_skins/manage_propertiesForm, to make sure that the correct skin layers are listed. You might even need to reimport the "skins tool" step via portal_setup at http://localhost:8080/mysite/portal_setup/manage_importSteps. Make sure you choose the correct profile first by choosing your theme product's name from the drop-down list at the top of the import page. The theme product's name is the same name as you find in your profiles.zcml file. Adjusting how stylesheets and images are used Next, we remove some of the default behavior given to us by the plone3_theme recipe. In a vanilla theme product, folders named images/ and stylesheets/ are inserted into the plonetheme.guria/plonetheme/guria/browser/ directory. Additionally, a file named main.css is included in the stylesheets/ directory. I chose not to place the theme's images or stylesheets in the browser/ directory, as this is generally unnecessary for most themes. Advanced programmers may wish to expose these items to the browser layer, but this is generally a personal choice and carries with it additional consequences. I deleted the folders mentioned above, as well as the i file. Then, I opened the file named configure.zcml, located at plonetheme.guria/plonetheme/guria/browser/, and removed all of the following boilerplate text: <!-- Viewlets registration --> <!-- Zope 3 browser resources --> <!-- Resource directory for images --> <browser:resourceDirectory name="plonetheme.guria.images" directory="images" layer=".interfaces.IThemeSpecific" /> <!-- Resource directory for stylesheets --> <browser:resourceDirectory name="plonetheme.guria.stylesheets" directory="stylesheets" layer=".interfaces.IThemeSpecific" /> I then removed the highlighted code below fromI then removed the highlighted code below from plonetheme.guria/plonetheme/guria/profiles/default/cssregistry.xml:: <stylesheet title="" id="++resource++plonetheme.guria.stylesheets/main.css" media="screen" rel="stylesheet" rendering="import" cacheable="True" compression="safe" cookable="True" enabled="1" expression=""/> And replaced it with the following: <stylesheet title="" id="guria.css" media="screen" rel="stylesheet" rendering="import" cacheable="True" compression="safe" cookable="True" enabled="1" expression=""/> This, in effect, tells our theme product that we will be using a stylesheet named guria.css (or more correctly, guria.css.dtml, as we'll see in a moment). This stylesheet does not yet exist, so we have to create it. I wanted the option of making use of the DTML behavior provided by Plone, so that I could use certain base properties provided to us via the base_properties.props file (also located in our skins/guria_styles/ folder). DTML essentially allows us to use property-sheet variables and apply changes on a more global scale. The easiest way to create this new stylesheet is to go to your mybuildout/buildout-cache/eggs/Plone[some version number]/Products/CMFPlone/skins/plone_styles/ploneCustom.css and copy the contents of that file into a new stylesheet (named guria.css.dtml) in your theme's guria_styles/ folder (located in the skins/ directory at mybuildout/plonetheme.guria/plonetheme/guria/skins/guria_styles). The important bits of code you want are as follows: /* <dtml-with base_properties> (do not remove this :) *//* <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either :) *//* DELETE THIS LINE AND PUT YOUR CUSTOM STUFF HERE */ /* </dtml-with> */ Again, we would need to restart our Zope at this point, as we have modified our ZCML. If we had already installed our theme product, we'd also have to import our cssregistry.xml file via portal_setup in the ZMI, to capture the new GenericSetup profile settings. However, we have not yet installed the product, so we do not need to worry about this.
Read more
  • 0
  • 0
  • 4702

article-image-use-macros-ibm-cognos-8-report-studio
Packt
25 May 2010
13 min read
Save for later

Use of macros in IBM Cognos 8 Report Studio

Packt
25 May 2010
13 min read
Cognos Report Studio is widely used for creating and managing business reports in medium to large companies. It is simple enough for any business analyst, power user, or developer to pick up and start developing basic reports. However, when it comes to developing more sophisticated, fully functional business reports for wider audiences, report authors will need guidance. In this article, by Abhishek Sanghani, author of IBM Cognos 8 Report Studio Cookbook, we will show you  that even though macros are often considered a Framework Modeler's tool, they can be used within Report Studio as well. These recipes will show you some very useful macros around security, string manipulation, and prompting. (Read more interesting articles on Compiere here.) Introduction This article will introduce you to an interesting and useful tool of Cognos BI, called 'macros'. They can be used in Framework Manager as well as Report Studio. The Cognos engine understands the presence of a macro as it is written within a pair of hashes (#). It executes the macros first and puts the result back into report specification like a literal string replacement. We can use this to alter data items, filters, and slicers at run time. You won't find the macro functions and their details within Report Studio environment (which is strange, as it fully supports them). Anyways, you can always open Framework Manager and check different macro functions and their syntaxes from there. Also, there is documentation available in Cognos' help and online materials. Working with Dimensional Model (in the"Swapping dimension" recipe). In this article, I will show you more examples and introduce you to more functions which you can later build upon to achieve sophisticated functionalities. We will be writing some SQL straight against the GO Data Warehouse data source. Also, we will use the "GO Data Warehouse (Query)" package for some recipes. Add data level security using CSVIdentityMap macro A report shows the employee names by region and country. We need to implement data security in this report such that a user can see the records only for the country he belongs to. There are already User Groups defined on the Cognos server (in the directory) and users are made members of appropriate groups. For this sample, I have added my user account to a user group called 'Spain'. Getting ready Open a new list report with GO Data Warehouse (Query) as the package. How to do it... Drag the appropriate columns (Region, Country, and Employee name) on to the report from Employee by Region query subject. Go to Query Explorer and drag a new detail filter. Define the filter as: [Country] in (#CSVIdentityNameList(',')#) Run the report to test it. You will notice that a user can see only the rows of the country/countries of which he is a member. How it works... Here we are using a macro function called CSVIdentityNameList. This function returns a list of groups and roles that the user belongs to, along with the user's account name. Hence, when I run the report, one of the values returned will be 'Spain' and I will see data for Spain. The function accepts a string parameter which is used as a separator in the result. Here we are passing a comma (,) as the separator. If a user belongs to multiple country groups, he will see data for all the countries listed in the result of a macro. There's more... This solution, conspicuously, has its limitations. None of the user accounts or roles should be same as a country name, because that will wrongly show data for a country the user doesnot belong to. For example, for a user called 'Paris', it will show data for the 'Paris' region. So, there need to be certain restrictions. However, you can build upon the knowledge of this macro function and use it in many practical business scenarios. Using prompt macro in native SQL In this recipe, we will write an SQL statement straight to be fired on the data source. We will use the Prompt macro to dynamically change the filter condition. We will write a report that shows list of employee by Region and Country. We will use the Prompt macro to ask the users to enter a country name. Then the SQL statement will search for the employee belonging to that country. Getting ready Create a new blank list report against 'GO Data Warehouse (Query)' package. How to do it... Go to the Query Explorer and drag an SQL object on the Query Subject that is linked to the list (Query1 in usual case). Select the SQL object and ensure that great_outdoor_warehouse is selected as the data source. Open the SQL property and add the following statement: select distinct "Branch_region_dimension"."REGION_EN" "Region" ,"Branch_region_dimension"."COUNTRY_EN" "Country" , "EMP_EMPLOYEE_DIM"."EMPLOYEE_NAME" "Employee_name"from "GOSALESDW"."GO_REGION_DIM" "Branch_region_dimension","GOSALESDW"."EMP_EMPLOYEE_DIM" "EMP_EMPLOYEE_DIM","GOSALESDW"."GO_BRANCH_DIM" "GO_BRANCH_DIM"where ("Branch_region_dimension"."COUNTRY_EN" in(#prompt('Region')#))and "Branch_region_dimension"."COUNTRY_CODE" = "GO_BRANCH_DIM"."COUNTRY_CODE" and "EMP_EMPLOYEE_DIM"."BRANCH_CODE" = "GO_BRANCH_DIM"."BRANCH_CODE" Hit the OK button. This will validate the query and will close the dialog box. You will see that three data items (Region, Country, and Employee_Name) are added to Query1. Now go to the report page. Drag these data items on the list and run the report to test it. How it works... Here we are using the macro in native SQL statement. Native SQL allows us to directly fire a query on the data source and use the result on the report. This is useful in certain scenarios where we don't need to define any Framework Model. If you examine the SQL statement, you will notice that it is a very simple one that joins three tables and returns appropriate columns. We have added a filter condition on country name which is supposed to dynamically change depending on the value entered by user. The macro function that we have used here is Prompt(). As the name suggests, it is used to generate a prompt and returns the parameter value back to be used in an SQL statement. Prompt() function takes five arguments. The first argument is the parameter name and it is mandatory. It allows us to link a prompt page object (value prompt, date prompt, and so on) to the prompt function. The rest of the four arguments are optional and we are not using them here. You will read about them in the next recipe. Please note that we also have an option of adding a detail filter in the query subject instead of using PROMPT() macro within query. However, sometimes you would want to filter a table before joining it with other tables. In that case, using PROMPT() macro within the query helps. There's more... Similar to the Prompt() function, there is a i macro function. This works in exactly the same way and allows users to enter multiple values for the parameter. Those values are returned as a comma-separated list. Making prompt optional The previous recipe showed you how to generate a prompt through a macro. In this recipe, we will see how to make it optional using other arguments of the function. We will generate two simple list reports, both based on a native SQL. These lists will show product details for selected product line. However, the product line prompt will be made optional using two different approaches. Getting ready Create a report with two simple list objects based on native SQL. For that, create the Query Subjects in the same way as we did in the previous recipe. Use the following query in the SQL objects: select distinct "SLS_PRODUCT_LINE_LOOKUP"."PRODUCT_LINE_EN" "Product_line" , "SLS_PRODUCT_LOOKUP"."PRODUCT_NAME" "Product_name" , "SLS_PRODUCT_COLOR_LOOKUP"."PRODUCT_COLOR_EN" "Product_color" , "SLS_PRODUCT_SIZE_LOOKUP"."PRODUCT_SIZE_EN" "Product_size"from "GOSALESDW"."SLS_PRODUCT_DIM" "SLS_PRODUCT_DIM","GOSALESDW"."SLS_PRODUCT_LINE_LOOKUP" "SLS_PRODUCT_LINE_LOOKUP","GOSALESDW"."SLS_PRODUCT_TYPE_LOOKUP" "SLS_PRODUCT_TYPE_LOOKUP", "GOSALESDW"."SLS_PRODUCT_LOOKUP" "SLS_PRODUCT_LOOKUP","GOSALESDW"."SLS_PRODUCT_COLOR_LOOKUP" "SLS_PRODUCT_COLOR_LOOKUP","GOSALESDW"."SLS_PRODUCT_SIZE_LOOKUP" "SLS_PRODUCT_SIZE_LOOKUP","GOSALESDW"."SLS_PRODUCT_BRAND_LOOKUP" "SLS_PRODUCT_BRAND_LOOKUP"where "SLS_PRODUCT_LOOKUP"."PRODUCT_LANGUAGE" = N'EN' and "SLS_PRODUCT_DIM"."PRODUCT_LINE_CODE" = "SLS_PRODUCT_LINE_LOOKUP"."PRODUCT_LINE_CODE" and "SLS_PRODUCT_DIM"."PRODUCT_NUMBER" = "SLS_PRODUCT_LOOKUP"."PRODUCT_NUMBER" and "SLS_PRODUCT_DIM"."PRODUCT_SIZE_CODE"= "SLS_PRODUCT_SIZE_LOOKUP"."PRODUCT_SIZE_CODE" and "SLS_PRODUCT_DIM"."PRODUCT_TYPE_CODE" = "SLS_PRODUCT_TYPE_LOOKUP"."PRODUCT_TYPE_CODE" and "SLS_PRODUCT_DIM"."PRODUCT_COLOR_CODE" = "SLS_PRODUCT_COLOR_LOOKUP"."PRODUCT_COLOR_CODE" and "SLS_PRODUCT_BRAND_LOOKUP"."PRODUCT_BRAND_CODE" = "SLS_PRODUCT_DIM"."PRODUCT_BRAND_CODE" This is a simple query that joins product related tables and retrieves required columns. How to do it... We have created two list reports based on two SQL query subjects. Both the SQL objects use the same query as mentioned above. Now, we will start with altering them. For that open Query Explorer. Rename first query subject as Optional_defaultValue and the second one as Pure_Optional. In the Optional_defaultValue SQL object, amend the query with following lines: and "SLS_PRODUCT_LINE_LOOKUP"."PRODUCT_LINE_EN" = #sq(prompt ('ProductLine','string','Golf Equipment'))# Similarly, amend the Pure_Optional SQL object query with the following line: #prompt ('Product Line','string','and 1=1', ' and "SLS_PRODUCT_LINE_LOOKUP"."PRODUCT_LINE_EN" = ')# Now run the report. You will be prompted to enter a product line. Don't enter any value and just hit OK button. Notice that the report runs (which means the prompt is optional). First, list object returns rows for 'Golf Equipment'. The second list is populated by all the products. How it works... Fundamentally, this report works the same as the one in the previous report. We are firing the SQL statements straight on the data source. The filter condition in the WHERE clause are using the PROMPT macro. Optional_defaultValue In this query, we are using the second and third arguments of Prompt() function. Second argument defines the data type of value which is 'String' in our case. The third argument defines default value of the prompt. When the user doesn't enter any value for the prompt, this default value is used. This is what makes the prompt optional. As we have defined 'Golf Equipment' as the default value, the first list object shows data for 'Golf Equipment' when prompt is left unfilled. Pure_Optional In this query, we are using fourth argument of Prompt() function. This argument is of string type. If the user provides any value for the prompt, the prompt value is concatenated to this string argument and the result is returned. In our case, the fourth argument is the left part of filtering condition that is, 'and . 'and "SLS_PRODUCT_LINE_LOOKUP"."PRODUCT_LINE_EN" ='. So, if the user enters the value as 'XYZ', the macro is replaced by the following filter: and "SLS_PRODUCT_LINE_LOOKUP"."PRODUCT_LINE_EN" = 'XYZ' Interestingly, if the user doesn't provide any prompt value, then the fourth argument is simply ignored. The macro is then replaced by the third argument which is in our case is 'and 1=1'. Hence, the second list returns all the rows when user doesn't provide any value for the prompt. This way it makes the PRODUCT_LINE_EN filter purely optional. There's more... Prompt macro accepts two more arguments (fifth and sixth). Please check the help documents or internet sources to find information and examples about them. Adding token using macro In this recipe, we will see how to dynamically change the field on which filter is being applied using macro. We will use prompt macro to generate one of the possible tokens and then use it in the query. Getting ready Create a list report based on native SQL similar to the previous recipe. We will use the same query that works on the product tables but filtering will be different. For that, define the SQL as following: select distinct "SLS_PRODUCT_LINE_LOOKUP"."PRODUCT_LINE_EN" "Product_line" , "SLS_PRODUCT_LOOKUP"."PRODUCT_NAME" "Product_name" , "SLS_PRODUCT_COLOR_LOOKUP"."PRODUCT_COLOR_EN" "Product_color" , "SLS_PRODUCT_SIZE_LOOKUP"."PRODUCT_SIZE_EN" "Product_size"from "GOSALESDW"."SLS_PRODUCT_DIM" "SLS_PRODUCT_DIM","GOSALESDW"."SLS_PRODUCT_LINE_LOOKUP" "SLS_PRODUCT_LINE_LOOKUP","GOSALESDW"."SLS_PRODUCT_TYPE_LOOKUP" "SLS_PRODUCT_TYPE_LOOKUP", "GOSALESDW"."SLS_PRODUCT_LOOKUP" "SLS_PRODUCT_LOOKUP","GOSALESDW"."SLS_PRODUCT_COLOR_LOOKUP" "SLS_PRODUCT_COLOR_LOOKUP","GOSALESDW"."SLS_PRODUCT_SIZE_LOOKUP" "SLS_PRODUCT_SIZE_LOOKUP","GOSALESDW"."SLS_PRODUCT_BRAND_LOOKUP" "SLS_PRODUCT_BRAND_LOOKUP"where "SLS_PRODUCT_LOOKUP"."PRODUCT_LANGUAGE" = N'EN' and "SLS_PRODUCT_DIM"."PRODUCT_LINE_CODE" = "SLS_PRODUCT_LINE_LOOKUP"."PRODUCT_LINE_CODE" and "SLS_PRODUCT_DIM"."PRODUCT_NUMBER" = "SLS_PRODUCT_LOOKUP"."PRODUCT_NUMBER" and "SLS_PRODUCT_DIM"."PRODUCT_SIZE_CODE"= "SLS_PRODUCT_SIZE_LOOKUP"."PRODUCT_SIZE_CODE" and "SLS_PRODUCT_DIM"."PRODUCT_TYPE_CODE" = "SLS_PRODUCT_TYPE_LOOKUP"."PRODUCT_TYPE_CODE" and "SLS_PRODUCT_DIM"."PRODUCT_COLOR_CODE" = "SLS_PRODUCT_COLOR_LOOKUP"."PRODUCT_COLOR_CODE" and "SLS_PRODUCT_BRAND_LOOKUP"."PRODUCT_BRAND_CODE" = "SLS_PRODUCT_DIM"."PRODUCT_BRAND_CODE"and#prompt ('Field','token','"SLS_PRODUCT_LINE_LOOKUP"."PRODUCT_LINE_EN"')# like #prompt ('Value','string')# This is the same basic query that joins the product related tables and fetches required columns. The last statement in WHERE clause uses two prompt macros. We will talk about it in detail. How to do it... We have already created a list report based on an SQL query subject as mentioned previously. Drag the columns from the query subject on the list over the report page. Now create a new prompt page. Add a value prompt on the prompt page. Define two static choices for this. Display value Use value Filter on product line "SLS_PRODUCT_LINE_LOOKUP"."PRODUCT_LINE_EN" Filter on product name "SLS_PRODUCT_LOOKUP"."PRODUCT_NAME Set the parameter for this prompt to 'Field'. This will come pre-populated as existing parameter, as it is defined in the query subject. Choose the UI as radio button group and Filter on Product Line as default selection. Now add a text box prompt on to the prompt page. Set its parameter to Value which comes as a choice in an existing parameter (as it is already defined in the query). Run the report to test it. You will see an option to filter on product line or product name. The value you provide in the text box prompt will be used to filter either of the fields depending on the choice selected in radio buttons.
Read more
  • 0
  • 0
  • 9025

article-image-scaling-your-application-across-nodes-spring-pythons-remoting
Packt
24 May 2010
5 min read
Save for later

Scaling your Application Across Nodes with Spring Python's Remoting

Packt
24 May 2010
5 min read
(For more resources on Spring, see here.) With the explosion of the Internet into e-commerce in recent years, companies are under pressure to support lots of simultaneous customers. With users wanting richer interfaces that perform more business functions, this constantly leads to a need for more computing power than ever before, regardless of being web-based or thick-client. Seeing the slowdown of growth in total CPU horsepower, people are looking to multi-core CPUs, 64-bit chips, or at adding more servers to their enterprise in order to meet their growing needs. Developers face the challenge of designing applications in the simple environment of a desktop scaled back for cost savings. Then they must be able to deploy into multi-core, multi-server environments in order to meet their companies business demands. Different technologies have been developed in order to support this. Different protocols have been drafted to help communicate between nodes. The debate rages on whether talking across the network should be visible in the API or abstracted away. Different technologies to support remotely connecting client process with server processes is under constant development. Introduction to Pyro (Python Remote Objects) Pyro is an open source project (pyro.sourceforge.net) that provides an object oriented form of RPC. As stated on the project's site, it resembles Java's Remote Method Invocation (RMI). It is less similar to CORBA (http://www.corba.org), a technology-neutral wire protocol used to link multiple processes together, because it doesn't require an interface definition language, nor is oriented towards linking different languages together. Pyro supports Python-to-Python communications. Thanks to the power of Jython, it is easy to link Java-to-Python, and vice versa. Python Remote Objects is not to be confused with the Python Robotics open source project (also named Pyro). Pyro is very easy to use out of the box with existing Python applications. The ability to publish services isn't hard to add to existing applications. Pyro uses its own protocol for RPC communication. Fundamentally, a Pyro-based application involves launching a Pyro daemon thread and then registering your server component with this thread. From that point on, the thread along with your server code is in stand-by mode, waiting to process client calls. The next step involves creating a Pyro client proxy that is configured to find the daemon thread, and then forward client calls to the server. From a high level perspective, this is very similar to what Java RMI and CORBA offer. However, thanks to the dynamic nature of Python, the configuration steps are much easier, and there are no requirements to extend any classes or implement any interfaces.. As simple as it is to use Pyro, there is still the requirement to write some minimal code to instantiate your objects and then register them. You must also code up the clients, making them aware of Pyro as well. Since the intent of this article is to dive into using Spring Python, we will skip writing a pure Pyro application. Instead, let's see how to use Spring Python's out-of-the-box Pyro-based components, eliminating the need to write any Pyro glue code. This lets us delegate everything to our IoC container so that it can do all the integration steps by itself. This reduces the cost of making our application distributed to zero. Converting a simple application into a distributed one on the same machine For this example, let's develop a simple service that processes some data and produces a response. Then, we'll convert it to a distributed service. First, let's create a simple service. For this example, let's create one that returns us an array of strings representing the Happy Birthday song with someone's name embedded in it. class Service(object): def happy_birthday(self, name): results = [] for i in range(4): if i == 2: results.append("Happy Birthday Dear %s!" % name) else: results.append("Happy Birthday to you!") return results Our service isn't too elaborate. Instead of printing the data directly to screen, it collects it together and returns it to the caller. This allows us the caller to print it, test it, store it, or do whatever it wants with the result. In the following screen text, we see a simple client taking the results and printing them a little formatting inside the Python shell. As we can see, we have defined a simple service, and can call it directly. In our case, we are simply joining the list together with a newline character, and printing it to the screen. Fetching the service from an IoC container from springpython.config import *from simple_service import *class HappyBirthdayContext(PythonConfig): def __init__(self): PythonConfig.__init__(self) @Object def service(self): return Service() Creating a client to call the service Now let's write a client script that will create an instance of this IoC container, fetch the service, and use it. from springpython.context import *from simple_service_ctx import *if __name__ == "__main__": ctx = ApplicationContext(HappyBirthdayContext()) s = ctx.get_object("service") print "n".join(s.happy_birthday("Greg")) Running this client script neatly creates an instance of our IoC container, fetches the service, and calls it with the same arguments shown earlier.
Read more
  • 0
  • 0
  • 7701

article-image-easily-writing-sql-queries-spring-python
Packt
24 May 2010
9 min read
Save for later

Easily Writing SQL Queries with Spring Python

Packt
24 May 2010
9 min read
(For more resources on Spring, see here.) Many of our applications contain dynamic data that needs to be pulled from and stored within a relational database. Even though key/value based data stores exist, a huge majority of data stores in production are housed in a SQL-based relational database. Given this de facto requirement, it improves developer efficiency if we can focus on the SQL queries themselves, and not spend lots of time writing plumbing code and making every query fault tolerant. The classic SQL issue SQL is a long existing standard that shares a common paradigm for writing queries with many modern programming languages (including Python). The resulting effect is that coding queries by hand is laborious. Let's explore this dilemma by writing a simple SQL query using Python's database API. SQL is a long existing standard that shares a common paradigm for writing queries with many modern programming languages (including Python). The resulting effect is that coding queries by hand is laborious. Let's explore this dilemma by writing a simple SQL query using Python's database API. DROP TABLE IF EXISTS article;CREATE TABLE article ( id serial PRIMARY KEY, title VARCHAR(11), wiki_text VARCHAR(10000));INSERT INTO article(id, title, wiki_textVALUES(1, 'Spring Python Book', 'Welcome to the [http://springpythonbook.com Spring Python] book, where you can learn more about [[Spring Python]].');INSERT INTO article(id, title, wiki_textVALUES(2, 'Spring Python', ''''Spring Python''' takes the concepts of Spring and applies them to world of [http://python.org Python].'); Now, let's write a SQL statement that counts the number of wiki articles in the system using the database's shell. SELECT COUNT(*) FROM ARTICLE Now let's write some Python code that will run the same query on an sqlite3 database using Python's official database API (http://www.python.org/dev/peps/pep-0249). import sqlite3db = sqlite3.connect("/path/to/sqlite3db")cursor = db.cursor()results = Nonetry: try: cursor.execute("SELECT COUNT(*) FROM ARTICLE") results = cursor.fetchall() except Exception, e: print "execute: Trapped %s" % efinally: try: cursor.close() except Exception, e: print "close: Trapped %s, and throwing away" % ereturn results[0][0] That is a considerable block of code to execute such a simple query. Let's examine it in closer detail. First, we connect to the database. For sqlite3, all we needed was a path. Other database engines usually require a username and a password. Next, we create a cursor in which to hold our result set. Then we execute the query. To protect ourselves from any exceptions, we need to wrap this with some exception handlers. After completing the query, we fetch the results. After pulling the results from the result set into a variable, we close the cursor. Finally, we can return our response. Python bundles up the results into an array of tuples. Since we only need one row, and the first column, we do a double index lookup. What is all this code trying to find in the database? The key statement is in a single line. cursor.execute("SELECT COUNT(*) FROM ARTICLE") What if we were writing a script? This would be a lot of work to find one piece of information. Granted, a script that exits quickly could probably skip some of the error handling as well as closing the cursor. But it is still is quite a bit of boiler plate to just get a cursor for running a query. But what if this is part of a long running application? We need to close the cursors after every query to avoid leaking database resources. Large applications also have a lot of different queries we need to maintain. Coding this pattern over and over can sap a development team of its energy. Parameterizing the code This boiler plate block of code is a recurring pattern. Do you think we could parameterize it and make it reusable? We've already identified that the key piece of the SQL statement. Let's try and rewrite it as a function doing just that. import sqlite3def query(sql_statement): db = sqlite3.connect("/path/to/sqlite3db") cursor = db.cursor() results = None try: try: cursor.execute(sql_statement) results = cursor.fetchall() except Exception, e: print "execute: Trapped %s" % efinally: try: cursor.close() except Exception, e: print "close: Trapped %s, and throwing away" % ereturn results[0][0] Our first step nicely parameterizes the SQL statement, but that is not enough. The return statement is hard coded to return the first entry of the first row. For counting articles, what we have written its fine. But this isn't flexible enough for other queries. We need the ability to plug in our own results handler. import sqlite3def query(sql_statement, row_handler): db = sqlite3.connect("/path/to/sqlite3db") cursor = db.cursor() results = None try: try: cursor.execute(sql_statement) results = cursor.fetchall() except Exception, e: print "execute: Trapped %s" % e finally: try: cursor.close() except Exception, e: print "close: Trapped %s, and throwing away" % e return row_handler(results) We can now code a custom handler. def count_handler(results): return results[0][0]query("select COUNT(*) from ARTICLES", count_handler) With this custom results handler, we can now invoke our query function, and feed it both the query and the handler. The only thing left is to handle creating a connection to the database. It is left as an exercise for the reader to wrap the sqlite3 connection code with a factory solution. What we have coded here is essentially the core functionality of DatabaseTemplate. This method of taking an algorithm and parameterizing it for reuse is known as the template pattern. There are some extra checks done to protect the query from SQL injection attacks. Replacing multiple lines of query code with one line of Spring Python Spring Python has a convenient utility class called DatabaseTemplate that greatly simplifies this problem. Let's replace the two lines of import and connect code from the earlier example with some Spring Python setup code. from springpython.database.factory import Sqlite3ConnectionFactoryfrom springpython.database.core import DatabaseTemplateconn_factory = Sqlite3ConnectionFactory("/path/to/sqlite3db")dt = DatabaseTemplate(conn_factory) At first glance, we appear to be taking a step back. We just replaced two lines of earlier code with four lines. However, the next block should improve things significantly. Let's replace the earlier coded query with a call using our instance of return dt.query_for_object("SELECT COUNT(*) FROM ARTICLE") Now we have managed to reduce a complex 14-line block of code into one line of Spring Python code. This makes our Python code appear as simple as the original SQL statement we typed in the database's shell. And it also reduces the noise. The Spring triangle—Portable Service Abstractions From this diagram earlier , as an illustration of the key principles behind Spring Python is being made. The DatabaseTemplate represents a Portable Service Abstraction because: It is portable because it uses Python's standardized API, not tying us to any database vendor. Instead, in our example, we injected in an instance of Sqlite3ConnectionFactory It provides the useful service of easily accessing information stored in a relational database, but letting us focus on the query, not the plumbing code It offers a nice abstraction over Python's low level database API with reduced code noise. This allows us to avoid the cost and risk of writing code to manage cursors and exception handling DatabaseTemplate handles exceptions by catching and holding them, then properly closing the cursor. It then raises it wrapped inside a Spring Python DataAccessException. This way, database resources are properly disposed of without losing the exception stack trace. Using DatabaseTemplate to retrieve objects Our first example showed how we can easily reduce our code volume. But it was really only for a simple case. A really useful operation would be to execute a query, and transform the results into a list of objects. First, let's define a simple object we want to populate with the information retrieved from the database. As shown on the Spring triangle diagram, using simple objects is a core facet to the 'Spring way'. class Article(object): def __init__(self, id=None, title=None, wiki_text=None): self.id = id self.title = title self.wiki_text = wiki_text If we wanted to code this using Python's standard API, our code would be relatively verbose like this: cursor = db.cursor()results = []try: try: cursor.execute("SELECT id, title, wiki_text FROM ARTICLE") temp = cursor.fetchall() for row in temp: results.append( Article(id=temp[0], title=temp[1], wiki_text=temp[2])) except Exception, e: print "execute: Trapped %s" % efinally: try: cursor.close() except Exception, e: print "close: Trapped %s, and throwing away" % ereturn results This isn't that different from the earlier example. The key difference is that instead of assigning fetchall directly to results, we instead iterate over it, generating a list of Article objects. Instead, let's use DatabaseTemplate to cut down on the volume of code return dt.query("SELECT id, title, wiki_text FROM ARTICLE", ArticleMapper()) We aren't done yet. We have to code ArticleMapper, the object class used to iterate over our result set. from springpython.database.core import RowMapperclass ArticleMapper(RowMapper): def map_row(self, row, metadata=None): return Article(id=row[0], title=row[1], wiki_text=row[2]) RowMapper defines a single method: map_row. This method is called for each row of data, and includes not only the information, but also the metadata provided by the database. ArticleMapper can be re-used for every query that performs the same mapping This is slightly different from the parameterized example shown earlier where we defined a row-handling function. Here we define a class that contains the map_row function. But the concept is the same: inject a row-handler to convert the data.
Read more
  • 0
  • 0
  • 4284

article-image-spring-security-configuring-secure-passwords
Packt
24 May 2010
6 min read
Save for later

Encode your password with Spring Security 3

Packt
24 May 2010
6 min read
This article by Peter Mularien is an excerpt from the book Spring Security 3. In this article, we will: Examine different methods of configuring password encoding Understand the password salting technique of providing additional security to stored passwords (For more resources on Spring, see here.) In any secured system, password security is a critical aspect of trust and authoritativeness of an authenticated principal. Designers of a fully secured system must ensure that passwords are stored in a way in which malicious users would have an impractically difficult time compromising them. The following general rules should be applied to passwords stored in a database: Passwords must not be stored in cleartext (plain text) Passwords supplied by the user must be compared to recorded passwords in the database A user's password should not be supplied to the user upon demand (even if the user forgets it) For the purposes of most applications, the best fit for these requirements involves one-way encoding or encryption of passwords as well as some type of randomization of the encrypted passwords. One-way encoding provides the security and uniqueness properties that are important to properly authenticate users with the added bonus that once encrypted, the password cannot be decrypted. In most secure application designs, it is neither required nor desirable to ever retrieve the user's actual password upon request, as providing the user's password to them without proper additional credentials could present a major security risk. Most applications instead provide the user the ability to reset their password, either by presenting additional credentials (such as their social security number, date of birth, tax ID, or other personal information), or through an email-based system. Storing other types of sensitive information Many of the guidelines listed that apply to passwords apply equally to other types of sensitive information, including social security numbers and credit card information (although, depending on the application, some of these may require the ability to decrypt). It's quite common for databases storing this type of information to represent it in multiple ways, for example, a customer's full 16-digit credit card number would be stored in a highly encrypted form, but the last four digits might be stored in cleartext (for reference, think of any internet commerce site that displays XXXX XXXX XXXX 1234 to help you identify your stored credit cards). You may already be thinking ahead and wondering, given our (admittedly unrealistic) approach of using SQL to populate our HSQL database with users, how do we encode the passwords? HSQL, or most other databases for that matter, don't offer encryption methods as built-in database functions. Typically, the bootstrap process (populating a system with initial users and data) is handled through some combination of SQL loads and Java code. Depending on the complexity of your application, this process can get very complicated. For the JBCP Pets application, we'll retain the embedded-database declaration and the corresponding SQL, and then add a small bit of Java to fire after the initial load to encrypt all the passwords in the database. For password encryption to work properly, two actors must use password encryption in synchronization ensuring that the passwords are treated and validated consistently. Password encryption in Spring Security is encapsulated and defined by implementations of the o.s.s.authentication.encoding.PasswordEncoder interface. Simple configuration of a password encoder is possible through the <password-encoder> declaration within the <authentication-provider> element as follows: <authentication-manager alias="authenticationManager"> <authentication-provider user-service-ref="jdbcUserService"> <password-encoder hash="sha"/> </authentication-provider></authentication-manager> You'll be happy to learn that Spring Security ships with a number of implementations of PasswordEncoder, which are applicable for different needs and security requirements. The implementation used can be specified using the hash attribute of the <password-encoder> declaration. The following table provides a list of the out of the box implementation classes and their benefits. Note that all implementations reside in the o.s.s.authentication. encoding package. Implementation class Description hash value PlaintextPasswordEncoder Encodes the password as plaintext. Default DaoAuthenticationProvider password encoder. plaintext Md4PasswordEncoder PasswordEncoder utilizing the MD4 hash algorithm. MD4 is not a secure algorithm-use of this encoder is not recommended. md4 Md5PasswordEncoder PasswordEncoder utilizing the MD5 one-way encoding algorithm. md5 ShaPasswordEncoder PasswordEncoder utilizing the SHA one-way encoding algorithm. This encoder can support confi gurable levels of encoding strength. Sha   sha-256 LdapShaPasswordEncoder Implementation of LDAP SHA and LDAP SSHA algorithms used in integration with LDAP authentication stores. {sha}   {ssha}   As with many other areas of Spring Security, it's also possible to reference a bean definition implementing PasswordEncoder to provide more precise configuration and allow the PasswordEncoder to be wired into other beans through dependency injection. For JBCP Pets, we'll need to use this bean reference method in order to encode the bootstrapped user data. Let's walk through the process of configuring basic password encoding for the JBCP Pets application. Configuring password encoding Configuring basic password encoding involves two pieces—encrypting the passwords we load into the database after the SQL script executes, and ensuring that the DaoAuthenticationProvider is configured to work with a PasswordEncoder. Configuring the PasswordEncoder First, we'll declare an instance of a PasswordEncoder as a normal Spring bean: <bean class="org.springframework.security.authentication. encoding.ShaPasswordEncoder" id="passwordEncoder"/> You'll note that we're using the SHA-1 PasswordEncoder implementation. This is an efficient one-way encryption algorithm, commonly used for password storage. Configuring the AuthenticationProvider We'll need to configure the DaoAuthenticationProvider to have a reference to the PasswordEncoder, so that it can encode and compare the presented password during user login. Simply add a <password-encoder> declaration and refer to the bean ID we defined in the previous step: <authentication-manager alias="authenticationManager"> <authentication-provider user-service-ref="jdbcUserService"> <password-encoder ref="passwordEncoder"/> </authentication-provider></authentication-manager> Try to start the application at this point, and then try to log in. You'll notice that what were previously valid login credentials are now being rejected. This is because the passwords stored in the database (loaded with the bootstrap test-users-groupsdata. sql script) are not stored in an encrypted form that matches the password encoder. We'll need to post-process the bootstrap data with some simple Java code. Writing the database bootstrap password encoder The approach we'll take for encoding the passwords loaded via SQL is to have a Spring bean that executes an init method after the embedded-database bean is instantiated. The code for this bean, com.packtpub.springsecurity.security. DatabasePasswordSecurerBean, is fairly simple. public class DatabasePasswordSecurerBean extends JdbcDaoSupport { @Autowired private PasswordEncoder passwordEncoder; public void secureDatabase() { getJdbcTemplate().query("select username, password from users", new RowCallbackHandler(){ @Override public void processRow(ResultSet rs) throws SQLException { String username = rs.getString(1); String password = rs.getString(2); String encodedPassword = passwordEncoder.encodePassword(password, null); getJdbcTemplate().update("update users set password = ? where username = ?", encodedPassword,username); logger.debug("Updating password for username: "+username+" to: "+encodedPassword); } }); } } The code uses the Spring JdbcTemplate functionality to loop through all the users in the database and encode the password using the injected PasswordEncoder reference. Each password is updated individually.
Read more
  • 0
  • 0
  • 10184
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at €18.99/month. Cancel anytime
article-image-user-authentication-codeigniter-17-using-twitter-oauth
Packt
21 May 2010
6 min read
Save for later

User Authentication with Codeigniter 1.7 using Twitter oAuth

Packt
21 May 2010
6 min read
(Read more interesting articles on CodeIgniter 1.7 Professional Development here.) How oAuth works Getting used to how Twitter oAuth works takes a little time. When a user comes to your login page, you send a GET request to Twitter for a set of request codes. These request codes are used to verify the user on the Twitter website. The user then goes through to Twitter to either allow or deny your application access to their account. If they allow the application access, they will be taken back to your application. The URL they get sent to will have an oAuth token appended to the end. This is used in the next step. Back at your application, you then send another GET request for some access codes from Twitter. These access codes are used to verify that the user has come directly from Twitter, and has not tried to spoof an oAuth token in their web browser. Registering a Twitter application Before we write any code, we need to register an application with Twitter. This will give us the two access codes that we need. The first is a consumer key, and the second is a secret key. Both are used to identify our application, so if someone posts a message to Twitter through our application, our application name will show up alongside the user's tweet. To register a new application with Twitter, you need to go to http://www.twitter.com/apps/new. You'll be asked for a photo for your application and other information, such as website URL, callback URL, and a description, among other things. You must select the checkbox that reads Yes, use Twitter for login or you will not be able to authenticate any accounts with your application keys. Once you've filled out the form, you'll be able to see your consumer key and consumer secret code. You'll need these later. Don't worry though; you'll be able to get to these at any time so there's no need to save them to your hard drive. Here's a screenshot of my application: Downloading the oAuth library Before we get to write any of our CodeIgniter wrapper library, we need to download the oAuth PHP library. This allows us to use the oAuth protocol without writing the code from scratch ourselves. You can find the PHP Library on the oAuth website at www.oauth.net/code. Scroll down to PHP and click on the link to download the basic PHP Library; or just visit: http://oauth.googlecode.com/svn/code/php/—the file you need is named OAuth.php. Download this file and save it in the folder system/application/libraries/twitter/—you'll need to create the twitter folder. We're simply going to create a folder for each different protocol so that we can easily distinguish between them. Once you've done that, we'll create our Library file. Create a new file in the system/application/libraries/ folder, called Twitter_oauth.php. This is the file that will contain functions to obtain both request and access tokens from Twitter, and verify the user credentials. The next section of the article will go through the process of creating this library alongside the Controller implementation; this is because the whole process requires work on both the front-end and the back-end. Bear with me, as it could get a little confusing, especially when trying to implement a brand new type of system such as Twitter oAuth. Library base class Let's break things down into small sections. The following code is a version of the base class with all its guts pulled out. It simply loads the oAuth library and sets up a set of variables for us to store certain information in. Below this, I'll go over what each of the variables are there for. <?phprequire_once(APPPATH . 'libraries/twitter/OAuth.php');class Twitter_oauth{ var $consumer; var $token; var $method; var $http_status; var $last_api_call;}?> The first variable you'll see is $consumer—it is used to store the credentials for our application keys and the user tokens as and when we get them. The second variable you see on the list is $token—this is used to store the user credentials. A new instance of the oAuth class OAuthConsumer is created and stored in this variable. Thirdly, you'll see the variable $method—this is used to store the oAuth Signature Method (the way we sign our oAuth calls). Finally, the last two variables, $http_status and $last_api_call, are used to store the last HTTP Status Code and the URL of the last API call, respectively. These two variables are used solely for debugging purposes. Controller base class The Controller is the main area where we'll be working, so it is crucial that we design the best way to use it so that we don't have to repeat our code. Therefore, we're going to have our consumer key and consumer secret key in the Controller. Take a look at the Base of our class to get a better idea of what I mean. <?phpsession_start();class Twitter extends Controller{ var $data; function Twitter() { parent::Controller(); $this->data['consumer_key'] = ""; $this->data['consumer_secret'] = "";} The global variable $data will be used to store our consumer key and consumer secret. These must not be left empty and will be provided to you by Twitter when creating your application. We use these when instantiating the Library class, which is why we need it available throughout the Controller instead of just in one function. We also allow for sessions to be used in the Controller, as we want to temporarily store some of the data that we get from Twitter in a session. We could use the CodeIgniter Session Library, but it doesn't offer us as much flexibility as native PHP sessions; this is because with native sessions we don't need to rely on cookies and a database, so we'll stick with the native sessions for this Controller.
Read more
  • 0
  • 0
  • 3370

article-image-setting-complete-django-e-commerce-store-30-minutes
Packt
21 May 2010
7 min read
Save for later

Setting up a Complete Django E-commerce store in 30 minutes

Packt
21 May 2010
7 min read
In order to demonstrate Django's rapid development potential, we will begin by constructing a simple, but fully-featured, e-commerce store. The goal is to be up and running with a product catalog and products for sale, including a simple payment processing interface, in about half-an-hour. If this seems ambitious, remember that Django offers a lot of built-in shortcuts for the most common web-related development tasks. We will be taking full advantage of these and there will be side discussions of their general use. In addition to building our starter storefront, this article aims to demonstrate some other Django tools and techniques. In this article by Jesse Legg, author of Django 1.2 e-commerce, we will: Create our Django Product model to take advantage of the automatic admin tool Build a flexible but easy to use categorization system, to better organize our catalog of products Utilize Django's generic view framework to expose a quick set of views on our catalog data Finally, create a simple template for selling products through the Google Checkout API (Read more interesting articles on Django 1.2 e-commerce here.) Before we begin, let's take a moment to check our project setup. Our project layout includes two directories: one for files specific to our personal project (settings, URLs, and so on), and the other for our collection of e-commerce Python modules (coleman). This latter location is where the bulk of the code will live. If you have downloaded the source code from the Packt website, the contents of the archive download represents everything in this second location. Designing a product catalog The starting point of our e-commerce application is the product catalog. In the real world, businesses may produce multiple catalogs for mutually exclusive or overlapping subsets of their products. Some examples are: fall and spring catalogs, catalogs based on a genre or sub-category of product such as catalogs for differing kinds of music (for example, rock versus classical), and many other possibilities. In some cases a single catalog may suffice, but allowing for multiple catalogs is a simple enhancement that will add flexibility and robustness to our application. As an example, we will imagine a fictitious food and beverage company, CranStore.com, that specializes in cranberry products: cranberry drinks, food, and desserts. In addition, to promote tourism at their cranberry bog, they sell numerous gift items, including t-shirts, hats, mouse pads, and the like. We will consider this business to illustrate examples as they relate to the online store we are building. We will begin by defining a catalog model called Catalog. The basic model structure will look like this: class Catalog(models.Model): name = models.CharField(max_length=255 slug = models.SlugField(max_length=150) publisher = models.CharField(max_length=300) description = models.TextField() pub_date = models.DateTimeField(default=datetime.now) This is potentially the simplest model we will create. It contains only five, very simple fields. But it is a good starting point for a short discussion about Django model design. Notice that we have not included any relationships to other models here. For example, there is no products ManyToManyField. New Django developers tend to overlook simple design decisions such as the one shown previously, but the ramifications are quite important. The first reason for this design is a purely practical one. Using Django's built-in admin tool can be a pleasure or a burden, depending on the design of your models. If we were to include a products field in the Catalog design, it would be a ManyToManyField represented in the admin as an enormous multiple-select HTML widget. This is practically useless in cases where there could be thousands of possible selections. If, instead, we attach a ForeignKey to Catalog on a Product model (which we will build shortly), we instantly increase the usability of Django's automatic admin tool. Instead of a select-box where we must shift-click to choose multiple products, we have a much simpler HTML drop-down interface with significantly fewer choices. This should ultimately increase the usability of the admin for our users. For example, CranStore.com sells lots of t-shirts during the fall when cranberries are ready to harvest and tourism spikes. They may wish to run a special catalog of touristy products on their website during this time. For the rest of the year, they sell a smaller selection of items online. The developers at CranStore create two catalogs: one is named Fall Collection and the other is called Standard Collection. When creating product information, the marketing team can decide which catalog an individual product belongs to by simply selecting them from the product editing page. This is more intuitive than selecting individual products out of a giant list of all products from the catalog admin page. Secondly, designing the Catalog model this way prevents potential "bloat" from creeping into our models. Imagine that CranStore decides to start printing paper versions of their catalogs and mailing them to a subscriber list. This would be a second potential ManyToManyField on our Catalog model, a field called subscribers. As you can see, this pattern could repeat with each new feature CranStore decides to implement. By keeping models as simple as possible, we prevent all kinds of needless complexity. In addition we also adhere to a basic Django design principle, that of "loose coupling". At the database level, the tables Django generates will be very similar regardless of where our ManyToManyField lives. Usually the only difference will be in the table name. Thus it generally makes more sense to focus on the practical aspects of Django model design. Django's excellent reverse relationship feature also allows a great deal of flexibility when it comes time to using the ORM to access our data. Model design is difficult and planning up-front can pay great dividends later. Ideally, we want to take advantage of the automatic, built-in features that make Django so great. The admin tool is a huge part of this. Anyone who has had to build a CRUD interface by hand so that non-developers can manage content should recognize the power of this feature. In many ways it is Django's "killer app". Creating the product model Finally, let's implement our product model. We will start with a very basic set of fields that represent common and shared properties amongst all the products we're likely to sell. Things like a picture of the item, its name, a short description, and pricing information. class Product(models.Model): name = models.CharField(max_length=300) slug = models.SlugField(max_length=150) description = models.TextField() photo = models.ImageField(upload_to='product_photo', blank=True) manufacturer = models.CharField(max_length=300, blank=True) price_in_dollars = models.DecimalField(max_digits=6, decimal_places=2) Most e-commerce applications will need to capture many additional details about their products. We will add the ability to create arbitrary sets of attributes and add them as details to our products later in this article. For now, let's assume that these six fields are sufficient. A few notes about this model: first, we have used a DecimalField to represent the product's price. Django makes it relatively simple to implement a custom field and such a field may be appropriate here. But for now we'll keep it simple and use a plain and built-in DecimalField to represent currency values. Notice, too, the way we're storing the manufacturer information as a plain CharField. Depending on your application, it may be beneficial to build a Manufacturer model and convert this field to a ForeignKey. Lastly, you may have realized by now that there is no connection to a Catalog model, either by a ForeignKey or ManyToManyField. Earlier we discussed the placement of this field in terms of whether it belonged to the Catalog or in the Product model and decided, for several reasons, that the Product was the better place. We will be adding a ForeignKey to our Product model, but not directly to the Catalog. In order to support categorization of products within a catalog, we will be creating a new model in the next section and using that as the connection point for our products.
Read more
  • 0
  • 0
  • 14411

article-image-user-authentication-codeigniter-17-using-facebook-connect
Packt
21 May 2010
8 min read
Save for later

User Authentication with Codeigniter 1.7 using Facebook Connect

Packt
21 May 2010
8 min read
(Read more interesting articles on CodeIgniter 1.7 Professional Development here.) Registering a Facebook application You need to register a new Facebook Application so that you can get an API key and an Application Secret Key. Head on over to www.facebook.com/developers/ and click on the Set up New Application button in the upper right–hand corner. This process is very similar to setting up a new Twitter application which we covered in the previous article, so I won't bore you with all of the details. Once you've done that, you should have your API key and Application Secret Key. These two things will enable Facebook to recognize your application. Download the Client library When you are on your applications page showing all your applications' information, scroll down the page to see a link to download the Client Library. Once you've downloaded it, simply untar it. There are two folders inside the facebook-platform folder, footprints and php. We are only going to be using the php folder. Open up the php folder; there are two files here that we don't need, facebook_desktop.php and facebook_mobile.php—you can delete them. Finally, we can copy this folder into our application. Place it in the system/application/libraries folder, and then rename the folder to facebook. This helps us to keep our code tidy and properly sorted. Our CodeIgniter Wrapper Before we start coding, we need to know what we need to code in order to make the Facebook Client Library work with our CodeIgniter installation. Our Wrapper library needs to instantiate the Facebook class with our API Key and Secret Application Key. We'll also want it to create a session for the user when they are logged in. If a session is found but the user is not authenticated, we will need to destroy the session. You should create a new file in the system/application/libraries/ folder, called Facebook_connect.php. This is where the Library code given next should be placed. Base class The Base Class for our Facebook Connect Wrapper Library is very simple: <?phprequire_once(APPPATH . 'libraries/facebook/facebook.php');class Facebook_connect{ var $CI; var $connection; var $api_key; var $secret_key; var $user; var $user_id; var $client;}?> The first thing that our Library needs to do is to load the Facebook library—the one we downloaded from facebook.com. We build the path for this by using APPPATH, a constant defined by CodeIgniter to be the path of the application folder. Then, in our Class we have a set of variables. The $CI variable is the variable in which we will store the CodeIgniter super object; this allows us to load CodeIgniter resources (libraries, models, views, and so on) in our library. We'll only be using this to load and use the CodeIgniter Session library, however. The $connection variable will contain the instance of the Facebook class. This will allow us to grab any necessary user data and perform any operations that we like, such as updating a user's status or sending a message to one of their friends. The next few variables are pretty self-explanatory—they will hold our API Key and Secret Key. The $user variable will be used to store all of the information about our user, including general details about the user such as their profile URL and their name. The $user_id variable will be used to store the user ID of our user. Finally, the $client variable is used to store general information about our connection to Facebook, including the username of the user currently using the connection, amongst other things such as server addresses to query for things like photos. Class constructor Our class constructor has to do a few things in order to allow us to authenticate our users using Facebook Connect. Here's the code: function Facebook_connect($data){ $this->CI =& get_instance(); $this->CI->load->library('session'); $this->api_key = $data['api_key']; $this->secret_key = $data['secret_key']; $this->connection = new Facebook($this->api_key, $this->secret_key); $this->client = $this->connection->api_client; $this->user_id = $this->connection->get_loggedin_user(); $this->_session();} The first line in our function should be new to everyone reading this article. The function get_instance() allows us to assign the CodeIgniter super object by reference to a local variable. This allows us to use all of CodeIgniter's syntax for loading libraries, and so on; but instead of using $this->load we would use $this->CI->load. But of course it doesn't just allow us to use the Loader—it allows us to use any CodeIgniter resource, as we normally would inside a Controller or a Model. The next line of code gives us a brilliant example of this: we're loading the session library using the variable $this->CI rather than the usual $this. The next two lines simply set the values of the API key and Secret Application Key into a class variable so that we can reference it throughout the whole class. The $data array is passed into the constructor when we load the library in our Controller. More on that when we get there. Next up, we create a new instance of the Facebook Class (this is contained within the Facebook library that we include before our own class code) and we pass the API Key and Secret Application Key through to the class instance. This is all assigned to the class variable $this->connection, so that we can easily refer to it anywhere in the class. The next two lines are specific parts of the overall Facebook instance. All of the client details and the data that helps us when using the connection are stored in a class variable, in order to make it more accessible. We store the client details in the variable $this->client. The next line of code stores all of the details about the user that were provided to us by the Facebook class. We store this in a class variable for the same reason as storing the client data: it makes it easier to get to. We store this data in $this->user_id. The next line of code calls upon a function inside our class. The underscore at the beginning tells CodeIgniter that we only want to be able to use this function inside this class; so you couldn't use it in a Controller, for example. I'll go over this function shortly. _session(); This function manages the user's CodeIgniter session. Take a look at the following code: function _session(){ $user = $this->CI->session->userdata('facebook_user'); if($user === FALSE && $this->user_id !== NULL) { $profile_data = array('uid','first_name', 'last_name', 'name', 'locale', 'pic_square', 'profile_url'); $info = $this->connection->api_client-> users_getInfo($this->user_id, $profile_data); $user = $info[0]; $this->CI->session->set_userdata('facebook_user', $user); } elseif($user !== FALSE && $this->user_id === NULL) { $this->CI->session->sess_destroy(); } if($user !== FALSE) { $this->user = $user; }} This function initially creates a variable and sets its value to that of the session data from the CodeIgniter session library. Then we go through a check to see if the session is empty and the $this->user_id variable is false. This means that the user has not yet logged in using Facebook Connect. So we create an array of the data that we want to get back from the Facebook class, and then use the function users_getInfo() provided by the class to get the information in the array that we created. Then we store this data into the $user variable and create a new session for the user. The next check that we do is that if the $user variable is not empty, but the $this->user_id variable is empty, then the user is not authenticated on Facebook's side so we should destroy the session. We do this by using a function built in to the Session Library sess_destroy(); Finally, we check to see if the $user variable is not equal to FALSE. If it passes this check, we set the $this->user class variable to that of the local $user variable.
Read more
  • 0
  • 0
  • 2301

article-image-migration-spring-security-3
Packt
21 May 2010
5 min read
Save for later

Migration to Spring Security 3

Packt
21 May 2010
5 min read
(For more resources on Spring, see here.) During the course of this article we will: Review important enhancements in Spring Security 3 Understand configuration changes required in your existing Spring Security 2 applications when moving them to Spring Security 3 Illustrate the overall movement of important classes and packages in Spring Security 3 Once you have completed the review of this article, you will be in a good position to migrate an existing application from Spring Security 2 to Spring Security 3. Migrating from Spring Security 2 You may be planning to migrate an existing application to Spring Security 3, or trying to add functionality to a Spring Security 2 application and looking for guidance. We'll try to address both of your concerns in this article. First, we'll run through the important differences between Spring Security 2 and 3—both in terms of features and configuration. Second, we'll provide some guidance in mapping configuration or class name changes. These will better enable you to translate the examples from Spring Security 3 back to Spring Security 2 (where applicable). A very important migration note is that Spring Security 3 mandates a migration to Spring Framework 3 and Java 5 (1.5) or greater. Be aware that in many cases, migrating these other components may have a greater impact on your application than the upgrade of Spring Security! Enhancements in Spring Security 3 Significant enhancements in Spring Security 3 over Spring Security 2 include the following: The addition of Spring Expression Language (SpEL) support for access declarations, both in URL patterns and method access specifications. Additional fine-grained configuration around authentication and accessing successes and failures. Enhanced capabilities of method access declaration, including annotationbased pre-and post-invocation access checks and filtering, as well as highly configurable security namespace XML declarations for custom backing bean behavior. Fine-grained management of session access and concurrency control using the security namespace. Noteworthy revisions to the ACL module, with the removal of the legacy ACL code in o.s.s.acl and some important issues with the ACL framework are addressed. Support for OpenID Attribute Exchange, and other general improvements to the robustness of OpenID. New Kerberos and SAML single sign-on support through the Spring Security Extensions project. Other more innocuous changes encompassed a general restructuring and cleaning up of the codebase and the configuration of the framework, such that the overall structure and usage makes much more sense. The authors of Spring Security have made efforts to add extensibility where none previously existed, especially in the areas of login and URL redirection. If you are already working in a Spring Security 2 environment, you may not find compelling reasons to upgrade if you aren't pushing the boundaries of the framework. However, if you have found limitations in the available extension points, code structure, or configurability of Spring Security 2, you'll welcome many of the minor changes that we discuss in detail in the remainder of this article. Changes to configuration in Spring Security 3 Many of the changes in Spring Security 3 will be visible in the security namespace style of configuration. Although this article cannot cover all of the minor changes in detail, we'll try to cover those changes that will be most likely to affect you as you move to Spring Security 3. Rearranged AuthenticationManager configuration The most obvious changes in Spring Security 3 deal with the configuration of the AuthenticationManager and any related AuthenticationProvider elements. In Spring Security 2, the AuthenticationManager and AuthenticationProvider configuration elements were completely disconnected—declaring an AuthenticationProvider didn't require any notion of an AuthenticationManager at all. <authentication-provider> <jdbc-user-service data-source-ref="dataSource" /></authentication-provider> In Spring Security 2 to declare the <authentication-manager> element as a sibling of any AuthenticationProvider. <authentication-manager alias="authManager"/><authentication-provider> <jdbc-user-service data-source-ref="dataSource"/></authentication-provider><ldap-authentication-provider server-ref="ldap://localhost:10389/"/> In Spring Security 3, all AuthenticationProvider elements must be the children of <authentication-manager> element, so this would be rewritten as follows: <authentication-manager alias="authManager"> <authentication-provider> <jdbc-user-service data-source-ref="dataSource" /> </authentication-provider> <ldap-authentication-provider server-ref= "ldap://localhost:10389/"/></authentication-manager> Of course, this means that the <authentication-manager> element is now required in any security namespace configurations. If you had defined a custom AuthenticationProvider in Spring Security 2, you would have decorated it with the <custom-authentication-provider> element as part of its bean definition. <bean id="signedRequestAuthenticationProvider" class="com.packtpub.springsecurity.security .SignedUsernamePasswordAuthenticationProvider"> <security:custom-authentication-provider/> <property name="userDetailsService" ref="userDetailsService"/><!-- ... --></bean> While moving this custom AuthenticationProvider to Spring Security 3, we would remove the decorator element and instead configure the AuthenticationProvider using the ref attribute of the <authentication-provider> element as follows: <authentication-manager alias="authenticationManager"> <authentication-provider ref= "signedRequestAuthenticationProvider"/></authentication-manager> Of course, the source code of our custom provider would change due to class relocations and renaming in Spring Security 3—look later in the article for basic guidelines, and in the code download for this article to see a detailed mapping. New configuration syntax for session management options In addition to continuing support for the session fixation and concurrency control features from prior versions of the framework, Spring Security 3 adds new configuration capabilities for customizing URLs and classes involved in session and concurrency control management. If your older application was configuring session fixation protection or concurrent session control, the configuration settings have a new home in the <session-management> directive of the <http> element. In Spring Security 2, these options would be configured as follows: <http ... session-fixation-protection="none"><!-- ... --> <concurrent-session-control exception-if-maximum-exceeded ="true" max-sessions="1"/></http> The analogous configuration in Spring Security 3 removes the session-fixation-protection attribute from the <http> element, and consolidates as follows: <http ...> <session-management session-fixation-protection="none"> <concurrency-control error-if-maximum-exceeded ="true" max-sessions="1"/> </session-management></http> You can see that the new logical organization of these options is much more sensible and leaves room for future expansion.
Read more
  • 0
  • 0
  • 20946
article-image-oracle-rdbms-log-miner-utility-fra-and-aum
Packt
20 May 2010
7 min read
Save for later

Oracle: RDBMS Log Miner Utility, FRA, and AUM

Packt
20 May 2010
7 min read
Log Miner can help when questions such as the following come up: What was changed? Who changed it? And in what order? When unauthorized people change data, they may assume that the record does not retain all changes if that information isn't viewable at the application level. There is a record of all changes that are logged, but it takes time and trouble to find that information. The tool most often used is the PL/SQL package DBMS_LOGMNR, but the GUI Interface called Log Miner Viewer has been added to the OEM. There are quite a few examples in the Oracle Database Utilities Guide of how to use this utility for both the browser-based and PL/SQL versions. We will concentrate on when and how to find the data to restore. You already should have a good understanding of the database structures that include the undo and redo logs: undo is generated when an end user starts changing data and redo is generated after the commit. Each is written to their own set of files. While undo and redo are both online (database is open), archived redo is offline and written to a disk. Archived redo logs are no longer needed for the transactions inside the database because they have been committed and written to disk. Archive logs are still important in order to restore the previously committed transactions in a recovery situation. Making an archive log offl ine allows backup procedures (RMAN, third-party backup software or OS utilities) to manipulate the files at the operating system level. Recovery is a database process that will: Roll forward changes from redo logs and then rollback statements any end user used the rollback command for. Roll back any uncommitted changes found in the UNDO segments. There are specific Oracle processes such as LGWR that write the redo to the online logs and then an archiver process (ARC) writes to the archived logs. The only way to ensure every transaction in a database has been logged for recovery purposes is to operate in ARCHIVELOG mode. There are special situations that will call for running in noarchivelog mode. It is assumed that any transactions lost between backups can be recreated. Archived redo logs can be used to restore transactions that occurred between regular backups. From the last exercise, you also have a good understanding of read consistency available from undo segments, which also contribute to redo entries. The DBMS_LOGMNR package is used to find data in both the undo and redo database structures. It is also useful for analyzing patterns over time for specific tuning needs, schema changes, and forecasting the time for hardware upgrades. With the DBMS_LOGMNR package, you can extract data that populates the V$LOGMNR_CONTENTS view with the actual transactions that have been executed. These entries contain both the REDO and UNDO statements. You can operate Log Miner on the original database that created the log entries or almost any other Oracle database of a higher version that is running the same character set, database block size, and operating system. This is why it is critical that you protect the online redo, undo, and archive logs—they can be mined for information. Most often a DBA will actually use a different database to do the mining so that it doesn't consume additional resources in a production database. If you use a different database than where the original transactions were created, you will have to rebuild the Log Miner data dictionary (online, offline, or a standalone flat file). The dictionary translates the internal object identifiers and types to table and column names that can be queried, but those object IDs will vary between databases, making the rebuild a requirement. The Log Miner example task requires several preparatory steps to be completed first, with some additional discussion along the way. Discussion includes archiving, supplemental logging, and Flashback technologies. You won't get to an actual logminer example for quite a few pages. Since logminer has extensive documentation detailing all of the steps for various scenarios, it was decided to only include a lesser known method of using logminer. Turn on archivelog mode Before we delve into the mining exercise, we will cover more information about SCNs, as they relate to checkpoints and log switches while turning on archiving for the database. Transactions in a database produce redo entries in the redo log buffer (in memory), but that is always being written to the online redo logs. That occurs according to different triggering events that can happen in the redo stream—a certain amount of data, commits, 3 seconds or 1/3 full redo log buffer. Whether these triggering events occur or not depends on the type and frequency of transactions. A checkpoint synchronizes modified data blocks in the redo log buffer with the actual data files, keeping the data consistent. In the case of a database crash, this identifies the point where all outstanding data (transactions) have been written to disk. This checkpoint isn't synchronized with the SCN of a transaction commit and it does not behave like a log switch. The files you will need as you work through this exercise are included in the code as follows: sys_archive.sql sysarchive.lst Open up the file sysarchive.lst. One of the most important views (anything labeled v$ is called a dynamic view) in the database is v$database. SYS@NEWDB> SELECT LOG_MODE, NAME, CURRENT_SCN, ARCHIVE_CHANGE#, OPEN_MODE FROM V$DATABASE; Find this section for the statement from v$log_history farther down in sysarchive.lst. What are all these entries if we aren't in archivelog mode? These are the log switches to the online redo logs. They are overwritten once that section of the redo log is no longer needed by a transaction to maintain consistency. This is where a checkpoint comes into play. It ensures that data is written to the disk and is independent of the ARC log switch process. Once we switch to archivelog mode, the online redo will still be overwritten, but the ARC process will write a copy of that log to an archive destination. Below you will see that each log contains a range of database SCNs. This log contains database changes from the first SCN number to the next. Now we try to correlate archive_change# and checkpoint_change#. Also notice that the checkpoint_change# for each data file is consistent for normal database operations. I am showing only the partial output from the following command for the single data file created: At this point, we have started the database in mount mode (the controlfile needs to be accessed, but the database is not opened for full use), turned on the archiving process, and verified that archiving has started and also verified the location of the archived logs. Making a log switch from one online redo to another doesn't sync the checkpoint_change# with what the controlfile has (controlfile_change# is what is also called a thread checkpoint). Only when we do a manual checkpoint (instead of a database-activated checkpoint) do tho se numbers coincide. They can be verified with the dynamic view v$datafile as shown below: Additional information for troubleshooting archiving issues comes from another dynamic view, V$INSTANCE: The archiver column can also indicate when the ARC process failed to switch logs with an automatic retry in another five minutes. The log_switch_wait will indicate the wait event the log switching process is waiting on—ARCHIVE LOG, CLEAR LOG, or CHECKPOINT. All of the activity associated with log switches and checkpoints will influence database performance. We shall continue now with the further required setup steps to complete all of the tasks.
Read more
  • 0
  • 0
  • 2583

article-image-creating-custom-content-type-paster-plone-3
Packt
20 May 2010
18 min read
Save for later

Creating a Custom Content Type with Paster in Plone 3

Packt
20 May 2010
18 min read
(Further resources on Plone see here.) we have used a graphic application (ArgoUML) to draw a UML model that was automatically transformed by ArchGenXML into an Archetypes-based content type for Plone. In this article, we'll create a content type product with another tool, paster. It's not a graphic application, but it's as easy to use as writing a few characters. We used paster earlier to create a buildout-based Zope instance and an egg-structured Plone product. Here we'll use it to create a full Archetype product, its schema fields, and even the required tests to make sure everything is working as intended Creating an Archetypes product with paster There are several steps to take with paster to produce a full and useful content type. The first one should be the creation of the structure, meaning the product directory organization. Getting ready The final destination of this product, at least at development stage, is the src folder of our buildout directory. There is where we place our packages source code while we are working on them, until they become eggs (to see how to turn them into eggs read Submitting products to an egg repository). Thus go to your buildout directory and then get inside the src folder: cd ./src Make sure you have the latest ZopeSkel installed. ZopeSkel is the name of a Python package with a collection of skeletons and templates to create commonly used Zope and Plone projects via a paster command. easy_install -U ZopeSkel   How to do it… Create a package for the new add-on product: We are going to create a new package called pox.video. The pox prefix is taken from PloneOpenX (the website we are working on) and will be the namespace of our product. paster create -t archetype Fix the main configure.zcml file to prevent errors: Open the just created configure.zcml file in the pox/video folder and comment the internationalization registration like this: <!-- <i18n:registerTranslations directory="locales" /> --> Update the Zope instance with the new product: To let Zope know that there's new code to be used, let's update our instance buildout.cfg file. In the main [buildout] section, modify the eggs and develop parameters like this: [buildout] ... eggs = ... pox.video ... develop = src/pox.video Automatically add the product in a Plone site: We can install our brand new product automatically during buildout. So add a pox.video line inside the [plonesite] part's products parameter: [plonesite] recipe = collective.recipe.plonesite ... products = ... pox.video Rebuild and relaunch the Zope instance: Build your instance and, if you want to, launch it to check that the pox.video product is installed (not strictly necessary though). ./bin/buildout ./bin/instance fg How it works… So far we have a skeleton product, which is composed basically of boilerplate (we will build on it further). However, it has all the necessary code to be installed, which is important. The paster command of Step 1 in How to do it… creates a package using the archetype available template. When run, it will output some informative text and then a short wizard will be started to select some options. The most important are the first five ones: Option Value Enter project name pox.video Expert mode? Choose whatever option you like. Project Title Video Version 1.0 Description Video content type for PloneOpenX website Add whatever you want to the remaining options (if you chose other than easy mode), or just hit Enter to each one. After selecting the last option, you'll get an output like this (a little longer actually): Creating template basic_namespace Creating directory .pox.video Creating template archetype Recursing into +namespace_package+ Recursing into +package+ Recursing into content Recursing into interfaces Recursing into portlets Recursing into profiles Recursing into tests ... The project you just created has local commands. These can be used from within the product. usage: paster COMMAND Commands: addcontent Adds plone content types to your project For more information: paster help COMMAND The first group of lines tells us something about the created directory structure. We have a pox.video (project name) folder, containing a pox (namespace) folder, which contains a video (package) folder, which in turn contains several sub-packages: content, interfaces, portlets, profiles, and tests. In the following sections, we are going to deal with all of them except portlets, which will be tackled in Creating a portlet package, Customizing a new portlet according to our requirements, and Testing portlets. The second group of lines (after the ellipsis) gives us very important information: we can use particular local commands inside our fresh product. More of this in the next section. Step 2 in the preceding procedure is to tell Zope about the new available package. By adding pox.video in the eggs parameter, we add it in Zope's PYTHONPATH. We also have to add the package's location in the develop parameter. If not, the buildout process would try to fetch it from some of the URLs listed in the find-links parameter. During start up, Zope 2 loads (Five does the job actually) configuration files, usually configure.zcml, for all the products and packages inside the folders that are listed in the [instance] section's products parameter. For other Python packages outside those folders, a ZCML slug is required for the product to be loaded. Fortunately, from Plone 3.3 onwards, the ZCML slug is not needed if packages to be installed use z3c.autoinclude, which automatically detects and includes ZCML files. Although we were not aware of that, when we created the pox.video package with paster, z3c.autoinclude was added as an entry point in the setup.py file. Open it in the main pox.video folder to check it: ... setup(name='pox.video', version=version, description="Video content type for PloneOpenX website", ... entry_points=""" # -*- entry_points -*- [z3c.autoinclude.plugin] target = plone """, ... ) For those packages that don't have this feature, we must explicitly insert a reference to the package in the zcml parameter of the [instance] section like we did in Taking advantage of an enhanced interactive Python debugger with ipdb: [instance] ... # If you want to register ZCML slugs for any packages, # list them here. # e.g. zcml = my.package my.other.package zcml = iw.debug There's more… Do not forget to test your changes (paster changes in fact)! Fortunately, paster creates automatically a tests sub-package and a package-level README.txt file with the first part of a test (logging into our website). Feel free to take a look at it, as it is a very good example of doctest. Nevertheless, it really doesn't test too much for the time being. It will be more productive after adding some features to the product. You may find it really useful to read the content types section from the online Plone Developer Manual at http://plone.org/documentation/manual/developer-manual/archetypes. See Also Submitting products to an egg repository Taking advantage of an enhanced interactive Python debugger with ipdb Adding a content type into a product Adding fields to a content type Adding a custom validator to a content type Creating a portlet egg with paster Customizing a new portlet according to our requirements Testing portlets Adding a content type into a product In Creating an Archetypes product with paster, we were able to create a package shell with all the necessary code to install a product, although it was unproductive. We are now going to add some useful functionality by means of, again, our dear paster. Getting ready When we ran paster in Creating an Archetypes product with paster, we highlighted some of its output, copied below: The project you just created has local commands. These can be used from within the product. Paster local commands are available inside the project folder. So let's move inside it: cd ./src/pox.video How to do it… To add a new content type inside the product, run the following command: paster addcontent contenttype How it works… This will run the addcontent paster command with its contenttype template. After a short wizard asking for some options, it will produce all the code we need. Option Value Enter Video Enter contenttype_description FLV video file Enter folderish False Enter global_allow True Enter allow_discussion True/False, whatever - You'll get an output like this: ... Inserting from README.txt_insert into /pox.video/pox/video/README.txt Recursing into content Recursing into interfaces Recursing into profiles Recursing into default Recursing into types If you need more than just one content type in your product, you can run the paster addcontent contenttype command as many times as you want. There's no need to modify, buildout.cfg file, as we have already made all the required changes. If you didn't make these modifications, please refer to Creating an Archetypes product with paster. Open the interface file in ./src/pox.video/pox/video/interface/video.py: from zope import schema from zope.interface import Interface from pox.video import videoMessageFactory as _ class IVideo(Interface): """Description of the Example Type""" # -*- schema definition goes here -*- Empty interfaces, like this one, are called marker interfaces. Although they provide some information (they can be used to associate a class with some functionality as we will see in Using the ZCA to extend a third party product: Collage), they lack attributes and methods information (that is, their promised functionalities), and consequently and worse, they don't document. Interfaces don't exist in Python. However, Zope 3 has incorporated this concept to let components interact easier. All attributes and methods declarations in interfaces are a contract (not a binding one, though) with the external world. For more information about zope.interface, visit http://wiki.zope.org/Interfaces/FrontPage. The new content type class is in the video.py file located in the ./src/pox.vieo/pox/video/content package. Let's go through it and explain its pieces. """Definition of the Video content type """ from zope.interface import implements, directlyProvides from Products.Archetypes import atapi from Products.ATContentTypes.content import base from Products.ATContentTypes.content import schemata from pox.video import videoMessageFactory as _ from pox.video.interfaces import IVideo from pox.video.config import PROJECTNAME All paster-generated content types inherit from basic ATContentTypes, which is good given the large number of products available for them. Check the Products.ATContentTypes package for plenty of good working examples. VideoSchema = schemata.ATContentTypeSchema.copy() + atapi.Schema(( # -*- Your Archetypes field definitions here ... -*- )) Schemas specify the fields available in content types. In our case, the Video content type is a plain copy of ATContentTypeSchema, which already includes all fields necessary to support Dublin Core convention. Dublin Core is supported thanks to the BaseObject and ExtensibleMetadata modules in the Products.Archetypes package. VideoSchema here is the result of the addition (yes, we can actually add schemas) of two other schemas: the aforementioned ATContentTypeSchema and the new empty one created with the atapi.Schema(()) method, which expects a tuple argument (check the double brackets). Up to ZopeSkel 2.16 (paster's package) the storage of title and description fields are changed to AnnotationStorage. This reduces performance and therefore it would be better to change it by removing these lines letting Archetypes deal with regular AttributeStorage: # Set storage on fields copied from ATContentTypeSchema, # making sure # they work well with the python bridge properties. VideoSchema['title'].storage = atapi. AnnotationStorage() VideoSchema['description'].storage = atapi. AnnotationStorage() here are plans to remove this from ZopeSkel, but there's no release date yet for it. After schema definition, we call finalizeATCTSchema to re-order and move some fields inside our schema according to Plone standard. It's advisable to get familiar with its code in the Products.ATContentTypes.content.schema module: schemata.finalizeATCTSchema(VideoSchema, moveDiscussion=False) Once defined its schema the real class is created. As we said earlier, it inherits from base.ATCTContent; this will be changed for our Video content type. class Video(base.ATCTContent): """FLV video file""" implements(IVideo) meta_type = "Video" schema = VideoSchema title = atapi.ATFieldProperty('title') description = atapi.ATFieldProperty('description') # -*- Your ATSchema to Python Property Bridges Here ... -*- atapi.registerType(Video, PROJECTNAME) The first line in our class body specifies that it implements IVideo interface (interfaces/video.py file). then VideoSchema is associated with the class. ATFieldProperty is required to create ATSchema to Python Property bridges. These are recommended for fields of a schema using AnnotationStorage. If you still have title and description fields storage as AnnotationStorage, you should keep these lines. Otherwise you can safely remove them. And finally, the atapi.registerType() call adds all getters and setters to the Video class. This is Archetypes' magic. You define just a schema and Archetypes will automatically create all methods needed to interact with the class. There's more… We do have some more interesting code now, that's why we should be more careful with it and test it. Again, paster has appended several functional tests in the README.txt file, including the creation (as Manager and Contributor users), modification, and deletion of a Video object. Test the product with the following command: ./bin/instance test -s pox.video We'd like to highlight the block of statements regarding the creation of content as a contributor member: Let's logout and then login as 'contributor', a portal member that has the contributor role assigned. >>> browser.getLink('Log out').click() >>> browser.open(portal_url) >>> browser.getControl(name='__ac_name').value = 'contributor' >>> browser.getControl(name='__ac_password').value = default_password >>> browser.getControl(name='submit').click() This contributor member isn't mentioned anywhere inside the test. Nevertheless the login action doesn't fail. How can that be possible if there's no contributor member included by default in the PloneTestCase base class, like default_user or portal_owner? If we check the base.py file inside the tests sub-package of our product, we'll see that the FunctionalTestCase class has a special afterSetUp method, which is called just before the real test begins and registers the contributor member above. Could we have created the user inside the test? Definitely, because test code is a set of Python statements and we can do whatever we want with them. Is it sensible to perform this kind of set up actions inside the test code? Absolutely not. functional tests should be conceived as black-box tests, from the sheer end-user point of view. This means that code inside a functional test shouldn't assume anything about the underlying environment, but behave as if a regular user were acting through the user interface. Anything we need during testing that shouldn’t be done by the user must be placed outside the test code, as in this example. See also Creating an Archetypes product with paster Working with paster generated test suites Zope Functional testing Using the ZCA to extend a third party product: Collage Changing the base class in paster content types All paster-created (non-folderish) content types inherit from the basic ATCTContent class, which comes with ATContentTypeSchema. However, this is a very basic content type: title, description, and some more metadata fields. On top of this, we intend to upload videos to our website, not just text. ATContentTypes are native to Plone and many community developers had released extensions or plugins for them, such as LinguaPlone. That's why it is prudent to stay close to them. We are now going to change the ATCTContent parent class for ATFile to automatically inherit all the benefits, including the file upload field. How to do it… Open the video.py file inside the content sub-package of your product and make these changes. Be aware of commented lines — they can be just removed, but we wanted to keep them here to remark what's going on. Import the base class and interface to be used: from Products.Archetypes import atapi # from Products.ATContentTypes.content import base from Products.ATContentTypes.content import file from Products.ATContentTypes.interface.file import IATFile from Products.ATContentTypes.content import schemata This way we are importing interface and class of the out-of-the-box File content type. Change original schema: # VideoSchema = schemata.ATContentTypeSchema.copy() + # atapi.Schema(( VideoSchema = file.ATFileSchema.copy() + atapi.Schema(( # -*- Your Archetypes field definitions here ... -*- )) Now, our VideoSchema includes File fields. Change the base class and implemented interface: # class Video(base.ATCTContent): class Video(file.ATFile): """ pox Video """ # implements(IVideo) implements(IATFile,IVideo The last step is to change the parent class of Video so that now it inherits from ATFile instead of just ATCTContent. And then we adjust the interfaces this class now implements. Change the view action URL: Open profiles/default/types/Video.xml file and amend the url_expr attribute in View action by adding /view. <?xml version="1.0"?> <object name="Video" meta_type="Factory-based Type Information with dynamic views" i18n_domain="pox.video" action_id="view" category= "object" condition_expr="" url_expr="string:${object_url}/view" visible="True"> <permission value="View" /> </action> ... </object> Tell Plone to use the new action URL in listings: Add a propertiestool.xml file inside the profiles/default folder with this code: <?xml version="1.0"?> <object name="portal_properties" meta_type= "Plone Properties Tool"> <object name="site_properties" meta_type="Plone Property Sheet"> <property name="typesUseViewActionInListings" type= "lines" purge="False"> <element value="Video"/> </property> </object> </object> Relaunch your instance and reinstall the product. By restarting the Zope instance all of the latest changes will be applied: ./bin/instance fg Go to http://localhost:8080/plone/prefs_install_products_form and reinstall the product. Create a new Video object:Inside your Plone site, click on the Add new... drop-down menu and select the Video option. It should look like this. How it works… Since the first creation of the almost empty product (full of boilerplate, though), in Creating an Archetypes product with paster, we haven't tried to use it, except for the tests we have run. We can now say that it has grown up and it's ready to be seen in action. In Steps 1 to 3 above, we changed some of the basics in paster's original class and its schema to inherit all the benefits of another existing content type: ATFile. If you had tried to create a Video content type before Step 4, after saving, you would have been automatically prompted to download the file you just uploaded. Why's that? The reason is we inherited our class from ATFile, which has a special behavior (like ATImage) regarding its URLs. Files and images uploaded to a Plone site (using regular content types) are downloadable via their natural URL. For example, if you browse to http://yoursite.com/document.pdf, you will be asked to download the file. Alternatively, if you want to open the web page with a download link and metadata, you should use http://yoursite.com/document.pdf/view. That's why we had to change the view URL for our content type in Video.xml (Step 4) for users to be able to open an inline video player (as we plan to). All files included in the profiles folder are used by GenericSetup during installation of the product and are to give some information that Python code doesn't provide, such as whether we'll let users post comments inside the content types (allow_discussion). Plone object listings (including search results) tend to create links to contents without the /view suffix. We must explicitly tell Plone that when listing videos, the suffix should be appended to prevent a download attempt. Fortunately, Plone has foreseen this could have happened. Thus there's no need to modify or override every single list. If the content type name is listed in the special typesUseViewActionInListings property, it will work as expected. Plone object listings (including search results) tend to create links to contents without the /view suffix. We must explicitly tell Plone that when listing videos, the suffix should be appended to prevent a download attempt. Fortunately, Plone has foreseen this could have happened. Thus there's no need to modify or override every single list. If the content type name is listed in the special typesUseViewActionInListings property, it will work as expected. Changes in Step 5 will make the site_properties update its typesUseViewActionInListings property. By including purge="False" in <property /> tag, we prevent other existing values (typically File and Image) in the property from being removed.
Read more
  • 0
  • 0
  • 1873

article-image-building-image-slideshow-using-scripty2
Packt
20 May 2010
10 min read
Save for later

Building an Image Slideshow using Scripty2

Packt
20 May 2010
10 min read
In our previous Scripty2 article, we saw the basics of the Scripty2 library, we saw the UI elements available, the fx transitions and some effects. We even build an small example of a image slide effect. This article is going to be a little more complex, just a little, so we are able to build a fully working image slideshow. If you haven't read our previous article, it would be interesting and useful if you do so before continuing with this one. You can find the article here: Scripty2 in Action Well, now we can continue. But first, why don't we take a look at what we are going to build in this article: As we can see in the image we have three main elements. The biggest one will be where the main images are placed, there is also one element where we will make the slide animation to take place. There's also a caption and some descriptive text for the image and, to the right, we have the miniatures slider, clicking on them will make the main image to also slide out and the new one to appear. Seems difficult to achieve? Don't worry, we will make it step by step, so it's very easy to follow. Our main steps are going to be these: First we we will create the html markup and css necessary, so our page looks like the design. Next step will be to create the slide effect for the available images to the right. And our final step will be to make the thumbnail slider to work. Good, enough talking, let's start with the action. Creating the necessary html markup and css We will start by creating an index.html file, with some basic html in it, just like this: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xml_lang="es-ES" lang="es-ES" ><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title>Scripty2</title><link rel="stylesheet" href="css/reset.css" type="text/css" /><link rel="stylesheet" href="css/styles.css" type="text/css" /> </head><body id="article"> <div id="gallery"> </div> <script type="text/javascript" src="js/prototype.s2.min.js"></script> </body></html> Let's take a look at what we have here, first we are including a reset.css file, this time, for a change, we are going to use the Yahoo one, which we can find in this link: http://developer.yahoo.com/yui/3/cssreset/ We will create a folder called css, and a reset.css file inside it, where we will place the yahoo code. Note that we could also link the reset directly from the yahoo site: <link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.1.1/build/cssreset/reset-min.css"> Just below the link to the reset.css file, we find a styles.css file. This file will be the place where we are going to place our own styles. Next we find a div: <div id="gallery"> </div> This will be our placeholder for the entire slideshow gallery. Then one last thing, the link to the Scripty2 library: <script type="text/javascript" src="js/prototype.s2.min.js"></script> Next step will be to add some styles in our styles.css file: html, body{ background-color: #D7D7D7; }#gallery{ font-family: arial; font-size: 12px; width: 470px; height: 265px; background-color: #2D2D2D; border: 1px solid #4F4F4F; margin: 50px auto; position: relative;} Mostly, we are defining a background colour for the page, and then some styles for our gallery div like its width, height, margin and also a background colour. With all this our page will look like the following screenshot: We will need to keep working on this, first in our index.html file, we need a bit more of code: <div id="gallery"> <div id="photos_container"> <img src="./img/image_1.jpg" title="Lorem ipsum" /> <img src="./img/image_1.jpg" title="Lorem ipsum" /> <img src="./img/image_1.jpg" title="Lorem ipsum" /> <img src="./img/image_1.jpg" title="Lorem ipsum" /> </div> <div id="text_container"> <p><strong>Lorem Ipsum</strong><br/>More lorem ipsum but smaller text</p> </div> <div id="thumbnail_container"> <img src="./img/thumbnail_1.jpg" title="Lorem ipsum"/> <img src="./img/thumbnail_1.jpg" title="Lorem ipsum"/> <img src="./img/thumbnail_1.jpg" title="Lorem ipsum"/> <img src="./img/thumbnail_1.jpg" title="Lorem ipsum"/> </div></div> We have placed three more divs inside our main gallery one. One of them would be the photos-photos_container, where we place our big photos. The other two will be one for the text- text_container, and the other for the thumbnail images, that will be thumbnail_container. After we have finished with our html, we need to work with our css. Remember we are going to do it in our styles.css: #photos_container{ width: 452px; height: 247px; background-color: #fff; border: 1px solid #fff; margin-top: 8px; margin-left: 8px; overflow: hidden;}#text_container{ width: 377px; height: 55px; background-color: #000000; color: #ffffff; position: absolute; z-index: 2; bottom: 9px; left: 9px;}#text_container p{ padding: 5px; }#thumbnail_container{ width: 75px; height: 247px; background-color: #000000; position: absolute; z-index: 3; top: 9px; right: 9px;}#thumbnail_container img{ margin: 13px 13px 0px 13px; }strong{ font-weight: bold; } Here we have added styles for each one of our divs, just quite basic styling for the necessary elements, so our page now looks a bit more like the design: Though this looks a bit better than before, it still does nothing and that's going to be our next step. Creating the slide effect First we need some modifications to our html code, this time, though we could use id tags in order to identify elements, we are going to use rel tags. So we can see a different way of doing things. Let's then modify the html: <div id="photos_container"> <img src="./img/image_1.jpg" title="Lorem ipsum" rel="1"/> <img src="./img/image_1.jpg" title="Lorem ipsum" rel="2"/> <img src="./img/image_1.jpg" title="Lorem ipsum" rel="3"/> <img src="./img/image_1.jpg" title="Lorem ipsum" rel="4"/> </div> <div id="text_container"> <p><strong>Lorem Ipsum</strong><br/>More lorem ipsum but smaller text</p> </div> <div id="thumbnail_container"> <img src="./img/thumbnail_1.jpg" title="Lorem ipsum" rel="1"/> <img src="./img/thumbnail_1.jpg" title="Lorem ipsum" rel="2"/> <img src="./img/thumbnail_1.jpg" title="Lorem ipsum" rel="3"/> <img src="./img/thumbnail_1.jpg" title="Lorem ipsum" rel="4"/> </div> Note the difference, we have added rel tags to each one of the images in every one of the divs. Now we are going to add a script after the next line: <script type="text/javascript" src="js/prototype.s2.min.js"></script> The script is going to look like this: <script type="text/javascript"> $$('#thumbnail_container img').each(function(image){ image.observe('click', function(){ $$('#photos_container img[rel="'+this. readAttribute('rel')+'"]').each(function(big_image){ alert(big_image.readAttribute('title')); }) }); });</script> First we select all the images inside the #thumbnail_container div: $$('#thumbnail_container img') Then we use the each function to loop through the results of this selection, and add the click event to them: image.observe('click', function(){ This event will fire a function, that will in turn select the bigger images, the one in which the rel attribute is equal to the rel attribute of the thumbnail: $$('#photos_container img[rel="'+this.readAttribute('rel')+'"]').each(function(big_image){ We know this will return only one value, but as the selected could, theoretically, return more than one value, we need to use the each function again. Note that we use the this.readAttribute('rel') function to read the value of the rel attribute of the thumbnail image. Then we use the alert function to show the title value of the big image: alert(big_image.readAttribute('title')); If we now click on any of the thumbnails, we will get an alert, just like this: We have done this just to check if our code is working and we are able to select the image we want. Now we are going to change this alert for something more interesting. But first, we need to do some modifications to our styles.css file, we will modify our photos container styles: #photos_container{ width: 452px; height: 247px; background-color: #fff; border: 1px solid #fff; margin-top: 8px; margin-left: 8px; overflow: hidden; position: relative;} Only to add the position relate in it, this way we will be able to absolute position the images inside it, adding these styles: #photos_container img{ position: absolute;} With these changes we are done with the styles for now, return to the index.html file, we are going to introduce some modifications here too: <script type="text/javascript" src="js/prototype.s2.min.js"></script> <script type="text/javascript"> var current_image = 1; $$('#photos_container img').each(function(image){ var pos_y = (image.readAttribute('rel') * 247) - 247; image.setStyle({top: pos_y+'px'}); })... I've placed the modifications in bold, so we can concentrate on them. What have we here? We are creating a new variable, current_image, so we can save which is the current active image. At page load this will be the first one, so we are placing 1 to its value. Next we loop through all of the big images, reading its rel attribute, to know which one of the images are we working with. We are multiplying this rel attribute with 247, which is the height of our div. We are also subtracting 247 so the first image is at 0 position. note Just after this, we are using prototype's setStyle function to give each image its proper top value. Now, I'm going to comment one of the css styles: #photos_container{ width: 452px; height: 247px; background-color: #fff; border: 1px solid #fff; margin-top: 8px; margin-left: 8px; //overflow: hidden; position: relative;} You don't need to do this, I' will do it for you, so we can see the result of our previous coding, and then I will turn back and leave it as it was before, prior to continuing. So our page would look like the next image: As we see in the image, all images are one on top of the others, this way we will be able to move them in the y axis. We are going to achieve that by modifying this code: $$('#thumbnail_container img').each(function(image){ image.observe('click', function(){ $$('#photos_container img[rel="'+this. readAttribute('rel')+'"]').each(function(big_image){ alert(big_image.readAttribute('title')); }) }); });
Read more
  • 0
  • 0
  • 10438
article-image-different-types-mapping-nhibernate-2
Packt
19 May 2010
8 min read
Save for later

Different types of Mapping in Nhibernate 2

Packt
19 May 2010
8 min read
(Read more interesting articles on Nhibernate 2 Beginner's Guide here.) What is mapping? Simply put, we need to tell NHibernate about the database that we created and how the fields and tables match up to the properties and classes we created. We need to tell NHibernate how we will be assigning Primary Keys, the data types that we will be using to represent data, what variables we will store them in, and so on. You could say this is one of the most important exercises we will perform in our pursuit of NHibernate. Don't worry though, it's pretty easy. Types of mapping There are two basic ways to map data for NHibernate: the traditional XML mapping in an hbm.xml file, or the newer "Fluent NHibernate" style, which is similar to the interface pattern introduced with the .NET 3.5 framework (see http://www.martinfowler.com/bliki/FluentInterface.html). In both cases, we will create a document for each of our tables. We will map each field from our database to the property we created to display it in our class. XML mapping XML mapping is undoubtedly the most common method of mapping entities with NHibernate. Basically, we create an XML document that contains all of the information about our classes and how it maps to our database tables. These documents have several advantages: They are text files, so they are small They are very readable They use a very small number of tags to describe the data The two biggest complaints about XML mapping is the verbosity of the text and that it is not compiled. We can handle some of the verbosity by limiting the amount of data we put into the document. There are a number of optional parameters that do not absolutely need to be mapped, but that provide additional information about the database that can be included. We'll discuss more about that in the Properties section. You should copy the nhibernate-mapping.xsd and nhibernate-configuration.xsd files from the NHibernate ZIP file into your Visual Studio schemas directory (that is C:Program FilesMicrosoft Visual Studio 9.0Common7Packagesschemasxml). This will give you IntelliSense and validation in the .NET XML editor when editing NHibernate mapping and configuration files. Without compilation, when the database changes or the classes change, it's difficult to detect mismatches until the application is actually executed and NHibernate tries to reconcile the database structure with the mapping classes. While this can be an issue there are a number of ways to mitigate it, such as careful monitoring of changes, writing tests for our persistence layer, using a Visual Studio plugin, or using a code generation tool. Getting started The XML mapping document begins like any XML document, with an XML declaration. No magic here, just a simple xml tag, and two attributes, version and encoding. <?xml version="1.0" encoding="utf-8" ?> The next tag we are going to see in our document is the hibernate-mapping tag. This tag has an attribute named ><hibernate-mapping namespace="BasicWebApplication.Common.DataObjects" assembly="BasicWebApplication"> </hibernate-mapping> These three properties within the hibernate-mapping tag make up the basic XML mapping document. Classes The next tag we need to define in our document is the class tag. This is a KEY tag, because it tells NHibernate two things—the class this mapping document is meant to represent and which table in the database that class should map to. The class tag has two attributes we need to be concerned with—name and table <class name="" table=""> </class> The name attribute contains the fully-qualified POCO (or VB.NET) class that we want to map to, including the assembly name. While this can be specified in the standard fully-qualified dotted class name, a comma, and then the assembly name, the preferred method is to define the namespace and assembly in the <hibernate-mapping> tag, as shown in the previous code. The table attribute specifies the table in the database that this mapping file represents. It can be as simple as the name of the table Address or as complex as needed to adequately describe the table. If you need to include the owner of the table, such as dbo.Address, then you can add the schema attribute as follows: schema="dbo" If we were going to map the Address class in our application to the Address table in the database, then we would use a tag as follows: <class name="Address" table="Address"> </class> Technically, as the table name is the same as our class name, we could leave out the table attribute. Properties We can map properties from our class to fields in the database using the id tag and the property tag. These tags are for the standard fields in the database, not the Foreign Key fields. We'll get to those in a minute. The id and property tags follow a standard pattern and have a number of optional parameters. They follow the basic format of defining the property on the class that they are mapping to and the data type that is used to represent that data. This will generally look as follows: <property name="Address1" type="String"> <column name="Address1" length="255" sql-type="varchar" not-null="true"/> </property> This is the fully-verbose method of mapping the properties, and the one I personally use. If something happens to your database, you can re-generate the database from this information. It's also very helpful when you are troubleshooting because all of the information about the data is right there. Alternately, you can map the property as follows: <property name="Address1" /> Both methods will provide the same mapping to NHibernate, but as I stated earlier, the more verbose method gives you a lot more flexibility. One of the optional attributes that I generally use on the id and property tags is the type attribute. With this attribute I can tell NHibernate that I am using a particular type of data to store that information in my class. Adding this data type, our property tag would look as follows: <property name="Address1" type="String" /> I also like to use the column tag, just to explicitly link the field with the property in the class, but that again is just preference. The previous code is completely adequate. ID columns The first property from our class that we want to map is the Id property. This tag has a number of attributes we can optionally set, but the simplest way we can map the Id property is as follows: <id name="Id"> <generator class="hilo"/> </id> This tells NHibernate that we have a property in our class named Id which maps to a field in the database called Id and also that we use the hilo method to automatically generate a value for this field. Simple enough! An optional attribute that I generally use on the id tag is the unsaved-value attribute. This attribute specifies what value should be returned in a new object before it is persisted (saved) to the database. Adding this attribute, as well as the type attribute we talked about, the code would look as follows: <id name="Id" type="Int32" unsaved-value="null"> <generator class="hilo"/> </id> As long as our field is named Id in the database, we are good to go. But what if it was named id or address_id? This simply wouldn't handle it. In that case, we would have to add the optional column tag to identify it: <id name="Id"> <column name="address_id"/> <generator class="hilo"/> </id> Now we have mapped our address_id field from the database into a more standard Id property on our class. Some of the additional attributes that are commonly used on the column tag are as follows: name: Define the name of the column in the database length: The length of the field, as defined in the database sql-type: The database definition of the column type not-null: Whether or not the database column allows nulls. not-null="true" specifies a required field Again, these optional attributes simply allow you to further define how your database is created. Some people don't even define the database. They just define the hbm.xml files and use the NHibernate.Tool.hbm2ddl to create a SQL script to do this work!
Read more
  • 0
  • 0
  • 5109

article-image-django-12-e-commerce-generating-pdf-reports-python-using-reportlab
Packt
19 May 2010
6 min read
Save for later

Django 1.2 E-commerce: Generating PDF Reports from Python using ReportLab

Packt
19 May 2010
6 min read
(Read more interesting articles on Django 1.2 e-commerce here.) ReportLab is an open source project available at http://www.reportlab.org. It is a very mature tool and includes binaries for several platforms as well as source code. It also contains extension code written in C, so it's relatively fast. It is possible for ReportLab to insert PNG and GIF image files into PDF output, but in order to do so we must have the Python Imaging Library (PIL) installed. We will not require this functionality in this article, but if you need it for a future project, see the PIL documentation for setup instructions. The starting point in the ReportLab API is drawing to canvas objects. Canvas objects are exactly what they sound like: blank slates that are accessible using various drawing commands that paint graphics, images, and words. This is sometimes referred to as a low-level drawing interface because generating output is often tedious. If we were creating anything beyond basic reporting output, we would likely want to build our own framework or set of routines on top of these low-level drawing functions. Drawing to a canvas object is a lot like working with the old LOGO programming language. It has a cursor that we can move around and draw points from one position to another. Mostly, these drawing functions work with two-dimensional (x, y) coordinates to specify starting and ending positions. This two-dimensional coordinate system in ReportLab is different from the typical system used in many graphics applications. It is the standard Cartesian plane, whose origin (x and y coordinates both equal to 0) begins in the lower-left hand corner instead of the typical upper-right hand corner. This coordinate system is used in most mathematics courses, but computer graphics tools, including HTML and CSS layouts, typically use a different coordinate system, where the origin is in the upper-left. ReportLab's low-level interface also includes functions to render text to a canvas. This includes support for different fonts and colors. The text routines we will see, however, may surprise you with their relative crudeness. For example, word-wrapping and other typesetting operations are not automatically implemented. ReportLab includes a more advanced set of routines called PLATYPUS, which can handle page layout and typography. Most low-level drawing tools do not include this functionality by default (hence the name "low-level"). This low-level drawing interface is called pdfgen and is located in the reportlab.pdfgen module. The ReportLab User's Guide includes extensive information about its use and a separate API reference is also available. The ReportLab canvas object is designed to work directly on files. We can create a new canvas from an existing open file object or by simply passing in a file name. The canvas constructor takes as its first argument the filename or an open file object. For example: from reportlab.pdfgen import canvasc = canvas.Canvas("myreport.pdf") Once we obtained a canvas object, we can access the drawing routines as methods on the instance. To draw some text, we can call the drawString method: c.drawString(250, 250, "Ecommerce in Django") This command moves the cursor to coordinates (250, 250) and draws the string "Ecommerce in Django". In addition to drawing strings, the canvas object includes methods to create rectangles, lines, circles, and other shapes. Because PDF was originally designed for printed output, consideration needs to be made for page size. Page size refers to the size of the PDF document if it were to be output to paper. By default, ReportLab uses the A4 standard, but it supports most popular page sizes, including letter, the typical size used in the US. Various page sizes are defined in reportlab.lib.pagesizes. To change this setting for our canvas object, we pass in the pagesize keyword argument to the canvas constructor. from reportlab.lib.pagesizes import letterc = canvas.Canvas('myreport.pdf', pagesize=letter) Because the units passed to our drawing functions, like rect, will vary according to what page size we're using, we can use ReportLab's units module to precisely control the output of our drawing methods. Units are stored in reportlab.lib.units. We can use the inch unit to draw shapes of a specific size: from reportlab.lib.units import inchc.rect(1*inch, 1*inch, 0.5*inch, 1*inch) The above code fragment draws a rectangle, starting one inch from the bottom and one inch from the left of the page, with sides that are length 0.5 inches and one inch, as shown in the following screenshot: Not particularly impressive is it? As you can see, using the low-level library routines require a lot of work to generate very little results. Using these routines directly is tedious. They are certainly useful and required for some tasks. They can also act as building blocks for your own, more sophisticated routines. Building our own library of routines would still be a lot of work. Fortunately ReportLab includes a built-in high-level interface for creating sophisticated report documents quickly. These routines are called PLATYPUS; we mentioned them earlier when talking about typesetting text, but they can do much more. PLATYPUS is an acronym for "Page Layout and Typography Using Scripts". The PLATYPUS code is located in the reportlab.platypus module. It allows us to create some very sophisticated documents suitable for reporting systems in an e-commerce application. Using PLATYPUS means we don't have to worry about things such as page margins, font sizes, and word-wrapping. The bulk of this heavy lifting is taken care of by the high-level routines. We can, if we wish, access the low-level canvas routines. Instead we can build a document from a template object, defining and adding the elements (such as paragraphs, tables, spacers, and images) to the document container. The following example generates a PDF report listing all the products in our Product inventory: from reportlab.platypus.doctemplate import SimpleDocTemplatefrom reportlab.platypus import Paragraph, Spacerfrom reportlab.lib import sytlesdoc = SimpleDocTemplate("products.pdf")Catalog = []header = Paragraph("Product Inventory", styles['Heading1']) Catalog.append(header)style = styles['Normal']for product in Product.objects.all(): for product in Product.objects.all(): p = Paragraph("%s" % product.name, style) Catalog.append(p) s = Spacer(1, 0.25*inch) Catalog.append(s)doc.build(Catalog) The previous code generates a PDF file called products.pdf that contains a header and a list of our product inventory. The output is displayed in the accompanying screenshot.
Read more
  • 0
  • 0
  • 26836
Modal Close icon
Modal Close icon