{"id":75186,"date":"2020-01-18T12:24:40","date_gmt":"2020-01-18T06:54:40","guid":{"rendered":"https:\/\/www.vskills.in\/certification\/tutorial\/?p=75186"},"modified":"2024-04-12T14:17:11","modified_gmt":"2024-04-12T08:47:11","slug":"your-second-view-dynamic-urls","status":"publish","type":"page","link":"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/","title":{"rendered":"Your Second View: Dynamic URLs"},"content":{"rendered":"<p>The \u201cHello world\u201d view was instructive in demonstrating the basics of how Django works, but it wasn\u2019t an example of a dynamic web page, because the content of the page is always the same. Every time you view \/hello\/, you\u2019ll see the same thing; it might as well be a static HTML file.<\/p>\n<p>For our second view, let\u2019s create something more dynamic \u2013 a web page that displays the current date and time. This is a nice, simple next step, because it doesn\u2019t involve a database or any user input \u2013 just the output of your server\u2019s internal clock. It\u2019s only marginally more exciting than \u201cHello world,\u201d but it\u2019ll demonstrate a few new concepts.<\/p>\n<p>This new view needs to do two things: calculate the current date and time, and return an HttpResponse containing that value. If you have experience with Python, you know that Python includes a datetime module for calculating dates. Here\u2019s a demonstration using the Python interactive interpreter:<\/p>\n<pre>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 C:\\Users\\nigel&gt;python\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (Intel)] on win32\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Type \"help\", \"copyright\", \"credits\" or \"license\" for more information.\r\n\r\n<\/pre>\n<p>&gt;&gt; import datetime<\/p>\n<p>&gt;&gt; now = datetime.datetime.now()<\/p>\n<p>&gt;&gt; now<\/p>\n<pre>        datetime.datetime(2017, 5, 20, 14, 32, 25, 412665)\r\n  \r\n        &gt;&gt;&gt; print (now)\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 2017-05-20 14:32:25.412665\r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &gt;&gt;&gt;<\/pre>\n<p>That\u2019s simple enough, and it has nothing to do with Django. It\u2019s just Python code. (I want to emphasize that you should be aware of what code is \u201cjust Python\u201d vs. code that is Django-specific. As you learn Django, I want you to be able to apply your knowledge to other Python projects that don\u2019t necessarily use Django.)<\/p>\n<p>To make a Django view that displays the current date and time, we just need to hook this datetime.datetime.now() statement into a view and return an HttpResponse. Here\u2019s what the updated views.py looks like:<\/p>\n<pre>from django.http import HttpResponse\r\n\r\nimport datetime\r\n\r\ndef hello(request):\u00a0\u00a0\u00a0 \r\n\r\nreturn HttpResponse(\"Hello world\")\u00a0\r\n\r\ndef current_datetime(request):\u00a0\u00a0\u00a0 \r\n\r\nnow = datetime.datetime.now()\u00a0\u00a0\u00a0 \r\n\r\nhtml = \"&lt;html&gt;&lt;body&gt;It is now %s.&lt;\/body&gt;&lt;\/html&gt;\" % now\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\r\n\r\n return HttpResponse(html)<\/pre>\n<p>Let\u2019s step through the changes we\u2019ve made to views.py to accommodate the current_datetime view.<\/p>\n<ul>\n<li>We\u2019ve added an import datetime to the top of the module, so we can calculate dates.<\/li>\n<li>The new current_datetime function calculates the current date and time, as a datetime.datetime object, and stores that as the local variable now.<\/li>\n<li>The second line of code within the view constructs an HTML response using Python\u2019s \u201cformat-string\u201d capability. The %s within the string is a placeholder, and the percent sign after the string means \u201cReplace the %s in the preceding string with the value of the variable now.\u201d The now variable is technically a datetime.datetime object, not a string, but the %s format character converts it to its string representation, which is something like \u201c2017-05-20 14:32:25.412665\u201c. This will result in an HTML string such as \u201cIt is now 2017-05-20 14:32:25.412665.\u201c.<\/li>\n<li>Finally, the view returns an HttpResponse object that contains the generated response \u2013 just as we did in hello.<\/li>\n<\/ul>\n<p>After adding that to views.py, add the URLpattern to urls.py to tell Django which URL should handle this view. Something like \/time\/ would make sense:<\/p>\n<pre>from django.conf.urls import url\r\n\r\nfrom django.contrib import admin\u00a0\r\n\r\nfrom mysite.views import hello, current_datetime\u00a0\r\n\r\nurlpatterns = [\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 url(r'^admin\/', admin.site.urls),\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 url(r'^hello\/$', hello),\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 url(r'^time\/$', current_datetime),]<\/pre>\n<p>We\u2019ve made two changes here. First, we imported the current_datetime function at the top. Second, and more importantly, we added a URLpattern mapping the URL \/time\/ to that new view. Getting the hang of this? With the view written and URLconf updated, fire up the development server and visit http:\/\/127.0.0.1:8000\/time\/ in your browser. You should see the current date and time.<\/p>\n<p><strong>A Word About Pretty URLs<\/strong> &#8211; If you\u2019re experienced in another Web development platform, such as PHP or Java, you may be thinking, \u201cHey, let\u2019s use a query string parameter!\u201d, something like \/time\/plus?hours=3, in which the hours would be designated by the hours parameter in the URL\u2019s query string (the part after the ?).<\/p>\n<p>You <em>can<\/em> do that with Django (and we\u2019ll tell you how later, if you really must know), but one of Django\u2019s core philosophies is that URLs should be beautiful. The URL \/time\/plus\/3\/ is far cleaner, simpler, more readable, easier to recite to somebody aloud and \u2026 just plain prettier than its query string counterpart. Pretty URLs are a sign of a quality Web application.<\/p>\n<p>Django\u2019s URLconf system encourages pretty URLs by making it easier to use pretty URLs than <em>not<\/em> to.<\/p>\n<p><strong>Wildcard URLpatterns<\/strong> &#8211; Continuing with our hours_ahead example, let\u2019s put a wildcard in the URLpattern. As we mentioned previously, a URLpattern is a regular expression; hence, we can use the regular expression pattern \\d+ to match one or more digits:<\/p>\n<pre>from django.conf.urls.defaults import *\r\n\r\nfrom mysite.views import current_datetime, hours_ahead\r\n\r\nurlpatterns = patterns('',\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (r'^time\/$', current_datetime),\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (r'^time\/plus\/\\d+\/$', hours_ahead),)<\/pre>\n<p>This URLpattern will match any URL such as \/time\/plus\/2\/, \/time\/plus\/25\/, or even \/time\/plus\/100000000000\/. Come to think of it, let\u2019s limit it so that the maximum allowed offset is 99 hours. That means we want to allow either one- or two-digit numbers\u2014in regular expression syntax, that translates into \\d{1,2}:<\/p>\n<pre>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (r'^time\/plus\/\\d{1,2}\/$', hours_ahead),<\/pre>\n<p><strong>Note<\/strong> &#8211; When building Web applications, it\u2019s always important to consider the most outlandish data input possible, and decide whether or not the application should support that input. We\u2019ve curtailed the outlandishness here by limiting the offset to 99 hours. And, by the way, The Outlandishness Curtailers would be a fantastic, if verbose, band name.<\/p>\n<p>Now that we\u2019ve designated a wildcard for the URL, we need a way of passing that data to the view function, so that we can use a single view function for any arbitrary hour offset. We do this by placing parentheses around the data in the URLpattern that we want to save. In the case of our example, we want to save whatever number was entered in the URL, so let\u2019s put parentheses around the \\d{1,2}:<\/p>\n<pre>\u00a0\u00a0\u00a0 (r'^time\/plus\/(\\d{1,2})\/$', hours_ahead),<\/pre>\n<p>If you\u2019re familiar with regular expressions, you\u2019ll be right at home here; we\u2019re using parentheses to <em>capture<\/em> data from the matched text. The final URLconf, including our previous current_datetime view, looks like this:<\/p>\n<pre>from django.conf.urls.defaults import *\r\n\r\nfrom mysite.views import current_datetime, hours_ahead\r\n\r\n\u00a0urlpatterns patterns('',\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (r'^time\/$', current_datetime),\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (r'^time\/plus\/(\\d{1,2})\/$', hours_ahead),)<\/pre>\n<p>With that taken care of, let\u2019s write the hours_ahead view.<\/p>\n<p><strong>Coding Order<\/strong> &#8211; In this example, we wrote the URLpattern first and the view second, but in the previous example, we wrote the view first, then the URLpattern. Which technique is better? Well, every developer is different. If you\u2019re a big-picture type of person, it may make the most sense to you to write all of the URLpatterns for your application at the same time, at the start of your project, and then code up the views. This has the advantage of giving you a clear to-do list, and it essentially defines the parameter requirements for the view functions you\u2019ll need to write. If you\u2019re more of a bottom-up developer, you might prefer to write the views first, and then anchor them to URLs afterward. That\u2019s OK, too. In the end, it comes down to which technique fits your brain the best. Both approaches are valid.hours_ahead is very similar to the current_datetime view we wrote earlier, with a key difference: it takes an extra argument, the number of hours of offset. Add this to views.py:<\/p>\n<pre>\u00a0def hours_ahead(request, offset):\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 offset = int(offset)\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 dt = datetime.datetime.now() + datetime.timedelta(hours=offset)\u00a0\u00a0\u00a0 \r\n\r\nhtml = \"&lt;html&gt;&lt;body&gt;In %s hour(s), it will be %s.&lt;\/body&gt;&lt;\/html&gt;\" % \r\n\r\n(offset, dt)\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 return HttpResponse(html)\r\n\r\n\r\n<\/pre>\n<p>Let\u2019s step through this code one line at a time:<\/p>\n<ul>\n<li>Just as we did for our current_datetime view, we import the class django.http.HttpResponse and the datetime module.<\/li>\n<li>The view function, hours_ahead, takes <em>two<\/em> parameters: request and offset.<\/li>\n<li>request is an HttpRequest object, just as in current_datetime. We\u2019ll say it again: each view <em>always<\/em> takes an HttpRequest object as its first parameter.<\/li>\n<li>offset is the string captured by the parentheses in the URLpattern. For example, if the requested URL were \/time\/plus\/3\/, then offset would be the string &#8216;3&#8217;. If the requested URL were \/time\/plus\/21\/, then offset would be the string &#8217;21&#8217;. Note that captured strings will always be <em>strings<\/em>, not integers, even if the string is composed of only digits, such as &#8217;21&#8217;.<\/li>\n<li>We decided to call the variable offset, but you can call it whatever you\u2019d like, as long as it\u2019s a valid Python identifier. The variable name doesn\u2019t matter; all that matters is that it\u2019s the second argument to the function (after request). It\u2019s also possible to use keyword, rather than positional, arguments in an URLconf.<\/li>\n<li>The first thing we do within the function is call int() on offset. This converts the string value to an integer.<\/li>\n<li>Note that Python will raise a ValueError exception if you call int() on a value that cannot be converted to an integer, such as the string &#8216;foo&#8217;. However, in this example we don\u2019t have to worry about catching that exception, because we can be certain offset will be a string containing only digits. We know that because the regular-expression pattern in our URLconf\u2014 (\\d{1,2})\u2014captures only digits. This illustrates another nicety of URLconfs: they provide a fair level of input validation.<\/li>\n<li>The next line of the function shows why we called int() on offset. On this line, we calculate the current time plus a time offset of offset hours, storing the result in dt. The datetime.timedelta function requires the hours parameter to be an integer.<\/li>\n<li>Next, we construct the HTML output of this view function, just as we did in current_datetime. A small difference in this line from the previous line is that it uses Python\u2019s format-string capability with <em>two<\/em> values, not just one. Hence, there are two %s symbols in the string and a tuple of values to insert: (offset, dt).<\/li>\n<li>Finally, we return an HttpResponse of the HTML\u2014again, just as we did in current_datetime.<\/li>\n<\/ul>\n<p>With that view function and URLconf written, start the Django development server (if it\u2019s not already running), and visit http:\/\/127.0.0.1:8000\/time\/plus\/3\/ to verify it works. Then try http:\/\/127.0.0.1:8000\/time\/plus\/5\/. Then http:\/\/127.0.0.1:8000\/time\/plus\/24\/. Finally, visit http:\/\/127.0.0.1:8000\/time\/plus\/100\/ to verify that the pattern in your URLconf only accepts one- or two-digit numbers; Django should display a \u201cPage not found\u201d error in this case, just as we saw in the \u201c404 Errors\u201d section earlier. The URL http:\/\/127.0.0.1:8000\/time\/plus\/ (with <em>no<\/em> hour designation) should also throw a 404.<\/p>\n<p>If you\u2019re following along while coding at the same time, you\u2019ll notice that the views.py file now contains two views. (We omitted the current_datetime view from the last set of examples for clarity.) Put together, views.py should look like this:<\/p>\n<pre>from django.http import HttpResponse\r\n\r\nimport datetime\r\n\r\ndef current_datetime(request):\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0 now = datetime.datetime.now()\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0 html = \"&lt;html&gt;&lt;body&gt;It is now %s.&lt;\/body&gt;&lt;\/html&gt;\" % now\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0 return HttpResponse(html)\u00a0\r\n\r\ndef hours_ahead(request, offset):\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0 offset = int(offset)\u00a0\u00a0\u00a0\r\n\r\n\u00a0\u00a0 dt = datetime.datetime.now() + datetime.timedelta(hours=offset)\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0 html = \"&lt;html&gt;&lt;body&gt;In %s hour(s), it will be %s.&lt;\/body&gt;&lt;\/html&gt;\" % \r\n\r\n(offset, dt)\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0 return HttpResponse(html)<\/pre>\n<h3>Your Third View: Dynamic URLs<\/h3>\n<p>In our current_datetime view, the contents of the page \u2013 the current date\/time \u2013 were dynamic, but the URL (\/time\/) was static. In most dynamic web applications though, a URL contains parameters that influence the output of the page. For example, an online bookstore might give each book its own URL, like \/books\/243\/ and \/books\/81196\/.<\/p>\n<p>Let\u2019s create a third view that displays the current date and time offset by a certain number of hours. The goal is to craft a site in such a way that the page \/time\/plus\/1\/ displays the date\/time one hour into the future, the page \/time\/plus\/2\/ displays the date\/time two hours into the future, the page \/time\/plus\/3\/ displays the date\/time three hours into the future, and so on.<\/p>\n<p>A novice might think to code a separate view function for each hour offset, which might result in a URLconf like this:<\/p>\n<pre>\u00a0\u00a0\u00a0\u00a0 urlpatterns = [\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0 url(r'^time\/$', current_datetime),\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0 url(r'^time\/plus\/1\/$', one_hour_ahead),\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 url(r'^time\/plus\/2\/$', two_hours_ahead),\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 url(r'^time\/plus\/3\/$', three_hours_ahead),]<\/pre>\n<p>Clearly, this line of thought is flawed. Not only would this result in redundant view functions, but also the application is fundamentally limited to supporting only the predefined hour ranges \u2013 one, two or three hours.<\/p>\n<p>If we decided to create a page that displayed the time four hours into the future, we\u2019d have to create a separate view and URLconf line for that, furthering the duplication.<\/p>\n<p>How, then do we design our application to handle arbitrary hour offsets? The key is to use wildcard URLpatterns. As I mentioned previously, a URLpattern is a regular expression; hence, we can use the regular expression pattern \\d+ to match one or more digits:<\/p>\n<pre>urlpatterns = [\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # ...\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 url(r'^time\/plus\/\\d+\/$', hours_ahead),\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # ...\r\n\r\n\u00a0\u00a0\u00a0 ]\r\n\r\n\r\n<\/pre>\n<p>(I\u2019m using the # &#8230; to imply there might be other URLpatterns that have been trimmed from this example.) This new URLpattern will match any URL such as \/time\/plus\/2\/, \/time\/plus\/25\/, or even \/time\/plus\/100000000000\/. Come to think of it, let\u2019s limit it so that the maximum allowed offset is something reasonable.<\/p>\n<p>In this example, we will set a maximum 99 hours by only allowing either one- or two-digit numbers \u2013 and in regular expression syntax, that translates into \\d{1,2}:<\/p>\n<pre>\u00a0,\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 url(r'^time\/plus\/\\d{1,2}\/$', hours_ahead),<\/pre>\n<p>Now that we\u2019ve designated a wildcard for the URL, we need a way of passing that wildcard data to the view function, so that we can use a single view function for any arbitrary hour offset. We do this by placing parentheses around the data in the URLpattern that we want to save. In the case of our example, we want to save whatever number was entered in the URL, so let\u2019s put parentheses around the \\d{1,2},<\/p>\n<p>like this:<\/p>\n<pre>url(r'^time\/plus\/(\\d{1,2})\/$', hours_ahead),<\/pre>\n<p>If you\u2019re familiar with regular expressions, you\u2019ll be right at home here; we\u2019re using parentheses to capture data from the matched text. The final URLconf, including our previous two views, looks like this:<\/p>\n<pre>from django.conf.urls import include, url\r\n\r\nfrom django.contrib import admin\r\n\r\nfrom mysite.views import hello, current_datetime, hours_ahead\u00a0\r\n\r\nurlpatterns = [\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 url(r'^admin\/', admin.site.urls),\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0 url(r'^hello\/$', hello),\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 url(r'^time\/$', current_datetime),\u00a0\u00a0\u00a0 \r\n\r\n\u00a0\u00a0\u00a0\u00a0 \u00a0 url(r'^time\/plus\/(\\d{1,2})\/$', hours_ahead),]<\/pre>\n<p>If you\u2019re experienced in another web development platform, you may be thinking, \u201cHey, let\u2019s use a query string parameter!\u201d \u2013 something like \/time\/plus?hours=3, in which the hours would be designated by the hours parameter in the URL\u2019s query string (the part after the \u2018?\u2019).You can do that with Django, but one of Django\u2019s core philosophies is that URLs should be beautiful.<\/p>\n<p>The URL \/time\/plus\/3\/ is far cleaner, simpler, more readable, easier to recite to somebody aloud and just plain prettier than its query string counterpart. Pretty URLs are a characteristic of a quality web application. Django\u2019s URLconf system encourages pretty URLs by making it easier to use pretty URLs than not to.<\/p>\n<p>With that taken care of, let\u2019s write the hours_ahead view. hours_ahead is very similar to the current_datetime view we wrote earlier, with a key difference: it takes an extra argument, the number of hours of offset. Here\u2019s the view code:<\/p>\n<pre>from django.http \r\n\r\nimport Http404, HttpResponseimport datetime\u00a0\r\n\r\ndef hours_ahead(request, offset):\u00a0\u00a0\u00a0 \r\n\r\ntry:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \r\n\r\noffset = int(offset)\u00a0\u00a0\u00a0 \r\n\r\nexcept ValueError:\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \r\n\r\nraise Http404()\u00a0\u00a0\u00a0 \r\n\r\ndt = datetime.datetime.now() + datetime.timedelta(hours=offset)\u00a0\u00a0\u00a0 \r\n\r\nhtml = \"&lt;html&gt;&lt;body&gt;In %s hour(s), it will be\u00a0 %s.&lt;\/body&gt;&lt;\/html&gt;\" % \r\n\r\n(offset, dt)\u00a0\u00a0\u00a0 \r\n\r\nreturn HttpResponse(html)<\/pre>\n<p>Let\u2019s take a closer look at this code. The view function, hours_ahead, takes two parameters: request and offset:<\/p>\n<ul>\n<li>request is an HttpRequest object, just as in hello and current_datetime. I\u2019ll say it again: each view always takes an HttpRequest object as its first parameter.<\/li>\n<li>offset is the string captured by the parentheses in the URLpattern. For example, if the requested URL were \/time\/plus\/3\/, then offset would be the string \u20183\u2019. If the requested URL were \/time\/plus\/21\/, then offset would be the string \u201921\u2019. Note that captured values will always be Unicode objects, not integers, even if the string is composed of only digits, such as \u201921\u2019.<\/li>\n<\/ul>\n<p>I decided to call the variable offset, but you can call it whatever you\u2019d like, as long as it\u2019s a valid Python identifier. The variable name doesn\u2019t matter; all that matters is that it\u2019s the second argument to the function, after request. (It\u2019s also possible to use keyword, rather than positional, arguments in an URLconf.)<\/p>\n<p>The first thing we do within the function is call int() on offset. This converts the Unicode string value to an integer.<\/p>\n<p>Note that Python will raise a ValueError exception if you call int() on a value that cannot be converted to an integer, such as the string \u201cfoo\u201d. In this example, if we encounter the ValueError, we raise the exception django.http.Http404, which, as you can imagine, results in a 404 \u201cPage not found\u201d error.<\/p>\n<p>Astute readers will wonder: how could we ever reach the ValueError case, anyway, given that the regular expression in our URLpattern \u2013 (\\d{1,2}) \u2013 captures only digits, and therefore offset will only ever be a string composed of digits? The answer is, we won\u2019t, because the URLpattern provides a modest but useful level of input validation, but we still check for the ValueError in case this view function ever gets called in some other way. It\u2019s good practice to implement view functions such that they don\u2019t make any assumptions about their parameters. Loose coupling, remember?<\/p>\n<p>In the next line of the function, we calculate the current date\/time and add the appropriate number of hours. We\u2019ve already seen datetime.datetime.now() from the current_datetime view; the new concept here is that you can perform date\/time arithmetic by creating a datetime.timedelta object and adding to a datetime.datetime object. Our result is stored in the variable dt.<\/p>\n<p>This line also shows why we called int() on offset \u2013 the datetime.timedelta function requires the hours parameter to be an integer. Next, we construct the HTML output of this view function, just as we did in current_datetime. A small difference in this line from the previous line is that it uses Python\u2019s format-string capability with two values, not just one. Hence, there are two %s symbols in the string and a tuple of values to insert: (offset, dt).<\/p>\n<p>Finally, we return an HttpResponse of the HTML. With that view function and URLconf written, start the Django development server (if it\u2019s not already running), and visit http:\/\/127.0.0.1:8000\/time\/plus\/3\/ to verify it works.<\/p>\n<p>Then try http:\/\/127.0.0.1:8000\/time\/plus\/5\/.<\/p>\n<p>Then http:\/\/127.0.0.1:8000\/time\/plus\/24\/.<\/p>\n<p>Finally, visit http:\/\/127.0.0.1:8000\/time\/plus\/100\/ to verify that the pattern in your URLconf only accepts one- or two-digit numbers; Django should display a \u201cPage not found\u201d error in this case, just as we saw in the section \u201cA Quick Note About 404 Errors\u201d earlier. The URL http:\/\/127.0.0.1:8000\/time\/plus\/ (with no hour designation) should also throw a 404.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The \u201cHello world\u201d view was instructive in demonstrating the basics of how Django works, but it wasn\u2019t an example of a dynamic web page, because the content of the page is always the same. Every time you view \/hello\/, you\u2019ll see the same thing; it might as well be a static HTML file. For our&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"categories":[8655],"tags":[8662],"class_list":["post-75186","page","type-page","status-publish","hentry","category-django-web-development","tag-dynamic-urls"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Your Second View: Dynamic URLs - Tutorial<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Your Second View: Dynamic URLs - Tutorial\" \/>\n<meta property=\"og:description\" content=\"The \u201cHello world\u201d view was instructive in demonstrating the basics of how Django works, but it wasn\u2019t an example of a dynamic web page, because the content of the page is always the same. Every time you view \/hello\/, you\u2019ll see the same thing; it might as well be a static HTML file. For our...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/\" \/>\n<meta property=\"og:site_name\" content=\"Tutorial\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/vskills.in\/\" \/>\n<meta property=\"article:modified_time\" content=\"2024-04-12T08:47:11+00:00\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"17 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/\",\"url\":\"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/\",\"name\":\"Your Second View: Dynamic URLs - Tutorial\",\"isPartOf\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#website\"},\"datePublished\":\"2020-01-18T06:54:40+00:00\",\"dateModified\":\"2024-04-12T08:47:11+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.vskills.in\/certification\/tutorial\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Your Second View: Dynamic URLs\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#website\",\"url\":\"https:\/\/www.vskills.in\/certification\/tutorial\/\",\"name\":\"Tutorial\",\"description\":\"Vskills - A initiative in elearning and certification\",\"publisher\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.vskills.in\/certification\/tutorial\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#organization\",\"name\":\"Vskills\",\"url\":\"https:\/\/www.vskills.in\/certification\/tutorial\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.vskills.in\/certification\/tutorial\/wp-content\/uploads\/2017\/07\/vskills-min-logo.jpg\",\"contentUrl\":\"https:\/\/www.vskills.in\/certification\/tutorial\/wp-content\/uploads\/2017\/07\/vskills-min-logo.jpg\",\"width\":73,\"height\":55,\"caption\":\"Vskills\"},\"image\":{\"@id\":\"https:\/\/www.vskills.in\/certification\/tutorial\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/vskills.in\/\",\"https:\/\/x.com\/vskills_in\",\"https:\/\/www.linkedin.com\/company-beta\/1371554\/\",\"https:\/\/www.youtube.com\/channel\/UCMWnscxPwRF_PqXo9B7q_Tw\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Your Second View: Dynamic URLs - Tutorial","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/","og_locale":"en_US","og_type":"article","og_title":"Your Second View: Dynamic URLs - Tutorial","og_description":"The \u201cHello world\u201d view was instructive in demonstrating the basics of how Django works, but it wasn\u2019t an example of a dynamic web page, because the content of the page is always the same. Every time you view \/hello\/, you\u2019ll see the same thing; it might as well be a static HTML file. For our...","og_url":"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/","og_site_name":"Tutorial","article_publisher":"https:\/\/www.facebook.com\/vskills.in\/","article_modified_time":"2024-04-12T08:47:11+00:00","twitter_misc":{"Est. reading time":"17 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/","url":"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/","name":"Your Second View: Dynamic URLs - Tutorial","isPartOf":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#website"},"datePublished":"2020-01-18T06:54:40+00:00","dateModified":"2024-04-12T08:47:11+00:00","breadcrumb":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/your-second-view-dynamic-urls\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.vskills.in\/certification\/tutorial\/"},{"@type":"ListItem","position":2,"name":"Your Second View: Dynamic URLs"}]},{"@type":"WebSite","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#website","url":"https:\/\/www.vskills.in\/certification\/tutorial\/","name":"Tutorial","description":"Vskills - A initiative in elearning and certification","publisher":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.vskills.in\/certification\/tutorial\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#organization","name":"Vskills","url":"https:\/\/www.vskills.in\/certification\/tutorial\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#\/schema\/logo\/image\/","url":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-content\/uploads\/2017\/07\/vskills-min-logo.jpg","contentUrl":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-content\/uploads\/2017\/07\/vskills-min-logo.jpg","width":73,"height":55,"caption":"Vskills"},"image":{"@id":"https:\/\/www.vskills.in\/certification\/tutorial\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/vskills.in\/","https:\/\/x.com\/vskills_in","https:\/\/www.linkedin.com\/company-beta\/1371554\/","https:\/\/www.youtube.com\/channel\/UCMWnscxPwRF_PqXo9B7q_Tw"]}]}},"_links":{"self":[{"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/pages\/75186","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/comments?post=75186"}],"version-history":[{"count":3,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/pages\/75186\/revisions"}],"predecessor-version":[{"id":76795,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/pages\/75186\/revisions\/76795"}],"wp:attachment":[{"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/media?parent=75186"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/categories?post=75186"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.vskills.in\/certification\/tutorial\/wp-json\/wp\/v2\/tags?post=75186"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}