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

7019 Articles
article-image-custom-types-documentum
Packt
22 Oct 2009
4 min read
Save for later

Custom Types in Documentum

Packt
22 Oct 2009
4 min read
Custom Types Documentum provides a large number of built-in object types that support the functionality of the platform. Some object types are general purpose and can be used for business purposes as well. However, all possible business needs can neither be anticipated nor supported by default. Therefore, Documentum allows creation of new object types, which are called custom types. This article addresses creation and management of custom types. Before reading this article, it would be helpful to know about Objects and Types, since the majority of the concepts pertaining to object types apply here as well. Some concepts are explained here. Managing Custom Types A user-defined object type is called a custom type and the user-defined properties are called custom properties. Properties are also known as attributes. Custom types can be created, modified, and removed as long as certain rules are followed. This section describes the detail around managing custom types. Creating a Custom Type A custom type can be created using Documentum Application Builder (DAB), using Documentum Administrator (DA), or using DQL/API scripts. DAB is the most commonly used application for creating custom types since it fully supports the data dictionary (see Data Dictionary later in this article) and it has a Graphical User Interface (GUI) specifically designed for creating and managing custom types. Further, DAB can also be used for packaging the types into a DocApp. The following screenshot shows the DAB screen for creating and updating a custom type: DA provides basic support for managing custom types. For example, DA does not provide an interface for defining value assistance for a property. The following screenshot shows the screen for creating and updating custom types in DA: Creating a custom type is a privileged operation and only the users with following privileges can do so: Create Type Sysadmin Superuser        The user creating the type becomes the owner of the type. A custom type can extend an existing type through inheritance (see Type Hierarchy in Documentum). A new custom type can have an existing custom type or one of the sets of Documentum object types as its supertype. The most common supertype for a new custom type for representing documents is dm_document. It is also possible to create a custom type without a supertype. Such a type is called a NULL type. Only a user with Superuser privilege can create a NULL type. A NULL type is useful for storing data that does not need the usual object management features such as versioning. There are several built-in types that are NULL types such as dm_user, dm_session, and dm_alias_set. If a custom type is intended to only store non-versionable data, a NULL type may be appropriate for this purpose. Recall that any given type uses up to two tables (one for single-valued properties and one for repeating) of its own for storing non-inherited properties of its objects. There are additional views for retrieving all the properties together. The following key information is needed or captured in DAB when creating a new custom type:   Info Description Name Name of the type. A type name must be unique (caseinsensitive) in the repository and can be up to 27 characterslong. The additional constraints on the type name are that itcannot contain a space or punctuation nor can it be same asany DQL reserved word, such as SELECT or WHERE. Further, it cannot start with dm_, dmi, dmr_, a number, space, or a single quote. It is recommended that a custom prefix be used for custom type names to distinguish them from the other types. Creator The user creating the type. Supertype The supertype of the new type. This can be NULL. Label User-friendly version of the name, for display purposes in Documentum client applications. Default Lifecycle A lifecycle that can be attached to a document of this type, without identifying the lifecycle explicitly. Default Storage Area A storage area identifies where the content files are stored for objects. The default storage area identifies where the content files for objects of this type will be stored by default. Default Permission Set The default permission set is used when the default ACL mode for the Content Server is set to Type. In this case, a new object of this type gets this permission set. Template Document One or more template documents can be created for the type, which are available to users when they are creating a new object of this type. The template documents are stored in the Templates cabinet in Documentum repository.
Read more
  • 0
  • 0
  • 5481

article-image-creating-accessible-tables-joomla
Packt
22 Oct 2009
5 min read
Save for later

Creating Accessible Tables in Joomla!

Packt
22 Oct 2009
5 min read
Creating Accessible Tables Tables got a bad review in accessibility circles, because they used to create complex visual layouts. This was due to the limitations in the support for presentational specifications like CSS and using tables for layout was a hack—that worked in the real world—when you wanted to position something in a precise part of the web page. Tables were designed to present data of all shapes and sizes, and that is really what they should be used for. The Trouble with Tables So what are tables like for screen reader users? Tables often contain a lot of information, so sighted users need to look at the information at the top of the table (the header info), and sometimes the first column in each row to associate each data cell. Obviously this works for sighted users, but in order to make the tables accessible to a screen reader user we need to find a way of associating the data in each cell with its correct header so the screen reader can inform the user which header relates to each data cell. Screen reader users can navigate between data cells easily using the cursor keys. We will see how to make tables accessible in simple steps. There are methods of conveying the meaning and purpose of a table to the screen reader user by using the caption element and the summary attribute of the table element that you will find more on in the next section. We will learn how to build a simple table using Joomla! and the features contained within the WYSIWYG editors that can make the table more accessible. Before we do that though I want you to ask yourself about why you want to use tables (though sometimes it is unavoidable) and what forms should they take. Simple guidelines for tables: Try to make the table as simple as possible.    If possible don't span multiple cells etc. The simpler the table, the easier it is to make accessible.    Try to include the data you want to present in the body text of your site. Time for Action—Create an Accessible Table (Part 1) In the following example we will build a simple table that will list the names of some artists, some albums they have recorded, and the year in which they recorded the albums. First of all click the table icon from the TinyMCE interface and add a table with a suitable number of columns and rows.            By clicking on the Advanced tab you will see the Summary field. The summary information is very important. It provides the screen reader user a summary of the table. For example, I filled in the following text: "A list of some funk artists, my favorite among their records, and the year they recorded it in". My table then looked as follows: What Just Happened? There is still some work to be done in order to make the content more accessible. The controls that the WYSIWYG editor offers are also a little limited so we will have to edit the HTML by hand. Adding the summary information is a very good start. The text that I entered "A list of some funk artists, my favorite among their records, and the year they recorded it in." will be read out by the screen reader as soon as it receives a focus by the user. Time for Action—Create an Accessible Table (Part 2) Next we are going to add a Caption to the table, which will be helpful to both sighted and non-sighted users. This is how it's done. Firstly, select the top row of the table, as these items are the table heading. Then click on the Table Row properties icon beside the Tables icon and select Table Head under General Properties. Make sure that the Update current Row is selected in the dialogue box in the bottom left. You will apply these properties to your selected row. If you wish to add a caption to your table you need to add an extra row to the table and then select the contents of that row and add the Caption in the row properties dialogue box. This will tell the browser to display the caption text, in this case Funky Table Caption, else it will remain hidden. What Just Happened? By adding caption to the table, you provide useful information to the screen reader user. This caption should be informative and should describe something useful about the table. As the caption element is wrapped in a heading it is read out by the screen reader when the user starts exploring the table—so it is slightly different to the summary attribute, which is read out automatically. Does it Work? What we just did using the WYSIWYG editor, TinyMCE, is enough to make a good start towards creating a more accessible table, but we will have to work a little more in order to truly make the table accessible. So we will now edit the HTML. The good news is that you have made some good steps in the right direction and the final step is of associating the data cells with their suitable headers, as this is something that we cannot really do with the WYSIWYG editor alone, and is essential to make your tables truly accessible.
Read more
  • 0
  • 0
  • 2244

article-image-textures-blender
Packt
22 Oct 2009
10 min read
Save for later

Textures in Blender

Packt
22 Oct 2009
10 min read
Procedural Textures vs. Bitmap Textures Blender has basically two types of textures, which are procedural textures and bitmap textures. Each one has both positive and negative points. Which one is the best will depend on your project needs. Procedural: This kind of texture is generated by the software at rendering time, just like vector lines. This means that it won't depend on any type of image file. The best thing about this type of texture is that it is resolution independent, so we can set the texture to be rendered with high resolutions with minimum loss of quality. The negative point about this kind of texture is that it's harder to get realistic textures with it. Bitmap: To use this kind of texture, we will need an image file, such as a JPEG, PNG, or TGA file. The good thing about these textures is that we can achieve very realistic materials with it quickly. On the other hand, we must find the texture file before using it. And there is more. If you are creating a high resolution render, the texture file must be big. Texture Library Do you remember the way we organized materials? We can do exactly the same thing about textures. Besides setting names and storing the Blender files to import and use again later, collecting bitmap textures is another important point. Even if you don't start right away, it's important to know where to look for textures. So here is a small list of websites that provides free texture download. http://www.blender-textures.org http://www.cgtextures.com http://blender-archi.tuxfamily.org/textures Applying Textures To use a texture, we must apply a material to an object, and then use the texture with this material. We always use the texture inside a material. For instance, to make a plane that simulates a marble floor, we have to use a texture and set up how the surface will react to light and texture, which can give the surface a proper look of marble using any texture. To do that, we must use the texture panel, which is located right next to the materials button. We can use a keyboard shortcut to open this panel: just hit F6. There is a way to add a texture in the material panel as well, with a menu called Texture. The best way to get all the options is to add the texture on the texture panel. On this panel, we will be able to see a lot of buttons, which represent the texture channels. Each one of these channels can hold a texture. The final texture will be a mix of all the channels. If we have a texture at channel 1 and another texture at channel 2, these textures will be blended and represented in the material. Before adding a new texture, we must select a channel by clicking over one of them. Usually the first channel is selected, but if you want to use another one, just click on the channel. When the channel is selected, just click the Add New button to add a new texture. The texture controls are very similar to the material controls. We can set a name for the texture at the top, or erase it if we don't want it anymore. With the selector, we can choose a previously created texture too—just click and select. Now comes the fun part. Having added a texture, we have to choose a texture type. To do that, we click on the texture type combo box. There are a lot of textures, but most of them are procedural textures and we won't use them much. The only texture type that isn't procedural is the image type. We can use textures like Clouds and Wood to create some effects and give surfaces a more complex look, or even create a grass texture with some dirt on it. But most times, the texture type that we will be using will be the Image type. Each texture has its own set of parameters to determine how it will look in the object. If we add a Wood texture, it will show the configuration parameters at the right. If we choose as texture type Clouds, the parameters showed at the right will be completely different. With the image texture type it's not different, this kind of texture has its own type of setup. This is the control panel: To show how to set up a texture, let's use an image file that represents a wood floor and a plane. We can apply the texture to this plane and set up how it's going to look, testing all the parameters. The first thing to do is assign a material to the plane, and add a texture to this material. We choose as texture type the Image option. It will show the configuration options for this kind of texture. To apply the image as a texture to the plane, just click on the Load button, situated on the Image menu. When we hit this button, we will be able to select the image file. Locate the image file and the texture will be applied. If we want to have more control over how this texture is organized and placed on the plane, we need to learn how the controls work. Every time you make any changes to the setup of a texture, these changes will be shown in the preview window; use it a lot to make good changes. Here is a list of what some of the buttons can do for the texture: UseAlpha: If the texture has an alpha channel, we have to press this button for Blender calculate the channel. An image has an alpha channel when some kind of transparency is stored in the image. For instance, a .png file with transparent background has an alpha channel. We can use this to create a texture with a logo, for a bottle, or to add an image of a tree or person to a plane. Rot90: With this option we can rotate the texture by 90 degrees. Repeat: Every texture must be distributed on the object surface, and repeating the texture in lines and columns is the default way to do that. Extended: If this button is pressed, the texture will be adjusted to fit all the object surface area. Clip: With this option, the texture will be cropped and we will be able to show only a part of it. To adjust which parts of the texture will be displayed, use the Min/Max X/Y options. Xrepeat / Yrepeat: This option determines how many times a texture is repeated, with the repeat option turned on. Normal Map: If the texture will be used to create Normal Maps, press this button. These are textures used to change the face normals of an object. Still: With this button selected, we can determine that the image used as texture is a still image. This option is marked by default. Movie: If you have to use a movie file as texture, press this button. This is very useful if we need to make something like a theatre projection screen or a tv screen. Sequence: We can use a sequence of images as texture too; just press this button. It works the same ways as with a movie file. There are a few more parameters, like the Reload button. If your texture file suffers any kind of change, we must press this button for the changes get accepted by Blender. The X button can erase this texture; use it if you need to select another image file. When we add a texture to any material, an external link is created with this file. This link can be absolute or relative. When we add a texture called "wood.png", which is located at the root of your main hard disk, like C:, a link to this texture will be created like this: "c:wood.png", so every time you open this file, the software will look for that file at that exact place. This is an absolute link, but we can use a relative link as well. For instance, when we add a texture located in the same folder as our scene, a relative link will be created. Every time we use an absolute link and we have to move the ".blend" file to another computer, the texture file must go with it. To imbue the image file with the .blend, just press the icon of gift package. To save all the textures used in a scene, just access the file menu and use the Pack Data option. It will make all the texture files embedded with the source blend file. Mapping Every time we add a texture to any object, we must choose a mapping type to set up how the texture will be applied to the object. For instance, if we have a wall and apply a wood texture, it must be placed like wallpaper. But for cylindrical or spherical objects, or even walls, we have to set up in a way that makes the texture adaptable to the topology of the surface, to avoid effects such as a stretched texture. To set this up, we use the mapping options, which are located on the Map Input menu. On this menu, we can choose between four basic mapping types which are Cube, Sphere, Flat, and Tube. If you have a wall, choose the option that matches the topology type with the model. In this case, the best choice is the Cube. Another important option here is the UV button, which allows us to use another very powerful type of texturing, based on UV Mapping. Normal Map This is a special and useful type of texture, that can change the normals of surfaces. If we have a floor and a texture of ceramic tiles, the surface can be represented with smaller details of that tiling, using this kind of a map. It's almost like modeling the tiles. But everything is created using just a normal map. To use this kind of texture, we must turn on the Nor button on the Map To menu. When this button is turned on, we can set up the Nor slider to determine the intensity of the normal displacement. It works based on the pixel color of the texture. With white pixels, the normals are not affected, and with black pixels, the normals are fully translated. If you want to optimize the normal mapping, using a special texture is much recommended. Some texture libraries even have this type of normal maps ready for use. They can be called bump maps too. Here is an example of how we can use them. We take a stone texture and a tiled texture with a white background and black lines. The stone texture is applied to the floor, and the tiled texture is used to create a tiling for the floor. The setup for that is really simple. Just apply the texture at a lower channel, and turn off the Col button for this channel. Turn on the Nor button, and this texture will affect only the normals and not the material color. Any image can be used as a normal map, but we will always get better results with a greyscale image prepared to be used as a normal map. Now, just set up the Nor intensity with the slider, and see the render. Turn on positive and turn on negativeSome of the buttons on the Map To menu can be turned on with positive and negative values. For instance, the Nor option can be turned on with one click. If we click on it again, the Nor text will turn yellow. This means that the Nor is inverted with negative values. Some other buttons may present the same option.
Read more
  • 0
  • 0
  • 26810

article-image-digitally-signing-and-verifying-messages-web-services-part-2
Packt
22 Oct 2009
4 min read
Save for later

Digitally Signing and Verifying Messages in Web Services ( part 2 )

Packt
22 Oct 2009
4 min read
Signature Verification by Oracle WSM Oracle Web Services Manager can actually validate the signature in the incoming i.e. request SOAP message. By using Oracle WSM to validate the signature, organizations can actually centralize the policy enforcement and also the public key management. As organizations deploy more web services that are accessed by other divisions and business partners, managing the signature verification process might become tedious, as with each new consumer, the certificate information should be maintained. Oracle WSM can address such issues by centralizing those operations. This section  will describe how to configure Oracle WSM policy to validate the signature of the SOAP request message. In order to view the policy, you can click on Policy Management and then Manage Policies. This will bring you to the screen with the gateway information and a hyperlink for policies (see the following screen capture).   You can then click on Policies to see all the policies and you will see theVerifyAndSign policy too that is created by default. A default policy is attached to the service. We can now click Edit to edit the  policy. When you click Edit, you will see the policy steps as shown in the  following screenshot. In this section, we want to configure the Request pipeline to validate the signature of the incoming SOAP message. In order to validate the signature, click Add Step Below to add the Verify Signature policy step as shown in the following screenshot. Once you click OK, the verify signature policy step is added, but that policy step should be configured. If you click on the Configure button on the verify signature policy step, it will take you to the screen where you can configure the verify signature policy information as shown in the following screen capture. In the previous screenshot, I configured Verify Signature policy steps with: Location of the key store Key store type as PKCS12 Password of the key store Public key alias in the key store Set Remove Signatures to true to remove the digital signature after the signature validation Enforce Signing is set to true to make sure that the incoming requests are signed In order to generate a PKCS12 key store from certifcate that is installed already in Microsoft certifcate services, you should frst export the certifcate (with or without private key) and then import that certifcate in FireFox (Advanced option) and then export back to PKCS12. Once the verify signature policy has been configured and saved (Commit Policy), the policy would enforce that any request for the time service with the particular service ID be digitally signed. Signature Generation by Oracle WSM In the last section, we discussed how to digitally sign a web service request by Microsoft .NET application and how to validate the signature by Oracle WSM. In this section, we will discuss how to digitally sign the web service response message. In the earlier section, we discussed how to register the service and how to attach the verify signature policy step to the request pipeline. In order to digitally sign the response message, the response pipeline of the policy should be modified to include the sign message policy step. The policy with the request pipeline that is already configured to verify signature would look like: Now we have to add the step in the Response pipeline to actually sign the response message. In order to add the policy step, click on Add Step Below and then select the Sign Message policy step. Once the Sign Message policy step is added, it can then be configured, as shown in the following screenshot, to include the appropriate key store location for the public key to digitally sign the message. In the previous figure, the location of the key store that has the private key, along with the Keystore password, alias and part of message to be signed are specified. Once the policy is created, it would look like: In the previous screenshot, the Response pipeline has two log steps—one to log the message before digitally signing and one to log the message after digitally signing the message. In this sample, we are using the same WSEQuickStartServer certificate to sign the message. Once the policy is saved, the response message will be digitally signed. The client application (Microsoft .NET) can be configured to validate the signature.
Read more
  • 0
  • 0
  • 1866

article-image-resource-oriented-clients-rest-principles
Packt
22 Oct 2009
8 min read
Save for later

Resource-Oriented Clients with REST Principles

Packt
22 Oct 2009
8 min read
Designing Clients While designing the library service, the ultimate outcome was the mapping of business operations to URIs and HTTP verbs. The client design is governed by this mapping. Prior to service design, the problem statement was analyzed. For consuming the service and invoking the business operations of the service using clients, there needs to be some understanding of how the service intends to solve the problem. In other words, the service, by design, has already solved the problem. However, the semantics of the solution provided by the service needs to be understood by the developers implementing the clients. The semantics of the service is usually documented in terms of business operations and the relationships between those operations. And sometimes, the semantics are obvious. As an example, in the library system, a member returning a book must have already borrowed that book. Theborrow book operation precedes the return book operation. Client design must take these semantics into account. Resource Design Following is the URI and HTTP verb mapping for business operations of the library system: URI HTTP Method Collection Operation Business Operation /book GET books retrieve Get books /book POST books create Add book(s) /book/{book_id} GET books retrieve Get book data /member GET members retrieve Get members /member POST members create Add member(s) /member/{member_id} GET members retrieve Get member data /member/{member_id}/books GET members retrieve Get member borrowings /member/{member_id}/books/{book_id} POST members create Borrow book /member/{member_id}/books/{book_id} DELETE members delete Return book   When it comes to client design, the resource design is given, and is an input to the client design. When it comes to implementing clients, we have to adhere to the design given to us by the service designer. In this example, we designed the API given in the above table, so we are already familiar with the API. Sometimes, you may have to use an API designed by someone else, hence you would have to ensure that you have access to information such as: Resource URI formats HTTP methods involved with each resource URI The resource collection that is associated with the URI The nature of the operation to be executed combining the URI and the HTTP verb The business operation that maps the resource operation to the real world context Looking into the above resource design table, we can identify two resources, book and member. And we could understand some of the semantics associated with the business operations of the resources. Create, retrieve books Create, retrieve members Borrow book, list borrowed books and return book Book ID and member ID could be used to invoke operations specific to a particular book or member instance System Implementation In this section, we will use the techniques on client programming to consume the library service. These techniques include: Building requests using XML Sending requests with correct HTTP verbs using an HTTP client library like CURL Receiving XML responses and processing the received responses to extract information that we require from the response Retrieving Resource Information Here is the PHP source code to retrieve book information. <?php$url = 'http://localhost/rest/04/library/book.php';$client = curl_init($url);curl_setopt($client, CURLOPT_RETURNTRANSFER, 1);$response = curl_exec($client);curl_close($client);$xml = simplexml_load_string($response);foreach ($xml->book as $book) { echo "$book->id, $book->name, $book->author, $book->isbn <br/>n";}?> The output generated is shown below As per the service design, all that is required is to send a GET request to the URL of the book resource. And as per the service semantics, we are expecting the response to be something similar to: <books> <book> <id>1</id> <name>Book1</name> <author>Auth1</author> <isbn>ISBN0001</isbn> </book> <book> <id>2</id> <name>Book2</name> <author>Auth2</author> <isbn>ISBN0002</isbn> </book></books> So in the client, we convert the response to an XML tree. $xml = simplexml_load_string($response); And generate the output that we desire from the client. In this case we print all the books. foreach ($xml->book as $book) { echo "$book->id, $book->name, $book->author, $book->isbn <br/>n";} The output is: 1, Book1, Auth1, ISBN0001 2, Book2, Auth2, ISBN0002 Similarly, we could retrieve all the members with the following PHP script. <?php$url = 'http://localhost/rest/04/library/member.php';$client = curl_init($url);curl_setopt($client, CURLOPT_RETURNTRANSFER, 1);$response = curl_exec($client);curl_close($client);$xml = simplexml_load_string($response);foreach ($xml->member as $member) { echo "$member->id, $member->first_name, $member->last_name <br/>n";}?> Next, retrieving books borrowed by a member. <?php$url = 'http://localhost/rest/04/library/member.php/1/books';$client = curl_init($url);curl_setopt($client, CURLOPT_RETURNTRANSFER, 1);$response = curl_exec($client);curl_close($client);$xml = simplexml_load_string($response);foreach ($xml->book as $book) { echo "$book->id, $book->name, $book->author, $book->isbn <br/>n";}?> Here we are retrieving the books borrowed by member with ID 1. Only the URL differs, the rest of the logic is the same. Creating Resources Books, members, and borrowings could be created using POST operations, as per the service design. The following PHP script creates new book. <?php$url = 'http://localhost/rest/04/library/book.php';$data = <<<XML<books> <book><name>Book3</name><author>Auth3</author><isbn>ISBN0003</isbn></book> <book><name>Book4</name><author>Auth4</author><isbn>ISBN0004</isbn></book></books>XML;$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_POSTFIELDS, $data);$response = curl_exec($ch);curl_close($ch);echo $response;?> When data is sent with POST verb to the URI of the book resource, the posted data would be used to create resource instances. Note that, in order to figure out the format of the XML message to be used, you have to look into the service operation documentation. This is where the knowledge on service semantics comes into play. Next is the PHP script to create members. <?php$url = 'http://localhost/rest/04/library/member.php';$data = <<<XML<members><member><first_name>Sam</first_name><last_name>Noel</last_name></member></members>XML;$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_POSTFIELDS, $data);$response = curl_exec($ch);curl_close($ch);echo $response;?> This script is very similar to the script that creates books. Only differences are the endpoint address and the XML payload used. The endpoint address refers to the location where the service is located. In the above script the endpoint address of the service is: $url = 'http://localhost/rest/04/library/member.php'; Next, borrowing a book can be done by posting to the member URI with the ID of the member borrowing the book, and the ID of the book being borrowed. <?php$url = 'http://localhost/rest/04/library/member.php/1/books/2';$data = <<<XMLXML;$ch = curl_init();curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_POSTFIELDS, $data);$response = curl_exec($ch);curl_close($ch);echo $response;?> Note that, in the above sample, we are not posting any data to the URI. Hence the XML payload is empty: $data = <<<XMLXML; As per the REST architectural principles, we just send a POST request with all resource information on the URI itself. In this example, member with ID 1 is borrowing the book with ID 2. $url = 'http://localhost/rest/04/library/member.php/1/books/2'; One of the things to be noted in the client scripts is that we have used hard coded URLs and parameter values. When you are using these scripts with an application that uses a Web-based user interface, those hard coded values need to be parameterized. And we send a POST request to this URL: curl_setopt($ch, CURLOPT_URL, $url);curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);curl_setopt($ch, CURLOPT_POST, true);curl_setopt($ch, CURLOPT_POSTFIELDS, $data); Note that, even though the XML payload that we are sending to the service is empty, we still have to set the CURLOPT_POSTFIELDS option for CURL. This is because we have set CURLOPT_POST to true and the CRUL library mandates setting POST field option even when it is empty. This script would cause a book borrowing to be created on the server side. When the member.php script receives a request with the from /{member_id}/books/{book_id} with HTTP verb POST, it maps the request to borrow book business operation. So, the URL $url = 'http://localhost/rest/04/library/member.php/1/books/2'; means that member with ID 1 is borrowing the book with ID 2.
Read more
  • 0
  • 0
  • 3580

article-image-python-ldap-applications-part-1-installing-and-configuring-python-ldap-library-and-bin
Packt
22 Oct 2009
16 min read
Save for later

Configuring and securing PYTHON LDAP Applications Part 1

Packt
22 Oct 2009
16 min read
This article mini-series by Matt Butcher will look at the Python application programmers interface (API) for the LDAP libraries, and using this API, we will connect to our OpenLDAP server and manipulate the directory information tree. More specifically, we will cover the following in this article series: Installing and configuring the Python-LDAP library. Binding to an LDAP directory. Comparing attributes between the client and server. Performing searches on the directory. Modifying the directory information tree with add, delete, and modify operations. Modifying directory passwords. Working with LDAP schemas. This first part will deal with installation and configuration of the Python-LDAP library. We will then see how the binding operation is performed. Installing Python-LDAP There are a couple of LDAP libraries available for Python, but the most popular is the Python-LDAP module, which (as with the PHP API) uses the OpenLDAP C library as a base for providing network access to an LDAP server. Like OpenLDAP, the Python-LDAP API is Open Source. It works on Linux, Windows, Mac OS X, BSD, and probably other UNIX operating systems as well (platforms that have both Python and OpenLDAP available). The source code is available at the official Python-LDAP website: http://python-ldap.sourceforge.net. Here pre-compiled binaries for many platforms are available, but we will install the version in the Ubuntu repository. Before installing Python-LDAP, you will need to have the Python scripting language installed. Typically, this is installed by default on Ubuntu (and on most flavors of Linux). Installing Python-LDAP requires only one command: $ sudo apt-get install python-ldap This will choose the module or modules that match the installed Python version. That is, if you are running Python 2.4 (the stable version, at the time of writing), this will install the python2.4-ldap package. The library, which consists of several Python packages, will be installed into /usr/lib/python2.4/site-packages/. In Ubuntu, there is no need to run further configuration in order to make use of the Python-LDAP library. We are ready to dive into the API. If you install by hand, either from source or from the binary packages, you may need to add the Python-LDAP library to your Python path. See the Python documentation for details. The Python-LDAP API is well documented. The documentation is available online at the official Python-LDAP website: http://python-ldap.sourceforge.net/docs.shtml. You may find it more convenient to download a copy of the documentation and use it locally. In previous versions of Ubuntu Python-LDAP documentation was available in the package python-ldap-doc, which could be installed with apt-get. Also, many of the Python-LDAP functions and objects have documentation strings that can be accessed from the Python interpreter like this: >>> print ldap.initialize.__doc__ Return LDAPObject instance by opening LDAP connection to LDAP host specified by LDAP URL Parameters: uri LDAP URL containing at least connection scheme and hostport, e.g. ldap://localhost:389 trace_level If non-zero a trace output of LDAP calls is generated. trace_file File object where to write the trace output to. Default is to use stdout. The documentation string usually contains a brief description of the function or object, and is a useful quick reference. A Quick Overview of the Python LDAP API Now that the package is installed, let's take a quick look at what was installed. The Python-LDAP package comes with nine different modules: ldap: This is the main LDAP module. It contains the functions  necessary for performing LDAP operations, such as binding, searching,  adding, and modifying. ldap.async: Python can do synchronous and asynchronous transactions.  This module provides utilities that are useful when performing asynchronous  operations. ldap.cidict: This contains the cidict class, which is a case-insensitive  dictionary. Although LDAP is case-insensitive when it comes to attribute  names, it is often necessary to perform case-insensitive operations on  dictionary keys. ldap.modlist: Utility functions for creating modification records (for  performing the LDAP modify operation) are in this package. ldap.filter: This module provides a couple of utility functions for  creating LDAP search filters. ldap.sasl: Python-LDAP's SASL support is partially contained in this  package. It is not documented in the online documentation, but there are  plenty of notes in the doc strings in this module. ldap.schema: This module contains classes that describe the subschema  subentry records. It can be used to access schema information. ldapurl: This module provides a class for generating and parsing LDAP  URLs. ldif: This module is used to parse or write LDIF-formatted LDAP records. Most of the commonly used LDAP features are in the ldap module, and we will be focused mainly on using that. Since many of the submodules have only a couple of functions, we will use them in passing but treat them as separate objects of discussion. A Note on the Python Examples The Python interpreter (python) can be run interactively. Running Python in an interactive mode can be very useful for discovery and debugging. Further, since it prints useful information directly to the console, it can be useful for demonstration purposes. In many of the examples below, the code is shown as it would be entered in the interactive shell. Here is an example: >>> h = "Hello World">>> h'Hello World'>>> print hHello World Lines that begin with >>> and ... are interpreter prompts (similar to $ in shell). Examples with the >>> are run in the interpreter interactively. Some code, however, will be typed into a file (as usual). This code will not have lines beginning with the interpreter prompt. They tend to look more like this: h = “Hello World”print h Most of the time, features are introduced using the interpreter, but lengthier examples are done in the form of a Python script. Where it might be confusing, I will explicitly say in the text which of the two methods I am using. Connecting and Binding to the Directory Now that we have the library installed, we are ready to use the API. The Python-LDAP API connects and binds in two stages. Initializing the LDAP system is done with the ldap.initialize() function. The initialize() method returns an LDAPObject object, which contains methods for performing LDAP operations and retrieving information about the LDAP connection and transactions. A basic initialization is done like this: >>> import ldap>>> con = ldap.initialize('ldap://localhost') The first line of this example imports the ldap module, that contains the initialize() method as well as the LDAPObject that we will make frequent use of. The second line initializes the LDAP code, and returns an LDAPObject that we will use to connect to the server. The initialize() function takes a simple LDAP URL (protocol://host:port) as a parameter. Sometimes, you may prefer to pass in simply host and port information. This can be done with the connect(host, port) function, that also returns an LDAPObject object. In addition, if you need to check or set any LDAP options, you should use the get_option() and set_option() functions before binding. For instance, we can set the connection to require a TLS certificate by setting the OPT_X_TLS_DEMAND option: >>> con.get_option(ldap.OPT_X_TLS_DEMAND)0>>> con.set_option(ldap.OPT_X_TLS_DEMAND, True)>>> con.get_option(ldap.OPT_X_TLS_DEMAND)1 A Safe Connection In most production environments, security is a major concern. As we have seen in previous chapters, one major component of security in network-based LDAP services is the use of SSL/TLS-based connections. There are two ways to get transport-layer security with the Python-LDAP module. The first is to connect to the LDAPS (LDAP over SSL) port. This is done by passing the correct parameter to the initialize() function. Instead of using the ldap:// protocol, which will make an unverified unencrypted connection to port 389, use an ldaps:// protocol, which will make an SSL connection to port 636 (you can specify alternate an alternate port by appending a colon (:) and then the port number to the end of the URL). Or, instead of using LDAPS, you can perform a Start TLS operation before binding to the server: >>> import ldap>>> con = ldap.initialize('ldap://localhost')>>> con.start_tls_s() Note that while the call to ldap.initialize() does not actually open a connection, the call to ldap.start_tls_s() does create a connection. Exceptions Connecting to an LDAP server may result in the raising of an exception, so in production code, it is best to wrap the connection attempt inside of a try/except block. Here is a fragment of a script: #!/usr/bin/env pythonimport ldap, sysserver = 'ldap://localhost'l = ldap.initialize(server)try: l.start_tls_s()except ldap.LDAPError, e: print e.message['info'] if type(e.message) == dict and e.message.has_key('desc'): print e.message['desc'] else: print e sys.exit() In the case above, if the start_tls_s() method results in an error, it will be caught. The except clause checks if the returned message is a dict (which it should always be), and also checks if it has the description ('desc') field. If so, it prints the description. Otherwise, it prints the entire message. There are a few dozen exceptions that the Python-LDAP library might raise, but all of them are subclasses of the LDAPError class, and can be caught by the line: except ldap.LDAPError, e: Within an LDAPError object, there is a dictionary, called message, which contains the 'info' and 'desc' fields. The 'info' field contains the information returned from the server, and the 'desc' field contains a description of the error. In general, it is best to use try/except blocks around LDAP operations in order to catch any errors that might occur during processing. Binding Once we have an LDAPObject instance, we can bind to the LDAP directory. The Python-LDAP API supports both simple and SASL binding methods, and there are five different bind methods: bind(): Takes three required parameters: a DN, a password (or credential, for SASL), and a string indicating what type of bind method to use. Currently, only ldap.AUTH_SIMPLE is supported. This is asynchronous. Example: con.bind(dn, pw, ldap.AUTH_SIMPLE) bind_s(): This one is same as above, but it is synchronous, and returns  information about the status of the bind. simple_bind(): This performs a simple bind. This has two optional  parameters: DN and password. If no parameter is specified, this will bind as  anonymous. This is asynchronous. simple_bind_s(): This is the synchronous version of the above. sasl_interactive_bind_s(): This performs an SASL bind, and it takes two parameters: an SASL identifier and an SASL authentication string. First, for many Python LDAP functions, including almost all of the LDAP operations, there are both synchronous and asynchronous versions. Synchronous versions, which will block until the server returns a result, have method names that end with _s. The other operations – those that do not end with _s – are asynchronous. An asynchronous message will begin an operation, and then return control to the program. The operation will continue in the background. It is the responsibility of the program to periodically check on the operation to see if it has been completed. Since they wait to return any results until the operation has been completed, synchronous methods will often have different return values than their asynchronous counterparts. Synchronized methods may return the results obtained from the server, or they may have void returns. Asynchronous methods, on the other hand, will always return a message identifier. This identifier can be used to access the results of the operation. Here's an example of the different results for the two different forms of simple bind. First, the synchronous bind: >>> dn = "uid=matt,ou=users,dc=example,dc=com">>> pw = "secret">>> con.simple_bind_s( dn, pw ) (97, [])>>> Notice that this method returns a tuple. Now, look at the asynchronous version: >>> con.simple_bind( dn, pw )8>>> con.result(8)(97, []) In this case, the simple_bind() method returned 8 – the message identification number for the result. We can use the result() method to fetch the resulting information. The result() method returns a two-item tuple, where the first item is the status code (97 means success), and the second is a list of messages from the server. In this case, the list is empty. Notes on Getting ResultsThere are two noteworthy caveats about fetching results. First, a particular result can only be fetched once. You cannot call result() with the same message ID multiple times. Second, you can execute multiple asynchronous operations without checking the results. The consequence of doing this is that all of the results will be stored until they are fetched. This consumes memory, and can lead to confusing results if result() or result( ldap.RES_ANY ) is called. Later in this chapter, we will see more sophisticated uses of synchronous and asynchronous methods, but for now we will continue looking at methods of binding. The bind() and bind_s() methods work the same way, but they require a third parameter, specifying which sort of authentication mechanism to use. Unfortunately, at the time of this writing, only the AUTH_SIMPLE form of binding (plain old simple bind) is supported by this mechanism: >>> con.bind_s( dn, pw, ldap.AUTH_SIMPLE ) (97, []) This performs a simple bind to the server. Exceptions A bind can fail for a number of reasons, the most common being that the connection failed (the CONNECT_ERROR exception) or authentication failed (INVALID_CREDENTIALS). In production code, it is a good idea to check for these exceptions using try/except blocks. By checking for them separately, you can distinguish between, say, authentication failures and other, more serious failures: l = ldap.initialize(server)try: #l.start_tls_s() l.bind_s(user_dn, user_pw)except ldap.INVALID_CREDENTIALS: print "Your username or password is incorrect." sys.exit()except ldap.LDAPError, e: if type(e.message) == dict and e.message.has_key('desc'): print e.message['desc'] else: print e sys.exit() In this case, if the failure is due to the user entering the wrong DN or password, a message to that effect is printed. Otherwise, the error description provided by the LDAP library is printed. SASL Interactive Binds SASL is a robust authentication mechanism, but the flexibility and adaptability of SASL comes at the cost of additional complexity. This additional complexity is evident in the Python-LDAP module. SASL binding is implemented differently than the other bind methods. First, there is no asynchronous version of the SASL bind method (not all thread safety issues have been worked out in this module, yet). Since the SASL code is not as stable as the rest of the API, you may want to stick to simple binding (with SSL/TLS protection) rather than rely upon SASL support. There is only one SASL binding method, sasl_interactive_bind_s(). This method takes two arguments. The first is a DN string. It is almost always left blank, since with SASL, we usually authenticate with some other identifier. The second argument is an sasl object (or a subclass of an sasl object). The sasl object contains a dictionary of information that the SASL subsystem uses to perform authentication. Each different SASL mechanism is implemented as a class that is a subclass of the sasl object. There are a handful of different subclasses that come with the Python-LDAP module, though you can create your own if you need support for a different mechanism. cram_md5: This class implements the CRAM-MD5 SASL mechanism. A new cram_md5 object can be created with a constructor that passes in the authentication ID, a password, and an optional authorization ID. digest_md5: This implements the DIGEST-MD5 SASL mechanism. Like  cram_md5(), this object can be constructed with an authentication ID, a  password, and an optional authorization ID. gssapi: This implements the GSSAPI mechanism, an its constructor has only the optional authorization ID. It is used to perform Kerberos V authentication. external: This implements the EXTERNAL SASL mechanism, that uses an underlying transport security mechanism (like SSL/TLS). Its constructor only takes the optional authorization ID. Our LDAP server is configured to allow DIGEST-MD5 SASL connections, so we will walk through an example of performing this sort of SASL authentication. >>> import ldap>>> import ldap.sasl>>> user_name = "matt">>> pw = "secret">>> >>> con = ldap.initialize("ldap://localhost")>>> auth_tokens = ldap.sasl.digest_md5( user_name, pw )>>> >>> con.sasl_interactive_bind_s( "", auth_tokens )0 To begin with, we import the ldap and ldap.sasl packages, and we store the user name and password information in a couple of variables. After initializing a connection, we need to create a new sasl object – on that will contain the information necessary to perform DIGEST-MD5 authentication. We do this by constructing a new digest_md5 object: >>> auth_tokens = ldap.sasl.digest_md5( user_name, pw ) Now, auth_tokens points to our new SASL object. Next, we need to bind. This is done with the sasl_interactive_bind_s() method of the LDAPObject: >>> con.sasl_interactive_bind_s( "", auth_tokens ) If a SASL interactive bind is successful, then this method will return an integer. Otherwise, an INVALID_CREDENTIALS exception will be raised: >>> auth_tokens = ldap.sasl.digest_md5( "foo", pw )>>> try:... con.sasl_interactive_bind_s( "", auth_tokens )... except ldap.INVALID_CREDENTIALS, e :... print e... {'info': 'SASL(-13): user not found: no secret in database', 'desc': 'Invalid credentials'} In this case, the user foo was not found in the SASL DB, and the SASL subsystem returned an error.
Read more
  • 1
  • 0
  • 34578
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 $19.99/month. Cancel anytime
article-image-identifying-key-elements-joomla-template-design
Packt
22 Oct 2009
6 min read
Save for later

Identifying Key Elements for Joomla! Template Design

Packt
22 Oct 2009
6 min read
The Joomla! Template When you install Joomla!, it comes with one or two built-in templates. In my version 1.0.8 installation, MadeYourWeb by Mark Hinse and rhuk_solarflare_ii by rhuk, are the two available. If you have a different version, you may have different templates available to you. We'll use the rhuk_solarflare_ii template to review the basic parts of a Joomla! template that you'll need to think about as you create your visual design. First, let's look at the following figure to see how our basic template affects the Joomla! PHP output: What Your XHTML does to the template layout. You'll recall that the PHP code for the footer, sitename, pathway, and MainBody are not module position slots. These functions load in the required information that helps Joomla! to run, display standard footer information, and load the actual site content from the Joomla! MySQL databases. Top, left, and right are module position slots, which can be assigned site modules. Site modules are what contain navigation links, form elements, and Joomla! status information that will be displayed to your visitors such as: Who's Online or Who's Logged In. You can assign site modules to any of the module position slots and even load multiple site modules into these position slots by assigning an ascending numerical order to them. You do this in the Module Manager [Site] by going to Modules | Site Modules in the administration panel. Site Modules panel in Joomla!'s admin panel. As shown in the following figure, you can assign up to 50 module position slots to place in your template layout. Go to Site | Template Manager | Module Positions to view the standard module positions Joomla! provides. Module Positions panel in Joomla's admin panel. Now that we have a deeper understanding of how the template, module position slots, and site modules work, let's take a look at how these three elements come together through the rhuk_solar_flare_ii template. The module position slot name is on the left, the content module name is on the right, and the assigned order, if any, is underneath. Example of modules assigned to Module Positions Using this example, you can now start thinking of how you're going to construct your template design. Let's move on to creating your design. Considerations to be Made First off, let's get to the most important consideration What modules will be used in your site? Thus, what modules do you need to design for? Go through your Joomla! installation and review all the modules your site will be using. There's the obvious top menu, main menu, and user menus, but will you be displaying the login form or a poll? If so, do you want to change their display? Will your site be displaying banners? Will your site require any special or add-on modules or components such as an image gallery or shopping cart? Make a list of each module or special component that your site will be displaying and take special note of their elements: Do they have headers or special text areas? Would you like anything to be highlighted with a background image? Do the modules have items that should be standard buttons or icons? All these things should be included in your list. When you begin work on your design in Photoshop, you'll want to compare your mock-up against your module checklist and make sure you've designed for all your modules. Refining the Wheel The next consideration is whether you are going to work from an existing template or from scratch? The more you work with Joomla! and learn all its quirks, the more you'll see that sometimes starting from scratch is best. However, while being a CSS and XHTML “wiz” is awesome, you don't always need to reinvent the wheel! Take a look at what happens to the standard rhuk template when all we do is change the color scheme and fonts. rhuk_solarflare_ii template with CSS changes to color and fonts Now, check out what happens in the following figure when we change the graphics. rhuk_solarflare_ii template with image changes And last, see what happens in the following figure when we use the Module Manager to swap module placements around. rhuk_solarflare_ii template with module swaps By thinking of this design in terms of leveraging the existing rhuk_solarflar_ii template, we effectively created a whole new template and module layout which is completely unique. And we only had to minimally edit the CSS to get it to work. Everything else was done in the Joomla! admin panel without touching any code. If you're going to work from an existing template, it's best to review that template's HTML output (right-click or Alt-click and chose View Source) and pull the image names from each page that you'll be replacing with your own images. It's also helpful to go through that template's image directory and just note each image: which ones you're going to change, leave alone, re-size, and so on as you work with your design mock-up. Make sure to note the specific file names that are going to be overwritten in your module check list so that you have them handy when it is time to export your image slices. So, when is it best to start from scratch? It's up to your site's specific needs. For instance, the Joomla! in-built templates comes with use tables to hold their layout structure together. If you want an all semantic, valid XHTML markup with CSS layout, you'll need to create it yourself from scratch. Whichever road you take, as you continue to design and build Joomla! templates, you'll find over time that you have your own “master” template—files you've generated or got to know so well—you understand how all their parts work together. You'll see how applying any new modules or components will affect the files and how they should be incorporated. It will become easy for you to work with this favorite or “master” template and easily massage it into any new creation you can imagine.  
Read more
  • 0
  • 0
  • 1756

Packt
22 Oct 2009
8 min read
Save for later

Working with Rails – ActiveRecord, Migrations, Models, Scaffolding, and Database Completion

Packt
22 Oct 2009
8 min read
ActiveRecord, Migrations, and Models ActiveRecord is the ORM layer (see the section Connecting Rails to a Database in the previous article) used in Rails. It is used by controllers as a proxy to the database tables. What's really great about this is that it protects you against having to code SQL. Writing SQL is one of the least desirable aspects of developing with other web-centric languages (like PHP): having to manually build SQL statements, remembering to correctly escape quotes, and creating labyrinthine join statements to pull data from multiple tables. ActiveRecord does away with all of that (most of the time), instead presenting database tables through classes (a class which wraps around a database table is called a model) and instances of those classes (model instances). The best way to illustrate the beauty of ActiveRecord is to start using it. Model == Table The base concept in ActiveRecord is the model. Each model class is stored in the app/models directory inside your application, in its own file. So, if you have a model called Person, the file holding that model is in app/models/person.rb, and the class for that model, defined in that file, is called Person. Each model will usually correspond to a table in the database. The name of the database table is, by convention, the pluralized (in the English language), lower-case form of the model's class name. In the case of our Intranet application, the models are organized as follows: Table Model class File containing class definition (in app/models) people Person person.rb companies Company company.rb addresses Address address.rb We haven't built any of these yet, but we will shortly. Which Comes First: The Model or The Table? To get going with our application, we need to generate the tables to store data into, as shown in the previous section. It used to be at this point where we would reach for a MySQL client, and create the database tables using a SQL script. (This is typically how you would code a database for a PHP application.) However, things have moved on in the Rails world. The Rails developers came up with a pretty good (not perfect, but pretty good) mechanism for generating databases without the need for SQL: it's called migrations, and is a part of ActiveRecord. Migrations enable a developer to generate a database structure using a series of Ruby script files (each of which is an individual migration) to define database operations. The "operations" part of that last sentence is important: migrations are not just for creating tables, but also for dropping tables, altering them, and even adding data to them. It is this multi-faceted aspect of migrations which makes them useful, as they can effectively be used to version a database (in much the same way as Subversion can be used to version code). A team of developers can use migrations to keep their databases in sync: when a change to the database is made by one of the team and coded into a migration, the other developers can apply the same migration to their database, so they are all working with a consistent structure. When you run a migration, the Ruby script is converted into the SQL code appropriate to your database server and executed over the database connection. However, migrations don't work with every database adapter in Rails: check the Database Support section of the ActiveRecord::Migration documentation to find out whether your adapter is supported. At the time of writing, MySQL, PostgreSQL, SQLite, SQL Server, Sybase, and Oracle were all supported by migrations. Another way to check whether your database supports migrations is to run the following command in the console (the output shown below is the result of running this using the MySQL adapter): >> ActiveRecord::Base.connection.supports_migrations? => true We're going to use migrations to develop our database, so we'll be building the model first. The actual database table will be generated from a migration attached to the model. Building a Model with Migrations In this section, we're going to develop a series of migrations to recreate the database structure outlined in Chapter 2 of the book Ruby on Rails Enterprise Application Development: Plan, Program, Extend. First, we'll work on a model and migration for the people table. Rails has a generate script for generating a model and its migration. (This script is in the script directory, along with the other Rails built-in scripts.) The script builds the model, a base migration for the table, plus scripts for testing the model. Run it like this: $ ruby script/generate model Person exists app/models/  exists test/unit/    exists test/fixtures/    create app/models/person.rb    create test/unit/person_test.rb    create test/fixtures/people.yml    exists db/migrate    create db/migrate/001_create_people.rb Note that we passed the singular, uppercase version of the table name ("people" becomes "Person") to the generate script. This generates a Person model in the file app/models/person.rb; and a corresponding migration for a people table (db/ migrate/001_create_people.rb). As you can see, the script enforces the naming conventions, which connects the table to the model. The migration name is important, as it contains sequencing information: the "001" part of the name indicates that running this migration will bring the database schema up to version 1; subsequent migrations will be numbered "002...", "003..." etc., each specifying the actions required to bring the database schema up to that version from the previous one. The next step is to edit the migration so that it will create the people table structure. At this point, we can return to Eclipse to do our editing. (Remember that you need to refresh the file list in Eclipse to see the files you just generated). Once, you have started Eclipse, open the file db/migrate/001_create_people.rb. It should look like this:     class CreatePeople < ActiveRecord::Migration        def self.up            create_table :people do |t|                # t.column :name, :string            end        end        def self.down            drop_table :people        end    end This is a migration class with two class methods, self.up and self.down. The self.up method is applied when migrating up one database version number: in this case, from version 0 to version 1. The self.down method is applied when moving down a version number (from version 1 to 0). You can leave self.down as it is, as it simply drops the database table. This migration's self.up method is going to add our new table using the create_table method, so this is the method we're going to edit in the next section. Ruby syntaxExplaining the full Ruby syntax is outside the scope of this book. For our purposes, it suffices to understand the most unusual parts. For example, in the create_table method call shown above:,     create_table :people do |t|        t.column :title, :string        ...    end The first unusual part of this is the block construct, a powerful technique for creating nameless functions. In the example code above, the block is initialized by the do keyword; this is followed by a list of parameters to the block (in this case, just t); and closed by the end keyword. The statements in-between the do and end keywords are run within the context of the block. Blocks are similar to lambda functions in Lisp or Python, providing a mechanism for passing a function as an argument to another function. In the case of the example, the method call create_table:people is passed to a block, which accepts a single argument, t; t has methods called on it within the body of the block. When create_table is called, the resulting table object is "yielded" to the block; effectively, the object is passed into the block as the argument t, and has its column method called multiple times. One other oddity is the symbol: that's what the words prefixed with a colon are. A symbol is the name of a variable. However, in much of Rails, it is used in contexts where it is functionally equivalent to a string, to make the code look more elegant. In fact, in migrations, strings can be used interchangeably with symbols.  
Read more
  • 0
  • 0
  • 5395

article-image-working-report-builder-microsoft-sql-server-2008-part-2
Packt
22 Oct 2009
3 min read
Save for later

Working with the Report Builder in Microsoft SQL Server 2008: Part 2

Packt
22 Oct 2009
3 min read
Enabling and reviewing My Reports As described in Part 1 the My Reports folder needs to be enabled in order to use the folder or display it in the Open Report dialogue. The RC0 version had a documentation bug which has been rectified (https://connect.microsoft.com/SQLServer/feedback/ViewFeedback.aspx?FeedbackID=366413) Getting ready In order to enable the My Reports folder you need to carry out a few tasks. This will require authentication and working with the SQL Server Management Studio. These tasks are listed here: Make sure the Report Server has started. Make sure you have adequate permissions to access the Servers. Open the Microsoft SQL Server Management Studio as described previously. Connect to the Reporting Services after making sure you have started the Reporting Services. Right-click the Report Server node. General Execution History Logging Security Advanced The Server Properties window is displayed with a navigation list on the left consisting of the following: In the General page the name, version, edition, authentication mode, and URL of Reporting Service is displayed. Download of an ActiveX Client Print control is enabled by default. In order to work with Report Builder effectively and provide a My Reports folder for each user, you need to place a check mark for the check box Enable a My Reports folder for each user. The My Reports feature has been turned on as shown in the next screenshot. In the Execution page there is choice for report timeout execution, with the default set such that the report execution expires after 1800 seconds. In the History page there is choice between keeping an unlimited number of snapshots in the report history (default) or to limit the copies allowing you to specify how many to be kept. In the Logging page, report execution logging is enabled and the log entries older than 60 days are removed by default. This can be changed if desired. In the Security page, both Windows integrated security for report data sources and ad hoc report executions are enabled by default. The Advanced page shows several more items including the ones described thus far as shown in the next figure. In the General page enable the My Reports feature by placing a check mark. Click on the Advanced list item in the left. The Advanced page is displayed as shown: Now expand the Security node of Reporting Services and you will see that the My Reports role is present in the list of roles as shown. This is also added to the ReportServer database. The description of everything that a user with the assignment My Reports role can do is as follows: May publish reports and linked reports, manage folders, reports, and resources in a users My Reports folder. Now bring up Report Builder 2.0 by clicking Start | All Programs | Microsoft SQL Server 2008 Report Builder | Report Builder 2.0. Report Builder 2.0 is displayed. Click on Office Button | Open. The Open Report dialogue appears as shown. When the report Server is offline, the default location is My Documents, like Microsoft products Excel and MS Access. Choose the Recent sites and Servers. The Report server that is active should get displayed here as shown: Highlight the Server URL and click Open. All the folders and files on the server become accessible as shown: Open the Report Manager by providing its URL address. Verify that a My Reports folder is created for the user (current user). There could be slight differences in the look of the interface depending on whether you are using the RTM or the final version of SQL Server 2008 Enterprise edition.
Read more
  • 0
  • 0
  • 2596

article-image-blogger-improving-your-blog-google-analytics-and-search-engine-optimization
Packt
22 Oct 2009
7 min read
Save for later

Blogger: Improving Your Blog with Google Analytics and Search Engine Optimization

Packt
22 Oct 2009
7 min read
If you've ever wondered how people find your website or how to generate more traffic, then this article tells you more about your visitors. Knowing where they come from, what posts they like, how long they stay, and other site metrics are all valuable information to have as a blogger. You would expect to pay for such a deep look into the underbelly of your blog, but Google wants to give it to you for free. Why for free? The better your site does, the more likely you are to pay for AdWords or use other Google tools. The Google Analytics online statistics application is a delicious carrot to encourage content rich sites and better ad revenue for everyone involved. You also want people to find your blog when they perform a search about your topic. The painful truth is that search engines have to find your blog first before it will show up in their results. There are thousands of new blogs being created everyday. If you want people to be able to find your blog in the increasingly crowded blogosphere, optimizing your blog for search engines will improve the odds. Improving Your Blog with Google Analytics Analytics gives you an overwhelming amount of data to use for measuring the success of your sites, and ads. Once you've had time to analyze that data, you will want to take action to improve the performance of your blog, and ads. We'll now look at how Analytics can help you make decisions about the design, and content of your site. Analyzing Navigation The Navigation section of the Content Overview report reveals how your visitors actually navigate your blog. Visitors move around a site in ways we can't predict. Seeing how they actually navigate a site and where they entered the site are powerful tools we can use to diagnose where we need to improve our blog. Exploring the Navigation Summary The Navigation Summary shows you the path people take through your site, including how they get there and where they go. We can see from the following graphical representation that our visitors entered the site through the main page of the blog most of the time. After reaching that page, over half the time, they went to other pages within the site. Entrance Paths We can see the path, the visitors take to enter our blog using the Entrance Paths report. It will show us from where they entered our site, which pages they looked at, and the last page they viewed before exiting. Visitors don't always enter by the main page of a site, especially if they find the site using search engines or trackbacks. The following screenshot displays a typical entrance path. The visitor comes to the site home page, and then goes to the full page of one of the posts. It looks like our visitors are highly attracted to the recipe posts. Georgia may want to feature more posts about recipes that tie in with her available inventory. Optimizing your Landing Page The Landing Page reports tell you where your visitors are coming from, and if they have used keywords to find you. You have a choice between viewing the source visitors used to get to your blog, or the keywords. Knowing the sources will give you guidance on the areas you should focus your marketing or advertising efforts on. Examining Entrance Sources You can quickly see how visitors are finding your site, whether through a direct link, or a search engine, locally from Blogger, or from social networking applications such as Twitter.com. In the Entrance Sources graph shown in the following screenshot, we can see that the largest among the number of people are coming to the blog using a direct link. Blogger is also responsible for a large share of our visitors, which is over 37%. There is even a visitor drawn to the blog from Twitter.com, where Georgia has an account. Discovering Entrance Keywords When visitors arrive at your site using keywords, the words they use will show up on the report. If they are using words in a pattern that do not match your site content, you may see a high bounce rate. You can use this report to redesign your landing page to better represent the purpose of your site by the words, and phrases that you use. Interpreting Click Patterns When visitors visit your site they show their attraction to links, and interactive content by clicking on them. Click Patterns are the representation of all those mouse clicks over a set time period. Using the Site Overlay reporting feature, you can visually see the mouse clicks represented in a graphical pattern. Much like collared pins stuck on a wall chart they will quickly reveal to you, which areas of your site visitors clicked on the most, and which links they avoided. Understanding Site Overlay Site Overlay shows the number of clicks for your site by laying them transparently in a graphical format on top of your site. Details with the number of clicks, and goal tracking information pop up in a little box when you hover over a click graphic with your mouse. At the top of the screen are options that control the display of the Site Overlay. Clicking the Hide Overlay link will hide the overlay from view. The Displaying drop-down list lets you choose how to view mouse Clicks on the page, or goals. The date range is the last item displayed. The graphical bars shown on top of the page content indicate where visitors clicked, and how many of them did so. You can quickly see what areas of the page interest your visitors the most. Based on the page clicks you see, you will have an idea of the content, and advertising that is most interesting to your visitors. Yes, Site Overlay will show the content areas of the page the visitors clicked on, and the advertisement areas. It will also help you see which links are tied to goals, and whether they are enticing your visitors to click. Optimizing Your Blog for Search Engines We are going to take our earlier checklists and use them as guides on where to make changes to our blog. When the changes are complete, the blog will be more attractive to search engines and visitors. We will start with changes we can make "On-site", and then progress to ways we can improve search engine results with "Off-site" improvements. Optimizing On-site The most crucial improvements we identified earlier were around the blog settings, template, and content. We will start with the easiest fixes, then dive into the template to correct validation issues. Let's begin with the settings in our Blogger blog. Seeding the Blog Title and Description with Keywords When you created your blog, did you take a moment to think about what words potential visitors were likely to type in when searching for your blog? Using keywords in the title and description of your blog gives potential visitors a preview and explanation of the topics they can expect to encounter in your blog. This information is what will also display in search results when potential visitors perform a search. Updating the Blog Title and Description It's never too late to seed your blog title and description with keywords. We will edit the blog title and description to optimize them for search engines. Login to your blog and navigate to Settings | Basic. We are going to replace the current title text with a phrase that more closely fits the blog. Type Organic Fruit for All into the Title field. Now, we are going to change the description of the blog. Type Organic Fruit Recipes, seasonal tips, and guides to healthy living into the description field. Scroll down to the bottom of the screen and click the Save Settings button. Y ou can enter up to 500 characters of descriptive text. What Just Happened? When we changed the title and description of our blog in the Basic Settings section, Blogger saved the changes and updated the template information as well. Now, when search engines crawl our blog, they will see richer descriptions of our blog in the blog title and blog description. The next optimization task is to verify that search engines can index our blog.
Read more
  • 0
  • 0
  • 4913
article-image-interacting-students-using-moodle-19-part-2
Packt
22 Oct 2009
10 min read
Save for later

Interacting with the Students using Moodle 1.9 (part 2)

Packt
22 Oct 2009
10 min read
We'll add a competitive element to the project and—just as we have seen on TV—let the children vote for the winner. The tasks we set will involve the students researching, collaborating, and reflecting. They will be working hard, but we'll have a much easier time now, as all of their responses will be on Moodle for us to view and mark at our convenience—no more carrying heavy books around. Giving our class a chance to vote Moodle has an activity, known as Choice, which allows you to present students with a number of options that they can choose from. We're actually going to use it twice in our project, for two different purposes. Let's us try and set it up. Time for action-giving students a chance to choose a winner The students have posted their suggestions, comments, and views on Moodle. A choice is to be made of the best suggestion. Who better, than the students themselves to choose and vote for the best? With editing turned on, click on Add an Activity and then select Choice. In the Name field, enter an appropriate descriptive text—in our case, this is Vote for the best design here. In the Choice Text field, ask the question based on which you want the students to cast a vote. Leave the Limit field as it is if you don't mind any number of students casting a vote for any option available. Change it to enable, if you only want a certain number of people to vote for a particular choice. We shall leave the Limit block as it is, but we shall inform the students that they can't vote for themselves. In the Choice block, type in the options (a minimum of two) you want the students to be able to cast their vote for. Clicking on Add more fields will provide you with more choice boxes. We will need one field for each member of the class, for this activity. Use the Restrict answering to this time period option to decide when to open and close your Choice—or have it always available. Miscellaneous settings: For our activity, we need to set Display Mode to Vertical set and Publish Results to Do Not Publish. The following table explains what the settings mean, so you can use them on other occasions. Setting What it is Why use it Display Mode Lets you have your buttons go across or down the screen Use Vertically if you have many options to avoid stretching your screen Publish Results Decide if and when you want students to see what others have put Choose Do not publish if you want them to tell you their progress privately; if you're doing a class survey, choose, for example, Always show results Privacy of Results Lets you choose whether to show names or not Are the results more important than who voted for what? Some students might be wary of responding if they think their names will be shown Allow choice to be updated Lets them change their mind-but they can still vote only once. Useful, if you are using this to assess progress over a period of time. Show column for unanswered Sets up a column showing those who haven't yet responded A clear visual way of knowing who hasn't done the task For now, you can ignore the Common Module Settings option, and just click on Save and return to course. What just happened? We've set up an area, on our course page, where the students can choose their favorite designs from a number of options, by clicking on the desired option button. On the screen, you will be able to see an icon (usually, a question mark) and some text next to it. If you click on the text next to the icon, the following information will appear: The students will click on the option button placed next to their choice—in our case, the name of the classmate whose design they prefer. Finding out the students' choice Access the Choice option and click on the words View *** responses on the upper right of the screen. The *** will be the number of students who have voted already. You will get a chart displaying the choices of the students. In my Moodle course, as shown in the following screenshot, nobody has voted yet—so they need a gentle nudge! Remember that we have set up this activity so that our students cannot see the results, in order to avoid peer pressure or bullying. However, we can see the results. Thus, if Mickey votes for himself (even after having been told not to) we will spot it and can reprimand him. Have a go hero-getting the class to give us feedback After we've gone through all of the effort to set up our project on Moodle, it would be nice to know how well it was received. Why not go off now and set up another Choice option, where the question asks how much did you enjoy planning and designing the campsite? You could give them three simple responses (displayed horizontally) as: A lot It was OK Not very much. Or you could be more specific, focusing on the individual activities and asking how much they feel they have benefited from, say, the wiki or the forum. Make sure it is set up, so that the students don't see the results—that way they're more likely to be truthful. Why use Choice? Here are a few other thoughts on Choice, based on my own experiences: It is a fast and simple method of gathering data for a class research project. I used this with a class of 13 year olds who had just returned from the summer break. I asked them to choose where they had been on vacation, giving them choices of our own country, several nearby countries in Europe, the United States of America, and a few more. I set up the choice, so that they could all see the answers when the time was up. I also set it up in such a way that the results were anonymous, to avoid any kind of uneasiness felt by those students who had stayed at home. The class then compared and contrasted the class results with Tourist Office statistics on the most popular tourist destinations. It offers a private way for students to evaluate and inform the teacher about their progress. Students might be too shy to tell you in person if they are struggling; they might be wary of being honest in the open voting methods that some teachers use (such as red, amber, or green traffic lights). However, if the students are aware of the fact that their classmates will not see their response, they are more likely to be honest with you. It acts as a way to involve the class in deciding the path that their learning will take. I first introduced my class of 11 year olds to rivers in Europe, South America, Africa, and Asia. Then, I offered the class, the chance to vote for the river that they wanted study in greater depth as part of their project. The majority opted for the Amazon—so the Amazon it was! Announcing the winner Well, you could give out the results in the classroom, of course! Alternatively, can encourage them to use Moodle by using the Compose a Webpage resource that we met in the previous article on Adding Worksheets and Resources with Moodle, and adding the information there. Writing creatively in Moodle Once a winner has been found, the next task for everyone is to create a cleverly-worded advertisement for this campsite, for which, you could use one of the names suggested in the glossary. This too can be done on Moodle. Why use Moodle and not their exercise books? The first reason is that it will save paper, the second reason is that the students enjoy working on the computer, and the third and final reason is that we can work at our leisure in school, at home, or in any room where there is an Internet connection. We're not tied to carrying around a pile of heavy books. We don't even need to manually hand-write the grades into our grade book. Moodle will put the grades that we give our students, into its grade book automatically and alphabetically. Moodle can also send our pupils an email telling them that we've graded their task, so that they can check their grades. This might be a different way of working from the one that you are used to, but do give it a try. It will take the pressure off your back and shoulders, if nothing else. Time for action-setting up an online creative writing exercise For our advert, we'll use an Online text assignment. With editing turned on, select online text option, within Assignments. In the Assignment name field, enter something descriptive—our students will click here to get to the task. In the Description field, enter the instructions. Our screen will then appear as shown in the following screenshot: If you need more space to type in, click on the icon on the far right of the bottom line of the HTML editor. This will enlarge the text box for you. Click it again when you're done, to return to the editing area. In the Grade field, enter the total marks out of which you will score the students (for now, we're sticking to a maximum of 100, but you can change this). Set a start and end date between which the students can send the work assigned to them, if you want. Leave the Prevent Late Submissions option as it is, unless you need to set a deadline by which the students must submit the assigned work. Set the Allow Resubmitting option to YES, if you want to let students redraft their work. Set the Email Alerts to teachers option to NO (unless you want 30 emails in your inbox!). Change the Comment inline option to YES, so that we can post a comment on the students work. Click on Save and return to course. What just happened? We've just explained to our class what we want them to do, and have also provided them with space in Moodle to do it. We used an Online Text assignment. If we go up to the top of our course, where the editing button is, you'll be able to see a very useful feature called Switch role to…. If we choose the Student option, it will allow us to see the tasks as the pupils will see them: In this case, there's a rather unfriendly command at the bottom of our assignment. Do you think that your students will know that they need to click here to get to their text box? Why not ask your Moodle administrator to look at the Language editing settings and change these words to something more child-friendly—such as Click here to type your answer?
Read more
  • 0
  • 0
  • 1543

article-image-enhancing-user-interface-ajax
Packt
22 Oct 2009
32 min read
Save for later

Enhancing the User Interface with Ajax

Packt
22 Oct 2009
32 min read
Since our project is a Web 2.0 application, it should be heavily focused on the user experience. The success of our application depends on getting users to post and share content on it. Therefore, the user interface of our application is one of our major concerns. This article will improve the interface of our application by introducing Ajax features, making it more user-friendly and interactive. Ajax and Its Advantages Ajax, which stands for Asynchronous JavaScript and XML, consists of the following technologies: HTML and CSS for structuring and styling information. JavaScript for accessing and manipulating information dynamically. XMLHttpRequest, which is an object provided by modern browsers for exchanging data with the server without reloading the current web page. A format for transferring data between the client and server. XML is sometimes used, but it could be HTML, plain text, or a JavaScript-based format called JSON. Ajax technologies let code on the client-side exchange data with the server behind the scenes, without having to reload the entire page each time the user makes a request. By using Ajax, web developers are able to increase the interactivity and usability of web pages. Ajax offers the following advantages when implemented in the right places: Better user experience. With Ajax, the user can do a lot without refreshing the page, which brings web applications closer to regular desktop applications. Better performance. By exchanging only the required data with the server, Ajax saves bandwidth and increases the application's speed. There are numerous examples of web applications that use Ajax. Google Maps and Gmail are perhaps two of the most prominent examples. In fact, these two applications played an important role in spreading the adoption of Ajax, because of the success that they enjoyed. What sets Gmail from other web mail services is its user interface, which enables users to manage their emails interactively without waiting for a page reload after every action. This creates a better user experience and makes Gmail feel like a responsive and feature-rich application rather than a simple web site. This article explains how to use Ajax with Django so as to make our application more responsive and user friendly. We are going to implement three of the most common Ajax features found in web applications today. But before that, we will learn about the benefits of using an Ajax framework as opposed to working with raw JavaScript functions. Using an Ajax Framework in Django In this section we will choose and install an Ajax framework in our application. This step isn't entirely necessary when using Ajax in Django, but it can greatly simplify working with Ajax. There are many advantages to using an Ajax framework: JavaScript implementations vary from browser to browser. Some browsers provide more complete and feature-rich implementations, whereas others contain implementations that are incomplete or don't adhere to standards. Without an Ajax framework, the developer must keep track of browser support for the JavaScript features that they are using, and work around the limitations that are present in some browser implementations of JavaScript. On the other hand, when using an Ajax framework, the framework takes care of this for us; it abstracts access to the JavaScript implementation and deals with the differences and quirks of JavaScript across browsers. This way, we concentrate on developing features instead of worrying about browser differences and limitations. The standard set of JavaScript functions and classes is a bit lacking for fully fledged web application development. Various common tasks require many lines of code even though they could have been wrapped in simple functions. Therefore, even if you decide not to use an Ajax framework, you will find yourself having to write a library of functions that encapsulates JavaScript facilities and makes them more usable. But why reinvent the wheel when there are many excellent Open Source libraries already available? Ajax frameworks available on the market today range from comprehensive solutions that provide server-side and client-side components to light-weight client-side libraries that simplify working with JavaScript. Given that we are already using Django on the server-side, we only want a client-side framework. In addition, the framework should be easy to integrate with Django without requiring additional dependencies. And finally, it is preferable to pick a light and fast framework. There are many excellent frameworks that fulfil our requirements, such as Prototype, the Yahoo! UI Library and jQuery. I have worked with them all and they are all great. But for our application, I'm going to pick jQuery, because it's the lightest of the three. It also enjoys a very active development community and a wide range of plugins. If you already have experience with another framework, you can continue using it during this article. It is true that you will have to adapt the JavaScript code in this article to your framework, but Django code on the server-side will remain the same no matter which framework you choose. Now that you know the benefits of using an Ajax framework, we will move to installing jQuery into our project. Downloading and Installing jQuery One of the advantages of jQuery is that it consists of a single light-weight file. To download it, head to http://jquery.com/ and choose the latest version (1.2.3 at the time of writing). You will find two choices: Uncompressed version: This is the standard version that I recommend you to use during development. You will get a .js file with the library's code in it. Compressed version: You will also get a .js file if you download this version. However, the code will look obfuscated. jQuery developers produce this version by applying many operations on the uncompressed .js file to reduce its size, such as removing white spaces and renaming variables, as well as many other techniques. This version is useful when you deploy your application, because it offers exactly the same features as the uncompressed one, but with a smaller file size. I recommend the uncompressed version during development because you may want to look into jQuery's code and see how a particular method works. However, the two versions offer exactly the same set of features, and switching from one to another is just a matter of replacing one file. Once you have the jquery-xxx.js file (where xxx is the version number), rename it to jquery.js and copy it to the site_media directory of our project (Remember that this directory holds static files which are not Python code). Next, you will have to include this file in the base template of our site. This will make jQuery available to all of our project pages. To do so, open templates/base.html and add the highlighted code to the head section in it: <head> <title>Django Bookmarks | {% block title %}{% endblock %}</title> <link rel="stylesheet" href="/site_media/style.css"type="text/css" /> <script type="text/javascript"src="/site_media/jquery.js"></script></head> To add your own JavaScript code to an HTML page, you can either put the code in a separate .js file and link it to the HTML page by using the script tag as above, or write the code directly in the body of a script tag: <script type="text/javascript"> // JavaScript code goes here.</script> The first method, however, is recommended over the second one, because it helps keep the source tree organized by putting HTML and JavaScript code in different files. Since we are going to write our own .js files during this article, we need a way to link .js files to templates without having to edit base.html every time. We will do this by creating a template block in the head section of the base.html template. When a particular page wants to include its own JavaScript code, this block may be overridden to add the relevant script tag to the page. We will call this block external, because it is used to link external files to pages. Open templates/base.html and modify its head section as follows: <head> <title>Django Bookmarks | {% block title %}{% endblock %}</title> <link rel="stylesheet" href="/site_media/style.css" type="text/css"/> <script type="text/javascript" src="/site_media/jquery.js"> </script> {% block external %}{% endblock %}</head> And we have finished. From now on, when a view wants to use some JavaScript code, it can link a JavaScript file to its template by overriding the external template block. Before we start to implement Ajax enhancements in our project, let's go through a quick introduction to the jQuery framework. The jQuery JavaScript Framework jQuery is a library of JavaScript functions that facilitates interacting with HTML documents and manipulating them. The library is designed to reduce the time and effort spent on writing code and achieving cross-browser compatibility, while at the same time taking full advantage of what JavaScript offers to build interactive and responsive web applications. The general workflow of using jQuery consists of two steps: Select an HTML element or a group of elements to work on. Apply a jQuery method to the selected group Element Selectors jQuery provides a simple approach to select elements; it works by passing a CSS selector string to a function called $. Here are some examples to illustrate the usage of this function: If you want to select all anchor (<a>) elements on a page, you can use the following function call: $("a") If you want to select anchor elements which have the .title CSS class, use $("a.title") To select an element whose ID is #nav, you can use $("#nav") To select all list item (<li>) elements inside #nav, use $("#nav li") And so on. The $() function constructs and returns a jQuery object. After that, you can call methods on this object to interact with the selected HTML elements. jQuery Methods jQuery offers a variety of methods to manipulate HTML documents. You can hide or show elements, attach event handlers to events, modify CSS properties, manipulate the page structure and, most importantly, perform Ajax requests. Before we go through some of the most important methods, I highly recommend using the Firefox web browser and an extension called Firebug to experiment with jQuery. This extension provides a JavaScript console that is very similar to the interactive Python console. With it, you can enter JavaScript statements and see their output directly without having to create and edit files. To obtain Firebug, go to http://www.getfirebug.com/, and click on the install link. Depending on the security settings of Firefox, you may need to approve the website as a safe source of extensions. If you do not want to use Firefox for any reason, Firebug's website offers a "lite" version of the extension for other browsers in the form of a JavaScript file. Download the file to the site_media directory, and then include it in the templates/base.html template as we did with jquery.js: <head> <title>Django Bookmarks | {% block title %}{% endblock %}</title> <link rel="stylesheet" href="/site_media/style.css" type="text/css"/> <script type="text/javascript" src="/site_media/firebug.js"> </script> <script type="text/javascript" src="/site_media/jquery.js"> </script> {% block external %}{% endblock %}</head> To experiment with the methods outlined in this section, launch the development server and navigate to the application's main page. Open the Firebug console by pressing F12, and try selecting elements and manipulating them. Hiding and Showing Elements Let's start with something simple. To hide an element on the page, call the hide() method on it. To show it again, call the show() method. For example, try this on the navigation menu of your application: >>> $("#nav").hide()>>> $("#nav").show() You can also animate the element while hiding and showing it. Try the fadeOut(), fadeIn(), slideUp() or slideDown() methods to see two of these animated effects. Of course, these methods (like all other jQuery methods) also work if you select more than one element at once. For example, if you open your user page and enter the following method call into the Firebug console, all of the tags will disappear: >>> $('.tags').slideUp() Accessing CSS Properties and HTML Attributes Next, we will learn how to change CSS properties of elements. jQuery offers a method called css() for performing CSS operations. If you call this method with a CSS property name passed as a string, it returns the value of this property: >>> $("#nav").css("display") Result: "block" If you pass a second argument to this method, it sets the specified CSS property of the selected element to the additional argument: >>> $("#nav").css("font-size", "0.8em") Result: <div id="nav" style="font-size: 0.8em;"> In fact, you can manipulate any HTML attribute and not just CSS properties. To do so, use the attr() method which works in a similar way to css(). Calling it with an attribute name returns the attribute value, whereas calling it with an attribute name/value pair sets the attribute to the passed value. To test this, go to the bookmark submission form and enter the following into the console: >>> $("input").attr("size", "48") Results: <input id="id_url" type="text" size="48" name="url"> <input id="id_title" type="text" size="48" name="title"> <input id="id_tags" type="text" size="48" name="tags"> (Output may slightly differ depending on the versions of Firefox and Firebug). This will change the sizes of all input elements on the page at once to 48. In addition, there are shortcut methods to get and set commonly used attributes, such as val() which returns the value of an input field when called without arguments, and sets this value to an argument if you pass one. There is also html() which controls the HTML code inside an element. Finally, there are two methods that can be used to attach or detach a CSS class to an element; they are called addClass() and removeClass(). A third method is provided to toggle a CSS class, and it is called toggleClass(). All of these class methods take the name of the class to be changed as a parameter. Manipulating HTML Documents Now that you are comfortable with manipulating HTML elements, let's see how to add new elements or remove existing elements. To insert HTML code before an element, use the before() method, and to insert code after an element, use the after() method. Notice how jQuery methods are well-named and very easy to remember! Let's test these methods by inserting parentheses around tag lists on the user page. Open your user page and enter the following in the Firebug console: >>> $(".tags").before("<strong>(</strong>")>>> $(".tags").after("<strong>)</strong>") You can pass any string you want to - before() or after() - the string may contain plain text, one HTML element or more. These methods offer a very flexible way to dynamically add HTML elements to an HTML document. If you want to remove an element, use the remove() method. For example: $("#nav").remove() Not only does this method hide the element, it also removes it completely from the document tree. If you try to select the element again after using the remove() method, you will get an empty set: >>> $("#nav") Result: [] Of course, this only removes the elements from the current instance of the page. If you reload the page, the elements will appear again. Traversing the Document Tree Although CSS selectors offer a very powerful way to select elements, there are times when you want to traverse the document tree starting from a particular element. For this, jQuery provides several methods. The parent() method returns the parent of the currently selected element. The children() method returns all the immediate children of the selected element. Finally, the find() method returns all the descendants of the currently selected element. All of these methods take an optional CSS selector string to limit the result to elements that match the selector. For example, $("#nav").find ("li") returns all the <li> descendants of #nav. If you want to access an individual element of a group, use the get() method which takes the index of the element as a parameter. $("li").get(0) for example returns the first <li> element out of the selected group. Handling Events Next, we will learn about event handlers. An event handler is a JavaScript function that is invoked when a particular event happens, for example, when a button is clicked or a form is submitted. jQuery provides a large set of methods to attach handlers to events; events of particular interest in our application are mouse clicks and form submissions. To handle the event of clicking on an element, we select this element and call the click() method on it. This method takes an event handler function as a parameter. Let's try this using the Firebug console. Open the main page of the application, and insert a button after the welcome message: >>> $("p").after("<button id="test-button">Click me!</button>") (Notice that we had to escape the quotations in the strings passed to the after() method.) If you try to click this button, nothing will happen, so let's attach an event handler to it: >>> $("#test-button").click(function () { alert("You clicked me!"); }) Now, when you click the button, a message box will appear. How did this work? The argument that we passed to click() may look a bit complicated, so let's examine it again: function () { alert("You clicked me!"); } This appears to be a function declaration but without a function name. Indeed, this construct creates what is called an anonymous function in JavaScript terminology, and it is used when you need to create a function on the fly and pass it as an argument to another function. We could have avoided using anonymous functions and declared the event handler as a regular function: >>> function handler() { alert("You clicked me!"); }>>> $("#test-button").click(handler) The above code achieves the same effect, but the first one is more concise and compact. I highly recommend you to get used to anonymous functions in JavaScript (if you are not already), as I'm sure you will appreciate this construct and find it more readable after using it for a while. Handling form submissions is very similar to handling mouse clicks. First, you select the form, and then you call the submit() method on it and pass the handler as an argument. We will use this method many times while adding Ajax features to our project in later sections. Sending Ajax Requests Before we finish this section, let's talk about Ajax requests. jQuery provides many ways to send Ajax requests to the server. There is, for example, the load() method which takes a URL and loads the page at this URL into the selected element. There are also methods for sending GET or POST requests, and receiving the results. We will examine these methods in more depth while implementing Ajax features in our project. What Next? This wraps up our quick introduction to jQuery. The information provided in this section will be enough to continue with this article, and once you finish the article, you will be able to implement many interesting Ajax features on your own. But please keep in mind that this jQuery introduction is only the tip of the iceberg. If you want a comprehensive treatment of the jQuery framework, I highly recommend the book "Learning jQuery" from Packt Publishing, as it covers jQuery in much more detail. You can find out more about the book at: http://www.packtpub.com/jQuery Implementing Live Searching of Bookmarks We will start introducing Ajax into our application by implementing live searching. The idea behind this feature is simple: when the user types a few keywords into a text field and clicks search, a script works behind the scenes to fetch search results and present them on the same page. The search page does not reload, thus saving bandwidth, and providing a better and more responsive user experience. Before we start implementing this, we need to keep in mind an important rule while working with Ajax: write your application so that it works without Ajax, and then introduce Ajax to it. If you do so, you ensure that everyone will be able to use your application, including users who don't have JavaScript enabled and those who use browsers without Ajax support. Implementing Searching So before we work with Ajax, let's write a simple view that searches bookmarks by title. First of all, we need to create a search form, so open bookmarks/forms.py and add the following class to it: class SearchForm(forms.Form): query = forms.CharField( label='Enter a keyword to search for', widget=forms.TextInput(attrs={'size': 32})) As you can see, it's a pretty straightforward form class with only one text field. This field will be used by the user to enter search keywords. Next, let's create a view for searching. Open bookmarks/views.py and enter the following code into it: def search_page(request): form = SearchForm() bookmarks = [] show_results = False if request.GET.has_key('query'): show_results = True query = request.GET['query'].strip() if query: form = SearchForm({'query' : query}) bookmarks = Bookmark.objects.filter (title__icontains=query)[:10] variables = RequestContext(request, { 'form': form, 'bookmarks': bookmarks, 'show_results': show_results, 'show_tags': True, 'show_user': True })return render_to_response('search.html', variables) Apart from a couple of method calls, the view should be very easy to understand. We first initialize three variables, form which holds the search form, bookmarks which holds the bookmarks that we will display in the search results, and show_results which is a Boolean flag. We use this flag to distinguish between two cases: The search page was requested without a search query. In this case, we shouldn't display any search results, not even a "No bookmarks found" message. The search page was requested with a search query. In this case, we display the search results, or a "No bookmarks found" message if the query does not match any bookmarks. We need the show_results flag because the bookmarks variable alone is not enough to distinguish between the above two cases. bookmarks will empty when the search page is requested without a query, and it will also be empty when the query does not match any bookmarks. Next, we check whether a query was sent by calling the has_key method on the request.GET dictionary: if request.GET.has_key('query'): show_results = True query = request.GET['query'].strip() if query: form = SearchForm({'query' : query}) bookmarks = Bookmark.objects.filter(title__icontains=query)[:10] We use GET instead of POST here because the search form does not create or change data; it merely queries the database, and the general rule is to use GET with forms that query the database, and POST with forms that create, change or delete records from the database. If a query was submitted by the user, we set show_results to True and call strip() on the query string to ensure that it contains non-whitespace characters before we proceed with searching. If this is indeed the case, we bind the form to the query and retrieve a list of bookmarks that contain the query in their title. Searching is done by using a method called filter in Bookmark.objects. This is the first time that we have used this method; you can think of it as the equivalent of a SELECT statements in Django models. It receives the search criteria in its arguments and returns search results. The name of each argument must adhere to the following naming convention: field__operator Note that field and operator are separated by two underscores: field is the name of the field that we want to search by and operator is the lookup method that we want to use. Here is a list of the commonly-used operators: exact: The value of the argument is an exact match of the field. contains: The field contains the value of the argument. startswith: The field starts with the value of the argument. lt: The field is less than the value of the argument. gt: The field is greater than the value of the argument. Also, there are case-insensitive versions of the first three operators: iexact, icontains and istartswith. After this explanation of the filter method, let's get back to our search view. We use the icontains operator to get a list of bookmarks that match the query and retrieve the first ten items using Python's list slicing syntax. Finally we pass all the variables to a template called search.html to render the search page. Now create the search.html template in the templates directory with the following content: {% extends "base.html" %}{% block title %}Search Bookmarks{% endblock %}{% block head %}Search Bookmarks{% endblock %}{% block content %}<form id="search-form" method="get" action="."> {{ form.as_p }} <input type="submit" value="search" /></form><div id="search-results"> {% if show_results %} {% include 'bookmark_list.html' %} {% endif %}</div>{% endblock %} The template consists of familiar aspects that we have used before. We build the results list by including the bookmark_list.html like we did when building the user and tag pages. We gave the search form an ID, and rendered the search results in a div identified by another ID so that we can interact with them using JavaScript later. Notice how many times the include template tag saved us from writing additional code? It also lets us modify the look of the bookmarks list by editing a single file. This Django template feature is indeed very helpful in organizing and managing templates. Before you test the new view, add an entry for it in urls.py: urlpatterns = patterns('', # Browsing (r'^$', main_page), (r'^user/(w+)/$', user_page), (r'^tag/([^s]+)/$', tag_page), (r'^tag/$', tag_cloud_page), (r'^search/$', search_page),) Now test the search view by navigating to http://127.0.0.1:8000/search/ and experiment with it. You can also add a link to it in the navigation menu if you want; edit templates/base.html and add the highlighted code: <div id="nav"> <a href="/">home</a> | {% if user.is_authenticated %} <a href="/save/">submit</a> | <a href="/search/">search</a> | <a href="/user/{{ user.username }}/"> {{ user.username }}</a> | <a href="/logout/">logout</a> {% else %} <a href="/login/">login</a> | <a href="/register/">register</a> {% endif %}</div> We now have a functional (albeit very basic) search page. Thanks to our modular code, the task will turn out to be much simpler than it may seem. Implementing Live Searching To implement live searching, we need to do two things: Intercept and handle the event of submitting the search form. This can be done using the submit() method of jQuery. Use Ajax to load the search results in the back scenes, and insert them into the page. This can be done using the load() method of jQuery as we will see next. jQuery offers a method called load() that retrieves a page from the server and inserts its contents into the selected element. In its simplest form, the function takes the URL of the remote page to be loaded as a parameter. First of all, let's modify our search view a little so that it only returns search results without the rest of the search page when it receives an additional GET variable called ajax. We do so to enable JavaScript code on the client-side to easily retrieve search results without the rest of the search page HTML. This can be done by simply using the bookmark_list.html template instead of search.html when request.GET contains the key ajax. Open bookmarks/views.py and modify search_page (towards the end) so that it becomes as follows: def search_page(request): [...] variables = RequestContext(request, { 'form': form, 'bookmarks': bookmarks, 'show_results': show_results, 'show_tags': True, 'show_user': True }) if request.GET.has_key('ajax'): return render_to_response('bookmark_list.html', variables) else: return render_to_response('search.html', variables) Next, create a file called search.js in the site_media directory and link it to templates/search.html like this: {% extends "base.html" %}{% block external %} <script type="text/javascript" src="/site_media/search.js"> </script>{% endblock %}{% block title %}Search Bookmarks{% endblock %}{% block head %}Search Bookmarks{% endblock %}[...] Now for the fun part! Let's create a function that loads search results and inserts them into the corresponding div. Write the following code into site_media/search.js: function search_submit() { var query = $("#id_query").val(); $("#search-results").load( "/search/?ajax&query=" + encodeURIComponent(query) ); return false;} Let's go through this function line by line: The function first gets the query string from the text field using the val() method. We use the load() method to get search results from the search_page view, and insert the search results into the #search-results div. The request URL is constructed by first calling encodeURIComponent on query, which works exactly like the urlencode filter we used in Django templates. Calling this function is important to ensure that the constructed URL remains valid even if the user enters special characters into the text field such as &. After escaping query, we concatenate it with /search/?ajax&query=. This URL invokes the search_page view and passes the GET variables ajax and query to it. The view returns search results, and the load() method in turn loads the results into the #search-results div. We return false from the function to tell the browser not to submit the form after calling our handler. If we don't return false in the function, the browser will continue to submit the form as usual, and we don't want that. One little detail remains; where and when to attach search_submit to the submit event of the search form? A rule of a thumb when writing JavaScript is that we cannot manipulate elements in the document tree before the document finishes loading. Therefore, our function must be invoked as soon as the search page is loaded. Fortunately for us, jQuery provides a method to execute a function when the HTML document is loaded. Let's utilize it by appending the following code to site_media/search.js: $(document).ready(function () { $("#search-form").submit(search_submit);}); $(document) selects the document element of the current page. Notice that there are no quotations around document; it's a variable provided by the browser, not a string. ready() is a method that takes a function and executes it as soon as the selected element finishes loading. So in effect, we are telling jQuery to execute the passed function as soon as the HTML document is loaded. We pass an anonymous function to the ready() method; this function simply binds search_submit to the submit event of the form #search-form. That's it. We've implemented live searching with less than fifteen lines of code. To test the new functionality, navigate to http://127.0.0.1:8000/search/, submit queries, and notice how the results are displayed without reloading the page: The information covered in this section can be applied to any form that needs to be processed in the back scenes without reloading the page. You can, for example, create a comment form with a preview button that loads the preview in the same page without reloading. In the next section, we will enhance the user page to let users edit their bookmarks in place, without navigating away from the user page. Editing Bookmarks in Place Editing of posted content is a very common task in web sites. It's usually implemented by offering an edit link next to content. When clicked, this link takes the user to a form located on another page where content can be edited. When the user submits the form, they are redirected back to the content page. Imagine, on the other hand, that you could edit content without navigating away from the content page. When you click edit, the content is replaced with a form. When you submit the form, it disappears and the updated content appears in its place. Everything happens on the same page; edit form rendering and submission are done using JavaScript and Ajax. Wouldn't such a workflow be more intuitive and responsive? The technique described above is called in-place editing. It is now finding its way into web applications and becoming more common. We will implement this feature in our application by letting the user edit their bookmarks in place on the user page. Since our application doesn't support the editing of bookmarks yet, we will implement this first, and then modify the editing procedure to work in place. Implementing Bookmark Editing We already have most of the parts that are needed to implement bookmark editing. This was easy to do thanks to the get_or_create method provided by data models. This little detail greatly simplifies the implementation of bookmark editing. Here is what we need to do: We pass the URL of the bookmark that we want to edit as a GET variable named url to the bookmark_save_page view. We modify bookmark_save_page so that it populates the fields of the bookmark form if it receives the GET variable. The form is populated with the data of the bookmark that corresponds to the passed URL. When the populated form is submitted, the bookmark will be updated as we explained earlier, because it will look like the user submitted the same URL another time. Before we implement the technique described above, let's reduce the size of bookmark_save_page by moving the part that saves a bookmark to a separate function. We will call this function _bookmark_save. The underscore at the beginning of the name tells Python not to import this function when the views module is imported. The function expects a request and a valid form object as parameters; it saves a bookmark out of the form data, and returns this bookmark. Open bookmarks/views.py and create the following function; you can cut and paste the code from bookmark_save_page if you like, as we are not making any changes to it except for the return statement at the end. def _bookmark_save(request, form): # Create or get link. link, dummy = Link.objects.get_or_create(url=form.clean_data['url']) # Create or get bookmark. bookmark, created = Bookmark.objects.get_or_create( user=request.user, link=link ) # Update bookmark title. bookmark.title = form.clean_data['title'] # If the bookmark is being updated, clear old tag list. if not created: bookmark.tag_set.clear() # Create new tag list. tag_names = form.clean_data['tags'].split() for tag_name in tag_names: tag, dummy = Tag.objects.get_or_create(name=tag_name) bookmark.tag_set.add(tag)# Save bookmark to database and return it.bookmark.save()return bookmark Now in the same file, replace the code that you removed from bookmark_save_page with a call to _bookmark_save: @login_requireddef bookmark_save_page(request): if request.method == 'POST': form = BookmarkSaveForm(request.POST) if form.is_valid(): bookmark = _bookmark_save(request, form) return HttpResponseRedirect( '/user/%s/' % request.user.username )else: form = BookmarkSaveForm()variables = RequestContext(request, { 'form': form})return render_to_response('bookmark_save.html', variables) The current logic in bookmark_save_page works like this: if there is POST data:Validate and save bookmark.Redirect to user page.else:Create an empty form.Render page. To implement bookmark editing, we need to slightly modify the logic as follows: if there is POST data: Validate and save bookmark. Redirect to user page.else if there is a URL in GET data: Create a form an populate it with the URL's bookmark.else: Create an empty form.Render page. Let's translate the above pseudo code into Python. Modify bookmark_save_page in bookmarks/views.py so that it looks like the following (new code is highlighted): from django.core.exceptions import ObjectDoesNotExist@login_requireddef bookmark_save_page(request): if request.method == 'POST': form = BookmarkSaveForm(request.POST) if form.is_valid(): bookmark = _bookmark_save(request, form) return HttpResponseRedirect( '/user/%s/' % request.user.username ) elif request.GET.has_key('url'): url = request.GET['url'] title = '' tags = '' try: link = Link.objects.get(url=url) bookmark = Bookmark.objects.get( link=link, user=request.user ) title = bookmark.title tags = ' '.join( tag.name for tag in bookmark.tag_set.all() ) except ObjectDoesNotExist: pass form = BookmarkSaveForm({ 'url': url, 'title': title, 'tags': tags }) else: form = BookmarkSaveForm() variables = RequestContext(request, { 'form': form }) return render_to_response('bookmark_save.html', variables) This new section of the code first checks whether a GET variable called url exists. If this is the case, it loads the corresponding Link and Bookmark objects of this URL, and binds all the data to a bookmark saving form. You may wonder why we load the Link and Bookmark objects in a try-except construct that silently ignores exceptions. Indeed, it's perfectly valid to raise an Http404 exception if no bookmark was found for the requested URL. But our code chooses to only populate the URL field in this situation, leaving the title and tags fields empty.
Read more
  • 0
  • 0
  • 11304

article-image-aspnet-mvc-framework
Packt
22 Oct 2009
7 min read
Save for later

ASP.NET MVC Framework

Packt
22 Oct 2009
7 min read
(For more resources on .NET, see here.) As of now, the ASP.NET MVC framework is still in CTP (Community Technology Preview, which is similar to an advanced pre-stage), and there is no certain date when it will be released. But even with the CTP 5, we can see how it will help MVC applications follow a stricter architecture. We will quickly see how to use the ASP.NET MVC framework through a small example. Sample Project First, download the ASP.NET MVC framework from the Microsoft website and install it. This installation will create an MVC project template in VS 2008. Start VS 2008, select the File | New Project menu item and then choose theASP.NET MVC Web Application template to create a new web application using this template. There are many free unit testing frameworks available for ASP.NET projects, and NUnit and MBUnit are two of the most popular ones. Here are the links: MBUnit: http://www.mbunit.com/NUnit:; http://www.nunit.org/index.php Select the default option and click OK. You will notice that two projects have been added to the solution that VS has created. The first project is a web project where you'll implement your application. The second is a testing project that you can use to write unit tests against. In our custom MVC code project, we had different projects (class libraries) for the model, the view, and the controllers. The default directory structure of an ASP.NET MVC Application has three top-level directories: /Controllers /Models /Views When the project becomes large, it is recommended that the Model, Views and Controllers are put in separate class library projects of their own so that it's easy to maintain them. But for the purpose of illustrating the ASP.NET MVC framework, this default structure is fine for us. We will create a simple customer management application. For this, we first create some ASPX pages in the Views folder. Note that VS has already created these subfolders for us, under Views: Home: Contains the and Index views Shared: Contains shared views such as master pages Before we go on to adding custom code in this project, let us understand what VS has done for us while creating this MVC project. URL Routing Engine In the standard ASP.NET model (or Postback model), the URLs map directly to the physical files: So when we make a request to a page, say MyPage.aspx, the runtime compiles that page and returns the generated HTML back to IIS to be displayed by the client browser. So we have a one-to-one relationship between the application URLs and the page. But in the MVC framework, the URLs map to the controller classes. Therefore, the URL is sent to IIS and then to ASP.NET runtime, where it initiates a controller class based on the URL, using the URL routes, and the controller class then loads the data from the model, with this data finally being rendered in the view. The controller classes uses URL routing to map the URLs, which in simpler terms means rewriting URL. We can set up the rules for which URL is to be routed to which controller class. The routing will pick up the appropriate controller and pass in the query string variables as necessary. Open the global.asax.cs file and examine the following code: public class GlobalApplication : System.Web.HttpApplication{public static void RegisterRoutes(RouteCollection routes){routes.IgnoreRoute("{resource}.axd/{*pathInfo}");routes.MapRoute("Default", // Route name"{controller}/{action}/{id}", // URL with parametersnew { controller = "Home", action = "Index", id = "" }// Parameter defaults);}protected void Application_Start(){RegisterRoutes(RouteTable.Routes);} The RegisterRoutes() method contains the URL mapping routes. Initially we have only the default rule set: routes.MapRoute("Default", // Route name"{controller}/{action}/{id}", // URL with parametersnew { controller = "Home", action = "Index", id = "" } // Parameter defaults); The RegisterRoutes() method contains the URL mapping routes. Initially we have only the default rule set: The MapRoute() method, which handles URL routing and mapping, takes three arguments: Name of the route (string) URL format (string) Default settings (object type) In our case, we named the first route "Default" (which is the route name) and then set the URL as: Controller/action/id The Controller here is the name of the controller class. action will be the method that needs to be invoked inside that controller class. id would be the parameters that need to be passed, if any. In the default arguments, we create a new object and call it "Home", set the action to Index, and do not pass parameters to it. Note the new anonymous type syntax used to create parameter defaults: new { controller = "Home", action = "Index", id = "" } The var keyword and anonymous types: We normally use classes to wrap behavior and properties, but in C# 3.0, we can create the types anonymously without needing to create classes for them. This can be useful when we need to create light weight classes that have only read-only properties. We can use the anonymous syntax to create those types without the need to create a class for them. We can use the new "var" keyword to hold such anonymous types, for example: var ch = new { readOnlyProperty1 = value1, readOnlyProperty2 = value2 }; It is important that we name and assign a value to each of the properties that we are creating. What will be the type of the properties? They will automatically be cast to the data types of the values of the properties specified. The anonymous types will always be derived from the base object class directly. They can only be used within class members and cannot be passed as method arguments (unless they are boxed), return values, or be specified as class-level variables. Once the type is created, it cannot be changed into another type. So we create a new anonymous type as the last argument of the MapRoute() method, passing in variable defaults with three properties, namely controller, action, and parameter. Now have the Default.aspx page under the root directory, which acts as a redirecting page to the main home page of the site (which is /View/Home/Index.aspx). We cannot directly set that as the "default" page since we are using URL routes to process pages instead of using physical files in the URLs. So in the code-behind of our Default.aspx page, we have a simple redirect: public void Page_Load(object sender, System.EventArgs e){Response.Redirect("~/Home");} So the runtime will first set up routes in the global.asax page, then it will process the Default.aspx page. Here it faces a redirect to this URL: /Home. The Controller The MVC framework maps this URL to the route set in the global route table, which currently has only the default one, in this format: Controller/action/id So /Home corresponds to a controller named Home, and because we have not specified any action or ID, it takes the default values we specified in the RegisterRoutes() method in the globals.asax.cs. So the default action was Index and the default parameter was an empty string. The runtime initializes the HomeController.cs class, and fires the Index action there: public class HomeController : Controller{public ActionResult Index(){ViewData["Title"] = "Home Page";ViewData["Message"] = "Welcome to ASP.NET MVC!";return View();}} In this Index() method, we set the data to be displayed in the View (aspx/ascx pages) by using a dictionary property of the base Controller class named ViewData. ViewData, as the name suggests, is used to set view-specific data in a dictionary object that can hold multiple name/value pairs. When we call the View() method, the ViewData is passed by the Controller to the View and rendered there.
Read more
  • 0
  • 0
  • 3802
article-image-cherrypy-photoblog-application
Packt
22 Oct 2009
6 min read
Save for later

CherryPy : A Photoblog Application

Packt
22 Oct 2009
6 min read
A photoblog is like a regular blog except that the principal content is not text but photographs. The main reason for choosing a photoblog is that the range of features to be implemented is small enough so that we can concentrate on their design and implementation. The goals behind going through this application are as follows: To see how to slice the development of a web application into meaningful layers and therefore show that a web application is not very different from a rich application sitting on your desktop. To show that the separation of concerns can also be applied to the web interface itself by using principles grouped under the name of Ajax. To introduce common Python packages for dealing with common aspects of web development such as database access, HTML templating, JavaScript handling, etc. Photoblog Entities As mentioned earlier, the photoblog will try to stay as simple as possible in order to focus on the other aspects of developing a web application. In this section, we will briefly describe the entities our photoblog will manipulate as well as their attributes and relations with each other. In a nutshell our photoblog application will use the following entities and they will be associated as shown in the following figure: This figure is not what our application will look like but it shows the entities our application will manipulate. One photoblog will contain several albums, which in turn will host as many films as required, which will carry the photographs. In other words, we will design our application with the following entity structure: Entity: Photoblog Role: This entity will be the root of the application. Attributes: name: A unique identifier for the blog title: A public label for the blog Relations: One photoblog will have zero to many albums Entity: Album Role: An album carries a story told by the photographs as an envelope. Attributes: name: A unique identifier for the album title: A public label for the album author: The name of the album's author description: A simple description of the album used in feeds story: A story attached to the album created: A timestamp of when the album is being created modified: A timestamp of when the album is being modified blog_id: A reference to the blog handling the album Relations: One album will reference zero to several films Entity: Film Role: A film gathers a set of photographs. Attributes: name: A unique identifier for the film title: A public label for the film created: A timestamp of when the film is being created modified: A timestamp of when the film is being modified album_id: A reference to the album Relations: A film will reference zero to several photographs Entity: Photo Role: The unit of our application is a photograph. Attributes: name: A unique identifier for the photo legend: A legend associated with the photograph filename: The base name of the photograph on the hard-disk filesize: The size in bytes of the photograph width: Width of the photograph in pixels height: Height of the photograph in pixels created: A timestamp of when the photograph is being created modified: A timestamp of when the photograph is being modified film_id: A reference to the film carrying the photograph Relations: None Functionally, the photoblog application will provide APIs to manipulate those entities via the traditional CRUD interface: Create, Retrieve, Update, and Delete. Vocabulary Here is a list of the terms we will be using: Persistence: Persistence is the concept of data items outliving the execution of programs manipulating them. Simply put, it is the process of storing data in long lasting memory medium such as a disk. Database: A database is a collection of organized data. There are different organization models: hierarchical, network, relational, object-oriented, etc. A database holds the logical representation of its data. Database Management System (DBMS): A DBMS is a group of related software applications to manipulate data in a database. A DBMS platform should offer the following among other features: Persistence of the data A query language to manipulate data Concurrency control Security control Integrity control Transaction capabilities We will use DBMSes as the plural of DBMS. DBMSes Overview In this section, we will quickly review the different kinds of existing DBMSes. The goal is to quickly introduce their main characteristics. Relational Database Management System (RDBMS) Of all DBMSes, the RDBMS is the most common, whether it is in small applications or multi-national infrastructure. An RDBMS comes with a database based on the concepts of the relational model, a mathematical model that permits the logical representation of a collection of data through relations. A relational database should be a concrete implementation of the relational model. However, modern relational databases follow the model only to a certain degree. The following table shows the correlation between the terms of the relational model and the relational database implementation. Relational databases support a set of types to define the domain of scope a column can use. However, there are only a limited number of supported types, which can be an issue with complex data types as allowed in objected-oriented design. Structure Query Language more commonly known as SQL is the language used to define, manipulate, or control data within a relational database. The following table is a quick summary of SQL keywords and their contexts. A construction of these keywords is called an SQL statement. When executed, an SQL statement returns a collection of rows of the data matching the query or nothing. The relational model algebra uses the relation composition to compose operations across different sets; this is translated in the relational database context by joins. Joining tables allows complex queries to be shaped to filter out data. SQL provides the following three kinds of joins:   Union Type Description INNER JOIN Intersection between two tables. LEFT OUTER JOIN Limits the result set by the left table. So all results from the left table will be returned with their matching result in the right table. If no matching result is found, it will return a NULL value. RIGHT OUTER JOIN Same as the LEFT OUTER JOIN except that the tables are reversed.  
Read more
  • 0
  • 0
  • 1901

article-image-creating-analysis-services-cube-visual-studio-2008-part-2
Packt
22 Oct 2009
2 min read
Save for later

Creating an Analysis Services Cube with Visual Studio 2008 - Part 2

Packt
22 Oct 2009
2 min read
Reviewing Jayaram's other OLAP related articles may greatly help in understanding this article. Creating a New Cube The folder structure for the project developed in Part 1 is shown in the next figure. The Northwind.ds data source and the Northwind.dsv data source view were configured in Part 1. There are no pre-existing cubes in Nwind2008. Right click the Cubes folder and from the drop-down menu you can create a new Cube. Click on New Cube... menu item. This opens the Cube Wizard welcome window as shown. Click on the Next button. This opens the Select Creation Method page of the wizard as shown. There are three options and the default is used for this article. Click on the Next button. This opens the Select Measure Groups tables. At least one table must be chosen to continue. There is even the option of asking for a suggestion. Click on the Suggest button at the top. The program goes through the motions and comes up with two tables as candidates for Measures group, the Products table and the Order Details table. You will see check marks appearing for these two tables. Accept the suggested tables for measures and click on the Next button. This opens the Select Measures window where you can choose measures that you want to include in the Cube as shown. Uncheck the ID related items in the Products table and click on the Next button. This brings up the Select New Dimensions window as shown in the next figure. Here also one could choose the needed items. For this article the default is accepted. Click on the Next button. This takes you to the Completing the Wizard window which shows your Cube contents in a tree view as shown. Now click on the Finish button. This creates the Cube as shown in the Solution Explorer. Now you will see additional tabs open up for the Northwind.cube as shown. Using these tabs you can look at more details. These are outside the scope of this article. Also separate windows gets displayed for Cube's Measures and Dimensions as shown. Also, the Data Source View of the Cube with the relationships between the Dimensions and Measures gets displayed as shown.    
Read more
  • 0
  • 0
  • 4200
Modal Close icon
Modal Close icon