1. Dependency
1-1 mysql
$ sudo apt-get install mysql-server1-2 phpmyadmin
$ sudo apt-get install phpmyadmin1-3 python 2.7 up
// system build in: python 2.71-4 pip
$ sudo apt-get install python-pip1-5 python-mysqldb
$ sudo apt-get install python-mysqldb2. Install django
2-1 Install pip
$ sudo apt-get install python-pip2-2 Install django
$ sudo pip install Django2-3 Verifying // optional
$ pythonPython 2.7.3 (default, Feb 27 2014, 20:00:17)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.VERSION
(1, 7, 0, 'final', 0)
3. First django project (with mysql database)
3.1 Create a folder to put the project [1]
$ mkdir ~/nthuojv23.2 Create a project [1]
$ cd ~/nthuojv2$ django-admin.py startproject nthuoj
/* --------------------------Folder structure--------------------------
* nthuojv2/nthuoj/
* manage.py
* nthuoj/
* __init__.py
* settings.py
* urls.py
* wsgi.py
* --------------------------End of structure-------------------------- */
3.3 Database configuration [2]
$ vim nthuoj/settings.py...$ vim nthuoj.ini
DATABASES = {
'default': {
'ENGINE': 'djago.db.backends.mysql',
'OPTIONS':{
'read_default_file': '~/nthuojv2/nthuoj.ini',
},
}
}
...
[client]
host = 127.0.0.1
database = newnthuoj
user = root
password = *********
default-character-set = utf8
3.4 Create database
$ mysql -u root -p*********mysql> CREATE DATABASE newnthuoj character set utf8;
mysql> exit
3.5 Run server [1]
$ python manage.py migrateOperations to perform:$ python manage.py runserver <IP>:<port>
Apply all migrations: admin, contenttypes, auth, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying sessions.0001_initial... OK
// without argument, default ip: 127.0.0.1, default port: 8000
// another version: only one argument <port>, default ip: 127.0.0.1
Performing system checks...
System check identified no issues (0 silenced).
October 15, 2014 - 09:26:04
Django version 1.7, using settings 'nthuoj.settings'
Starting development server at http://<IP>:<port>/
Quit the server with CONTROL-C.
3.6 Verifying //optional
open the browser and visit <IP>:<port>4. Create models [1]
4.1 Create a new app
$ python manage.py startapp <app_name> // app_name: polls/* --------------------------Folder structure--------------------------
* nthuojv2/polls/
* admin.py
* __init__.py
* migrations/
* __init__.py
* models.py
* tests.py
* views.py
* --------------------------End of structure-------------------------- */
4.2 Finish contents for the app
$ vim polls/models.pyimport datetime$ vim nthuoj/settings.py
from django.db import models
from django.utils import timezone
# Create your own models here.
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
# <blanks>def instead of <tab>def
def __unicode__(self): # python 3 up use __str__
# <blanks>return instead of <tab><tab>return
return self.question_text
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
class Choice(models.Model):
question = models.ForeignKey(Question)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __unicode__(seof): # python 3 up use __str__
return self.choice_text
...$ python manage.py makemigrations polls
INSTALLED_APPS = (
...
'polls',
)
...
Migrations for 'polls':
0001_initial.py:
- Create model Choice
- Create model Question
- Add field question to choice
4.3 See what django want to do on your database // optional
$ python manage.py sqlmigrate polls 0001BEGIN;
CREATE TABLE `polls_choice` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`choice_text` varchar(200) NOT NULL,
`votes` integer NOT NULL
);
CREATE TABLE `polls_question` (
`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
`question_text` varchar(200) NOT NULL,
`pub_date` datetime NOT NULL
);
ALTER TABLE `polls_choice` ADD COLUMN `question_id` integer NOT NULL;
ALTER TABLE `polls_choice` ALTER COLUMN `question_id` DROP DEFAULT;
CREATE INDEX polls_choice_7aa0f6ee ON `polls_choice` (`question_id`);
ALTER TABLE `polls_choice`
ADD CONSTRAINT polls_choice_question_id_40fbbd72_fk_polls_question_id
FOREIGN KEY (`question_id`)
REFERENCES `polls_question` (`id`);
COMMIT;
4.4 Create tables in database
$ python manage.py migrateOperations to perform:
Apply all migrations: admin, contenttypes, polls, auth, sessions
Running migrations:
Applying polls.0001_initial... OK
5. Use python shell to insert data [1]
5.1 Open python shell
$ python manage.py shell5.2 Setting environment
>>> import django>>> django.setup()
>>> from polls.models import Question, Choice
>>> from django.utils import timezone
5.3 Add a question
>>> q = Question(question_text="What's up?", pub_date=timezone.now())>>> q.save()
5.4 Add choices for the question
>>> q.choice_set.create(choice_text='Not much', votes=0)>>> q.choice_set.create(choice_text='The sky', votes=0)
// for more APIs, refer to [1]
6. Create views [3]
6.1 Edit the content
$ vim polls/views.py...
from django.http import HttpResponse
def index(request):
return HttpResponse("Hello, world.")
6.2 Create urls.py
$ vim polls/url.pyfrom django.conf.urls import patterns, url
from polls import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
)
6.3 Edit nthuoj/urls.py
$ vim nthuoj/urls.py...
urlpatterns = patterns('',
url(r'^polls/', include('polls.urls')),
...
)
6.4 Verifying // optional
run server, open the browser and visit <IP>:<port>/polls6.5 Passing parameters to view
$ vim polls/views.py // create more views...$ vim polls/urls.py // link views and urls
def detail(request, question_id):
return HttpResponse("You're looking at question %s." % question_id)
def results(request, question_id):
response = "You're looking at the results of question %s."
return HttpResponse(response % question_id)
def vote(request, question_id):
return HttpResponse("You're voting on question %s." % question_id)
...
urlpatterns = patterns('',
...
url(r'^(?P<question_id>\d+)/$', views.detail, name='detail'),
url(r'^(?P<question_id>\d+)/results/$', views.results, name='results'),
url(r'^(?P<question_id>\d+)/vote/$', views.vote, name='vote'),
)
6.6 Verifying // optional
run server, open the browservisit <IP>:<port>/polls/34
visit <IP>:<port>/polls/34/results/
visit <IP>:<port>/polls/34/vote/
7. Get data and show on web by view and template [3]
7.1 Create the template folder and polls templates folder
$ mkdir polls/templates$ mkdir polls/templates/polls // for namespace, not necessery, but recommand
7.2 Edit template file
$ vim polls/templates/polls/index.html<!-- views.py will pass content: 'lastest_question_list' -->$ vim polls/templates/polls/detail.html
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
<!-- views.py will pass content: 'question' -->
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>
7.3 Edit the movement (in views.py) // show latest 5 questions (sorted by public time, dec order)
$ vim polls/views.py...
from django.template import RequestContext, loader
from polls.models import Question
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
template = loader.get_template('polls/index.html')
context = RequestContext(request, {
'latest_question_list': latest_question_list,
})
return HttpResponse(template.render(context))
...
7.4 Shortcut: render() // no more HttpResponse is needed
$ vim polls/views.pyfrom django.shortcuts import render
from polls.models import Question
def index(request):
latest_question_list = Question.objects.all().order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)
7.5 Handing exception // query a not exist object
$ vim polls/views...// use shortcut get_object_or_404() to replace try except raise Http404
from django.http import Http404
...
def detail(request, question_id):
try:
question = Question.objects.get(id=question_id)
except Question.DoesNotExist:
raise Http404 # or redirect to borken page
return render(request, 'polls/detail.html', {'question': question})
7.6 Reomve hardcoded URLs in templates
$ vim polls/templates/polls/index.html...
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
...
7.7 Namespace of template // optionary, but recommand
$ vim nthuoj/urls.py...$ vim polls/templates/polls/index.html
url(r'^polls/', include('polls.urls', namespace="polls")),
...
...
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>
...
8. Modify data in database [4]
8.1 Complete version of detail.html
$ vim polls/templates/polls/detail.html<h1>{{ question.question_text }}</h1>
{% if error_message %}
<p><strong>{{ error_message }}</strong></p>
{% endif %}
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %} # Prevent Cross Site Request Forgeries [5]
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>
8.2 Complete version of vote and result
$ vim polls/views.pyfrom django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from polls.models import Choice, Question
...
def vote(request, question_id):
p = get_object_or_404(Question, pk=question_id)
try:
selected_choice = p.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': p,
'error_message': "You didn't select a choice.",
})
else:
# simply use += 1 and save to modify the value in database
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(p.id,)))
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})
8.3 Template for results
$ vim polls/templates/polls/results.html<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
<a href="{% url 'polls:detail' question.id %}">Vote again?</a>
8.4 Verifying // optional
run server, open the browservote it! and check the value in the database
9. Generic views [4][6] // To avoid redundant code
9.1 Change polls/urls.py
$ vim polls/urls.py...
urlpatterns = patterns('',
url(r'^$', views.IndexView.as_view(), name='index'),
# The DetailView generic view expects the primary key value captured from the URL to be called "pk"
url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
url(r'^(?P<pk>\d+)/results/$', views.ResultsView.as_view(), name='results'),
...
)
9.2 Change polls/views.py
$ vim polls/views.pyfrom django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.views import generic
from polls.models import Choice, Question
class IndexView(generic.ListView):
# default template: <app_name>/<model_name>_list.html, ie. polls/question_list.html
template_name = 'polls/index.html'
# default context variable: question_list
context_object_name = 'latest_question_list'
def get_queryset(self):
"""Return the last five published questions."""
return Question.objects.order_by('-pub_date')[:5]
class DetailView(generic.DetailView):
model = Question
# default template: <app_name>/<model_name>_detail.html, ie. polls/question_detail.html
template_name = 'polls/detail.html'
class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html'
def vote(request, question_id):
# same as section 8
9.3 Verifying // optional
run server, open the browserthe appearence should be the same as in section 8
// for more details on generic views, refer to [6]
Murmur
An app is a Web application that does somethingA project is a collection of configuration and apps for a particular Web site
A project can contain multiple apps. An app can be in multiple projects.
The “view” describes the data that gets presented to the user. It’s not necessarily how the data looks, but which data is presented. The view describes which data you see, not how you see it.
In Django, a “view” describes which data is presented, but a view normally delegates to a template, which describes how the data is presented.
By running makemigrations, you’re telling Django that you’ve made some changes to your models (in this case, you’ve made new ones) and that you’d like the changes to be stored as a migration.
There’s a command that will run the migrations for you and manage your database schema automatically - that’s called migrate,
The sqlmigrate command takes migration names and returns their SQL:
The sqlmigrate command doesn’t actually run the migration on your database - it just prints it to the screen so that you can see what SQL Django thinks is required.
Migrations are Django’s way of propagating changes you make to your models (adding a field, deleting a model, etc.) into your database schema.
You should always return an HttpResponseRedirect after successfully dealing with POST data. This tip isn’t specific to Django; it’s just good Web development practice.
Reference
[1] https://docs.djangoproject.com/en/1.7/intro/tutorial01/[2] https://docs.djangoproject.com/en/1.5/ref/databases/
[3] https://docs.djangoproject.com/en/1.7/intro/tutorial03/
[4] https://docs.djangoproject.com/en/1.7/intro/tutorial04/
[5] http://www.dotblogs.com.tw/joysdw12/archive/2013/09/16/asp-net-cross-site-request-forgery.aspx
[6] https://docs.djangoproject.com/en/1.7/topics/class-based-views/
No comments:
Post a Comment