Intro to Django

Intro to Django – Building a To-Do List

Feb 1st in Other by Logan Mortimer

Django is a powerful web framework, created in Python, which follows the DRY (Don't repeat yourself), and batteries included philosophies. It allows for rapid website development by providing a wide range of tools and shortcuts out of the box. Django is extremely fast and flexible - even faster than all of the PHP frameworks available. In this article, I'll introduce you to Django by showing you how to build a simple to-do list.

PG

Author: Logan Mortimer

This is a NETTUTS contributor who has published 1 tutorial(s) so far here. Their bio is coming soon!

Why Django? Why Not X?

As stated above, Django follows the batteries included philosophy. PHP frameworks such as Code Igniter try and strip all of the "unnecessaries" out for maximum performance; but Django can include all of these out of the box and still be high performance because of its modular design (If you don't call include feature XX then it isn't included; so it doesn't slow the script down). Here are some of the most notable features:

  • User/Authentication system
  • Automatic RSS generation
  • GIS
  • Automatically generated Admin interface
  • Generic views (more on this later)
  • Three level caching system
  • Powerful template system
  • Comments

MTV

Django runs on an MTV (Model Template View) system (Not the television channel). This is different from MVC.

  • Model. The model sets out the schema for our database. Unlike PHP frameworks, you don't write your queries here. Using Django's ORM you declare the fields, field types and any additional data such as Meta information.
  • View. In the View, you set all of your code logic. You may need to pull some results from the database or manipulate some strings. The view expects a request and a response. The response is typically an http redirect, http error (404), or a call to load a template. When loading a template you usually pass some data through - most likely, results from a database query.
  • Template. The template is the plain HTML code with Django's custom Template 'language' (similar to smarty) in it. You look and iterate just like you would with any other language.

Creating Our To-Do List

We are going to create a very simple application, a to-do list, to showcase how to get started with Django. We'll use the automatically generated admin interface to add, edit and delete items. The ORM will be used to query the database. The view will pull get the to-do items and pass them onto the template where they are shown. I'm going to assume you have Django installed and running.

First, we need to create our project. To do this, we need to use the command line.

django-admin.py startproject todo
That should have created a directory called todo. Go into that directory. (cd todo)
manage.py startapp core
Yours should look similar to the image below.

Now that we have created the project, we need to input some settings. Open up todo/settings.py with your favorite text editor. Django supports a wide range of databases - MySQL, Postgres and Oracle, to name a few. Since we are only developing, we are going to use SQLite. SQLite only requires the name of the database to be specified.

Change Line 12 to:
DATABASE_ENGINE = 'sqlite3'           # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
Change Line 13 to:
DATABASE_NAME = 'to-do.db'             # Or path to database file if using sqlite3.

With the database set up. we only need to do a couple more edits in the settings file. On line 69, we need to set a full path to the templates directory where all of our HTML templates will be stored. Create the directory in /todo/core/ and then specify it on line 69. My template directory and installed apps tuple:

Finally, we need to add our application and the admin application into the INSTALLED APPS tuple. So on line 81, insert:

'django.contrib.admin',
'todo.core',
After
'django.contrib.sites',

That's it for the settings.py file.

Model

Now we need to specify our model. Open /todo/core/models.py with your text editor. As I said above, models define the structure of the database. There's no need to run raw CREATE TABLE.. SQL queries, Django can do all of this for us. We just need to specify what we want. Since its a to-do list - each to-do will have a title, some content, and the date it was published. It's very easy to represent this in Django.

from django.db import models

class todo(models.Model): #Table name, has to wrap models.Model to get the functionality of Django.
		
	name = models.CharField(max_length=100, unique=True) #Like a VARCHAR field
	description = models.TextField() #Like a TEXT field
	created = models.DateTimeField() #Like a DATETIME field

	def __unicode__(self): #Tell it to return as a unicode string (The name of the to-do item) rather than just Object.
		return self.name

Now that we have defined the database, we need to tell Django to sync all of the tables. We can do this by calling the syncdb command in the command line. Open up the command line and navigate to todo/.

manage.py syncdb

You should get some output for the tables created, as well as a prompt for creating a super user. Create the user and make a note of the username and password, as we'll use them to login to the admin area. For this tutorial we are going to use Django's test server to test our application. It is strongly advised that you do not use the test server in deployment, but instead use apache + mod_python or FastCGI. To start the test server, we again call manage.py but with the argument of runserver. We can additionally provide a port for it to run on. By default it runs on port 8000.

manage.py runserver 9090

To view the results we can go to http://127.0.0.1:9090/ .

todo/urls.py

Now we need to set up our URLs. Unlike PHP all URLs in Django are routed. That simply means we specify them ourselves. If a user tries to navigate to a page that isn't set, it simply returns a 404. Since this is a simple to-do application, we only need to set one URL, the index page. We are also going to enable our admin panel so that we can add, delete and edit our to-do items.

from django.conf.urls.defaults import *
from django.contrib import admin

admin.autodiscover()

urlpatterns = patterns('',
    (r'^admin/(.*)', admin.site.root), #Lets us access the admin page
    (r'^$', 'todo.core.views.index'), #Our index page, it maps to / . Once the page is called it will look in /todo/core/views.py for a function called index
    
)

The final thing we need to do before we can use the admin panel is to register the model with it. Create todo/core/admin.py and set the contents to:

from django.contrib import admin #Import the admin
from models import todo #Import our todo Model.

admin.site.register(todo) #Register the model with the admin

Now that the URLs are set, the database is synced, and the model is registered, we can access our administrator panel. Start the test server if it isn't already and navigate to http://127.0.0.1:9090/admin/ . Login with the super user details you created.

You can see under the core heading there is "todo" - the name of the model. By clicking on this, we can see all of the "to-dos" we have made. The admin interface for making new to-dos is below.

Now that creating, updating and deleting the to-do items are finished, all we need to do is display them. If you navigate to http://127.0.0.1:9090/ you will see an error saying that "the view called index does not exist". Remember - in the urls.py file, we specified that if the user visited the index, then it would load /todo/core/views.py with the function index()? We're going to specify that now. We write index() just like any other Python function, except it has to accept a request and return a response.

from models import todo
from django.shortcuts import render_to_response

def index(request): #Define our function, accept a request

    items = todo.objects.all() #ORM queries the database for all of the to-do entries.

    return render_to_response('index.html', {'items': items}) #Responds with passing the object items (contains info from the DB) to the template index.html

Now all that's left is to create our template in the todo/core/templates/ directory. In this template, we want to iterate through all of the items (in the object items) and display them on the page. All of the Django logic is wrapped with curly braces; if it's a variable, then it is wrapped with two curly braces.


<h2>todo</h2>

{% for x in items %}
<p>{{ x.name }} - {{ x.created|date:"D d M Y" }}</p>

<p>{{ x.description }}</p>
<hr />
{% endfor %}

You're finished! Add a few to-do items in the admin panel, and then go to http://127.0.0.1:9090 . Your layout should look similar to the image below.

Further Reading

I encourage you to learn more about Django if you're intrigued. Feel free to tweet me with any questions that you might have.


Related Posts

Check out some more great tutorials and articles that you might like

Enjoy this Post?

Your vote will help us grow this site and provide even more awesomeness

Plus Members

Source Files, Bonus Tutorials and
More for $9 a month for all TUTS+
sites in one subscription.

Join Now

User Comments

( ADD YOURS )
  1. PG

    Jash Sayani February 1st

    Making something like Remember The Milk would be really cool !!

    BTW, they use the jQuery interface.

    ( Reply )
  2. PG

    Robin February 1st

    this is a good expample to django dev.

    ( Reply )
  3. Nice. Finally a Django tutorial for the masses, put in front of the right audience. I’d also recommend “Python Web development with Django” to any other Django newcomers. It’s a good read.

    ( Reply )
  4. I agree with Jash Sayani … creating something like remember the milk would be awesome!

    ( Reply )
  5. PG

    Pontus Johansson February 2nd

    Finally a helpful Django tutorial!

    ( Reply )
  6. PG

    xQlusive February 2nd

    Interesting system, thanx for the tut.

    ( Reply )
  7. PG

    ger February 2nd

    Please, improve this intro with a jquery integration

    ( Reply )
  8. PG

    Mark February 2nd

    Nice

    ( Reply )
  9. PG

    Phillip February 2nd

    If you are going to buy any books, ensure they are based on Django 1.0 and not the older 0.96.

    Phillip.

    ( Reply )
  10. PG

    Simon Zimmermann February 2nd

    Thanks for the article on Django. I discovered this framework some time ago. Really impressed me. I guess my only problem is the Python syntax. I really never liked those “:” everywhere :p Other then that “python & django > php”

    ( Reply )
  11. PG

    berofx February 2nd

    Being a n00b that I am, is there a Python version of XAMPP (Apache + MySQL + Python)?

    ( Reply )
  12. PG

    Suman Shakya February 2nd

    great article. I would also like to read tutorials on TYPO3 CMS. Its quite popular here in Europe.

    ( Reply )
  13. PG

    M.A.Yoosuf February 2nd

    cool.

    NETTUTS is moving to all the programming Languareg……huraaaaaa

    ( Reply )
  14. PG

    insic February 2nd

    I heard Django often but nothings motivate me to try it. But after reading this tutorial. I have my first django app running. nice tutorial. :)

    ( Reply )
  15. PG

    Darren McPherson February 2nd

    I hear nothing but great things about Python and Django. At present I’m using PHP + Code Igniter.

    ( Reply )
  16. PG

    dantario February 2nd

    yes yes yes

    this is the python revolution. good by to PHP, well come Python.

    ( Reply )
  17. PG

    Patternhead February 2nd

    How about a step by step guide to getting this running on Google App Engine?

    ( Reply )
  18. PG

    Kevin Quillen February 2nd

    “good by to PHP, well come Python.”

    That kind of crap always makes me laugh.

    Are there any tools that would automate setting up a Django site instead of cmd line’ing it each time?

    ( Reply )
    1. PG

      Dustin June 11th

      Webfaction hosting makes it ridiculously simple. I came up with a method of publishing my site changes with a double-click: http://www.nerdydork.com/one-click-django-project-publishing.html

      ( Reply )
  19. PG

    Shane February 2nd

    Nice to see something different on NETTUTS.

    I’m not going to rush to look at Django though – none of the ‘Why Django’ points seem that compelling to me. It just seems like another framework, Python might be ‘cool’, but what compelling reasons are there to learn it when other frameworks out there, based on more established languages such as PHP do the job?

    ( Reply )
  20. PG

    Wassim February 2nd

    Am I the only one experiencing problems to post a comment today or..?!

    ( Reply )
  21. PG

    Josh February 2nd

    I’ve been wanting to learn Django, so I was glad to see this article. Two things though:

    First, is anyone else a little confused about the difference between MVC and MTV? From my reading of the tutorial, it sounded pretty similar, only MTV renames ‘controller’ to ‘view’ and ‘view’ to ‘template’. What am I missing?

    Second, the article seems to imply that you can’t use ORM in PHP Frameworks. But several PHP frameworks, such as Kohana (http://kohanaphp.com) have ORM built in, and most of the others have ways that you can add it as a plug-in.

    ( Reply )
  22. PG

    Brenelz February 2nd

    Nice I have been interested in DJANGO but haven’t had time to play around in it much….

    ( Reply )
  23. PG

    Bjorn February 2nd

    Great… just when I’m really getting into PHP…

    ( Reply )
  24. PG

    demogar February 2nd

    Finally a Django tutorial!
    I’m a big fan of CodeIgniter (PHP Framework) but I really prefer Django all over.
    Great tut!

    ( Reply )
  25. PG

    Michael Thompson February 2nd

    @Patternhead: GAE has a different ORM, and different model definitions so your best bet is to get comfy with Django/Python and then learn the ins and outs of BigTable and the rest of GAE.

    Also, why not add a “complete” field to the model?

    complete = models.BooleanField()

    ( Reply )
  26. PG

    Michael Thompson February 2nd

    Also, to the PHP trolls: don’t get so defensive. Python is better, and Djanog’s ORM and MVT (still technically MVC) is cleaner. :P

    ( Reply )
  27. PG

    Kevin Quillen February 2nd

    How is it ‘better’? I’m not a PHP troll, no ones proven how Python is ‘better’ than PHP.

    So just because you say so, our entire company should switch from PHP to Python overnight?

    ( Reply )
    1. PG

      Leon Waldman August 26th

      - It is clean. The code layout was done with readability in mind.
      - It is closer to the OS.
      - It is infinitely more modular.
      - Easy to deploy, and… scale.
      - Short learning curve.
      - OO frow the ground…
      - etc…

      ( Reply )
  28. PG

    Michael Rice February 2nd

    Sweet Django tutorial!

    ( Reply )
  29. PG

    Jeremy February 2nd

    Nice to see a django tutorial finally, I was close to putting something together myself!

    @Kevin – I think the push towards frameworks like django or rails and the accompanying remarks that they’re *better* than PHP are more of a performance comment. Though its nearly impossible to put together a fair test to benchmark frameworks against one another, the attempts that I have seen show frameworks like django and rails on top of the competition. In some cases the differences in performance are fairly insignificant.

    I’ve also seen some great studies between rails and django on plain development and deployment time for identical projects. Because django comes with a built-in admin interface it typically comes out on top as far as time goes.

    I almost started to get into PHP and kept reading articles from noteworthy professionals in the field saying to stay away and move towards django or rails. I’m glad I listened.

    ( Reply )
  30. PG

    Raja February 2nd

    Its great to see a django tutorial. Nice to see you guys moving into python stuff.

    ( Reply )
  31. PG

    Dimitris February 2nd

    Thanks. I hope there will be a sequence to this tutorial!

    ( Reply )
  32. PG

    Logan February 2nd

    Thanks alot for the feedback guys, I’m glad you liked the tutorial.

    Phillip has a very good point about Django 1.X being backward incompatible with 0.96. If your going to buy a book I’d recommend ‘Python Web Development with Django’. It’s very detailed, great for someone who is just getting started with Python/Django.

    berofx: There is no need for a XAMPP alternative for Django as there is the ‘runserver’ built in for testing your project locally.

    Patternhead: Google say that Django works on app engine when infact there are alot of features missing from a standard Django install. I may write an App Engine tutorial later though : ) .

    KevinQuillen: A frontend for the commandline commands in Django would only be used on the desktop. When you deploy the project to your server you would be forced to use the command line anyway. It’s good to get used to it. There are alot more commands you can use with manage.py than I showed such as generating a SQL schema of your database.

    Shane: It’s a large subject to go over in one comment. Read http://news.ycombinator.com/item?id=314143

    Josh: Yeah, they’ve essentially renamed things. More http://tinyurl.com/3mwwhf . Django ORM is alot more flexible, I was trying to hint (and didn’t get across) that most mainstream PHP frameworks don’t have “correct” models. They are just a page where you write SQL queries rather than design your database. Python frameworks, Ruby frameworks and Symfony (to a degree) have “correct” models.

    ( Reply )
  33. PG

    Jake February 2nd

    So… If I am looking to invest a good amount of time in learning one of the two, which should I learn… PHP or Python (Django)??

    ( Reply )
  34. PG

    Matt February 2nd

    For books, I would wait. The definitive guide to django is being re-written and available online at djangobook.org. James is also rewriting his book practical django projects which is also really good.

    ( Reply )
  35. PG

    Matt Porter February 2nd

    This is a nice tutorial, any chance of a follow up to add an interface for adding items to the list?

    ( Reply )
  36. PG

    Logan February 2nd

    Matt Porter: There is the admin interface there. Do you want another/non authenticated one?

    ( Reply )
  37. PG

    Mason Sklut February 2nd

    The Django “To-Do list” app has been a classic for as long as I’ve known :-)

    ( Reply )
  38. PG

    Jonas February 3rd

    Jeremy wrote: “I think the push towards frameworks like django or rails and the accompanying remarks that they’re *better* than PHP are more of a performance comment. Though its nearly impossible to put together a fair test to benchmark frameworks against one another, the attempts that I have seen show frameworks like django and rails on top of the competition.”

    Do you have a link to the bechmarks you’re mentioning? Because from what I’ve read, both PHP and Django are known for being fast even under high load (e.g., Facebook uses PHP), whereas Rails is notorious for being slow and unsuited for high-traffic sites.

    I’m a PHP programmer, and while I’m currently looking into Django, it’s definitely not because of speed issues with PHP. I’ve used PHP for sites that get millions and millions of hit, and there were no problems whatsoever with the speed of PHP. The RDBMS was the bottleneck.

    ( Reply )
  39. PG

    Chris Robinson February 3rd

    great to see a Django tut, hope to see more in the future

    ( Reply )
  40. PG

    Joe February 3rd

    Shane (”based on more established languages such as PHP do the job?”):
    You do know Python is much older and more established then php, right? Python development started in the 80’s, php around 94. If you were referring to Django, then the proper comparison would be CakePHP, Codeigniter, Zend to Django..

    ( Reply )
  41. PG

    Dan February 3rd

    Looks interesting, may give it a go

    ( Reply )
  42. @ger

    This isn’t a jQuery tutorial. It isn’t a tutorial about how to replicate RTM. It’s supposed to be a basic into to Django, a Python framework, not Javascript library.

    That said, there are some nice jQuery tutorials on NETTUTS, as well as learningjquery.com, if you want to check those out. :-)

    ( Reply )
  43. @Jake

    I’d go with Django, but if you want a job at Facebook in the near future, PHP. But who wants to work at Facebook? :-)

    ( Reply )
  44. PG

    Raja February 4th

    Well, PHP based applications are more ‘popular’, plus I think as far as commercial hosting goes, almost everyone supports PHP.

    Python is picking up thanks to Google App Engine & Django.

    DJango also requires a different approach to hosting, so it may take awhile before the el-cheapo webosts offer it, or go bug the CPanel authors ;)

    ( Reply )
  45. PG

    Kevin Quillen February 4th

    “if you want a job at Facebook in the near future, PHP. But who wants to work at Facebook?”

    I hope you’re kidding. Making an underlying comment that PHP is simply dead outside of Facebook is ridiculous.

    Heres an idea. Everyone grasp the concepts of programming and problem solving instead of memorizing syntax and claiming X language is dead, long live Y language.

    Trends come and go. Like it or not PHP and .NET are going to be the dominant development languages on the internet for years to come. So just because Python has been around since the 80s doesn’t mean that if a magical framework comes along that suddenly all else is obsolete.

    ( Reply )
  46. PG

    Logan February 5th

    cPanel don’t officially support Django. That being said, if your aiming to run a good website, your going to want it on a VPS. It’s just as easy to set up a Django stack as it is to set up a PHP stack.

    ( Reply )
  47. PG

    Henrik Lied February 6th

    Regarding PHP vs. Python: The amount of strange decisions made by the PHP core team lately shows that communication between the users and the developers of PHP is pretty bad.

    I know a lot of developers who are completely dependent on PHP for their day job, but they have no interest in jumping on the PHP6 bandwagon, because of the weird changes to syntax and form.

    Regarding installation of Python/Django on simple hosts: I’ll give you one clue to why it’s not a cPanel-ready solution: World Online.
    Django originated from a news organization, and believe me – you don’t run a huge news site on a shared server with no root access.
    Having to use shell / SSH to configure your site is a necessity for larger sites anyway. How do you configure munin, apache, memcached and postgresql in a fair way through cPanel? You don’t.

    And yes, PHP is slow when compared to Python. So is Ruby. But I don’t mind. PHP’s performance is good enough for Facebook (although Facebook only uses PHP for the front end stuff. Most of the backend is written in Erlang and other pre-compiled languages).

    What I like about Python is the huge toolbox it brings. I don’t have to jump to Perl or another language to do server specific operations. In PHP you do.

    As most other developers using Python, I come from a PHP background. Once you get off, you’ll probably never go back.

    ( Reply )
  48. PG

    Sascha February 9th

    Great to see Django here. I already build alot of sites using PHP (Typo3) and Phyton (Django). In some cases i use Typo3 and in some other i use Django. Iam looking forward to uses both (php and python) in the future. And don’t forget to mix it up with our magic wand “jQuery”.

    ( Reply )
  49. PG

    Pelchile February 11th

    What are the server specific operations that require someone to jump to Perl that could not be accomplished with PHP?

    I mean I’m sure there are, just curious as to what they are and why writing code in Perl would be necessary to access them.

    ( Reply )
  50. PG

    neron-fx March 2nd

    Same old s**t, diffent day. People have been arguing about which programming language is best for years! Its getting so old people!

    Why not broaden your horizons rather than sticking with what you know? I know PHP, Ruby on Rails, Python (w Django), C# .NET and a bit of Java.

    I can tell you now that all these languages have their pros and cons and I like each for my own reasons! Use whatever is applicable to the job!

    Companies dont hire developers versed in only 1 language these days! They expect you have to have a much broader knowledge! So all you “I only use PHP or I only use Python” people out there, you are only shooting yourselves in the foot!

    On a side note! Good tut for newcomers to Django! Well done!

    ( Reply )
  51. PG

    Dartdog April 8th

    Great Tutorial, I think it will help me get over a few humps, as I try to get going with Google App Engine.

    I agree that if you could update the tutorial for Google app engine you would get overwhelmed with traffic,, I’ve been working for days to get to a simple blog example using the Google App engine patch.. Since it combines so many differences none of the tutorial info really works.

    There are no tutorials for getting a basic blog engine up and going using Django on Google app engine and only two “examples” as of now, one in Chinese and one which leaves out all the css/js so neither is a great starting point.

    ( Reply )
  52. PG

    Amara Emerson April 12th

    @Kevin Quillen
    Python is an older and actually much more established than PHP, but in a different area. PHP was designed specifically for the web, while Python is a general language. If you take the time to learn python, (not from Dive Into Python, an awful, awful book) then you’ll notice that it’s extremely easy to use. The syntax is clear and conducive to well written code, and coupled with Django it can significantly improve the time taken to get results out of the door because of the good design principles that Django encourages.

    If you use Symfony or other framework for PHP, then fine there’s nothing wrong with that. I like PHP because of it’s resemblance to C/C++ because I originally learnt those languages. But there are some glaring deficiencies which become highlighted when you try to use it for web applications.

    Don’t get so defensive about PHP, no one’s saying that PHP is useless. It just has certain weaknesses which make python a more viable language and platform for certain applications.

    As for rails, I’m still not entirely convinced. Ruby + Rails is definitely harder to learn than Python and Django because it’s inherently more implicit. There are a _lot_ more conventions which need to be learned in order to use them effectively. My view on RoR however is not authoritative, just my personal experience.

    ( Reply )
  53. PG

    T. Stone May 21st

    Nice tut. I got most of it working, but couldn’t get the admin interface working right. What version of Django was this written with?

    ( Reply )
  54. PG

    magidu August 17th

    I have this error, after adding admin.site.register(todo) #Register the model with the admin
    and start the server.

    TemplateSyntaxError at /admin/

    Caught an exception while rendering: Tried index in module todo.core.views. Error was: ‘module’ object has no attribute ‘index’

    Original Traceback (most recent call last):
    File “/Library/Python/2.5/site-packages/django/template/debug.py”, line 71, in render_node
    result = node.render(context)
    File “/Library/Python/2.5/site-packages/django/template/defaulttags.py”, line 370, in render
    url = reverse(self.view_name, args=args, kwargs=kwargs, current_app=context.current_app)
    File “/Library/Python/2.5/site-packages/django/core/urlresolvers.py”, line 341, in reverse
    *args, **kwargs)))
    File “/Library/Python/2.5/site-packages/django/core/urlresolvers.py”, line 275, in reverse
    possibilities = self.reverse_dict.getlist(lookup_view)
    File “/Library/Python/2.5/site-packages/django/core/urlresolvers.py”, line 195, in _get_reverse_dict
    self._populate()
    File “/Library/Python/2.5/site-packages/django/core/urlresolvers.py”, line 187, in _populate
    lookups.appendlist(pattern.callback, (bits, p_pattern))
    File “/Library/Python/2.5/site-packages/django/core/urlresolvers.py”, line 137, in _get_callback
    raise ViewDoesNotExist, “Tried %s in module %s. Error was: %s” % (func_name, mod_name, str(e))
    ViewDoesNotExist: Tried index in module todo.core.views. Error was: ‘module’ object has no attribute ‘index’

    Request Method: GET
    Request URL: http://localhost:9090/admin/
    Exception Type: TemplateSyntaxError
    Exception Value:

    Caught an exception while rendering: Tried index in module todo.core.views. Error was: ‘module’ object has no attribute ‘index’
    ——————-

    What did I do wrong?

    best regards,

    magi.

    ( Reply )
    1. PG

      Leon Waldman August 26th

      I get this error.

      under /core/views.py add:

      def index():
      pass

      ( Reply )
  55. PG

    Leon Waldman August 26th

    Amazing!

    This should be the on the django website.

    Is exactly what I was looking for! :) ))

    Thanks.

    ( Reply )
  1. Arrow
    Gravatar

    Your Name
    August 26th