Skip to content

Instantly share code, notes, and snippets.

@amelieykw
Last active July 5, 2018 12:46
Show Gist options
  • Save amelieykw/c08b1e67fbf6492e98edf78ed15ddaa8 to your computer and use it in GitHub Desktop.
Save amelieykw/c08b1e67fbf6492e98edf78ed15ddaa8 to your computer and use it in GitHub Desktop.
[Django project in MS visual studio 2017]#django #VisualStudio2017 #MySQL #python

Django at a glance

"How to write a database-driven Web app with Django?"

workflow:

  1. create models
  2. get admin sites up and running asap
  3. your staff(or client) can start populating data
  4. develop the way data is presented to the public

01 - Design your model

  1. object-relational mapper (ORM)
    • describe your database layout in Python code
  2. data-model syntax (models.py)
    • rich ways of presenting your models

02 - Install it

$python manage.py migrate

to create the database tables automatically (the migrate command looks at all your available models and creates tables in your database for whichever tables don't already exist)

03 - Enjoy the free API

free, rich Python API to access your data on the fl, no code generation necessary

04 - A dynamic admin interface : it's not just scaffolding - it's the whole house

Once your models are defined, Django can automatically create a professional, production ready administrative interface - a website that lets authenticated users add, change and delete objects.

register your model in the admin site:

# mysite/news/models.py
from django.db import models

class Article(models.Model):
    pub_date = models.DateField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
# mysite/news/admin.py
from django.contrib import admin

from . import models

admin.site.register(models.Article)

your site is edited by a staff, or a client, or maybe just you - and you don't want to have to deal with creating backend interfaces just to manage content

05 - Design your URLs

URLconf - a table of contents for your app - a simple mapping between URL patterns and Python callback functions ("views")

when a user requests a page, Django runs through each path, in order, and stops at the first one that matches the requested URL. Once one of the URL patterns matches, Django calls the given view, which is a Python function. Each view gets passed a request object - which contains request metadata - and the values captured in the pattern.

ex. if a user requested the URL ("/articles/2005/05/39323/"), Django would call the function news.views.article_detail(request, year=2005, month=5, pk=39323)

06 - Write your views

Each view is responsible for doing one of two things :

  • returning an HttpResponse object
    • containing the content for the requested page
  • raising an exception such as Http404

A view :

  1. retrieve data according to the parameters
  2. load a template
  3. render the template with the retrieved data
# mysite/news/views.py
from django.shortcuts import render

from .models import Article

def year_archive(request, year):
    a_list = Article.objects.filter(pub_date__year=year)
    context = {'year': year, 'article_list': a_list}
    return render(request, 'news/year_archive.html', context)

07 - Design your templates

# mysite/news/templates/news/year_archive.html
{% extends "base.html" %}

{% block title %}Articles for {{ year }}{% endblock %}

{% block content %}
<h1>Articles for {{ year }}</h1>

{% for article in article_list %}
    <p>{{ article.headline }}</p>
    <p>By {{ article.reporter.full_name }}</p>
    <p>Published {{ article.pub_date|date:"F j, Y" }}</p>
{% endfor %}
{% endblock %}
# mysite/templates/base.html
{% load static %}
<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <img src="{% static "images/sitelogo.png" %}" alt="Logo" />
    {% block content %}{% endblock %}
</body>
</html>
  1. Create a Django project in MS Visual Studio 2017
  2. Create a virtual environment
  3. install MySQL Community Server from the official site
  4. start your terminal and start MySQL
  5. create a username with a password
    • username: kyu
    • password: YKWyaodangxueba@
  6. open MySQL with the root account, and enter your password
    • username: admin
    • password: admin
  7. create a database with your username and password
    • create a database: CREATE DATABASE QPI_Dashboard;
    • check the database: SHOW DATABASES;
    • select the database: USE qpi_dashboard;
  8. install Python-MySQl adapter mysqlclient
  9. Open mysite/settings.py, edit the databases block:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydatabase',
        'USER': 'username',
        'PASSWORD': 'your_password',
        'HOST': '',
        'PORT': '',
    }
}
  1. make sure the timezone is correctly setup: TIME_ZONE='CET'
  2. save the file, and run the following commands to use the database in your project:
$ python manage.py check
$ python manage.py migrate
  1. create a superuser for your project
    • username: kyu
    • password: YKWyaodangxueba@
  2. create the models in models.py
  3. create the administration back-end
  4. open mysite/urls.py and make sure the following lines are present:
from django.conf.urls import url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
]
  1. run server to test if MySQL is correctly working by logging into the Django admin panel.

In this step you learn how to:

  1. Create a project from the template and initialize the database (step 6-1)
  2. Understand data models (step 6-2)
  3. Apply migrations (step 6-3)
  4. Understand the views and page templates created by the project template (step 6-4)
  5. Create a custom administration interface (step 6-5)

Step 6-1: Create the project and initialize the database

  1. Solution Explorer > right-click the "LearningDjango" solution > Add > New Project
  2. select "Polls Django Web Project" template > call the project "DjangoPolls" > select OK
  3. like the other project templates in VS, the "Polls Django Web Project" template includes a requirements.txt file, the VS prompts asks where to install those dependencies > Install into a virtual environment > in the Add Virtual Environment dialog select Create to accept the defaults
  4. Before running the project, initialize the database by following the readme.html
  5. create a Django super user (the administrator) :
    • right-click the "DjangoPolls" project in Solution Explorer
    • select the Python > Django Migrate command
    • right-click the project again, select Python > Django Create Superuser command, and follow the prompts
  6. Set the "DjangoPolls" project to be the default for the VS solution
    • right-clicking that project in Solution Explorer
    • select Set as Startup Project
  7. Select Debug > Start Debugging(F5) or use the Web Serve button on the toolbar to run the server
  8. route to /admin page

Question: what does the Django Migrate command do?

Django Migrate command = runs the manage.py migrate command > runs any scripts in the app/migrations folder that haven't been run previously

The migration script itself is created by the manage.py makemigrations command, which scans the app's models.py file, compares it to the current state of the database, and then generates the necessary scripts to migrate the database schema to match the current models.

This feature of Django is very powerful as you update and modify your models over time.

Step 6-2: Understand data models

Step 6-3: Use migrations

  1. Requests and responses
  2. Models and the admin site
  3. (1) Introducing the Django Admin
  4. views and templates
  5. Forms and generic views
  6. Testing
  7. Static files
  8. Customizing the admin site

Context

Object create a basic poll application
Part 1 A public site that lets people view polls and vote in them
Part 2 An admin that lets you add, change, and delete polls
Django Django 2.0
Python Python 3.4 or later

Create the Polls app in Mysite project

1. Requests and responses

  1. write your 1st view:
# polls/views.py
from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")
  1. To call the view, we need to map it to a URL - and for this we need a URLconf.
# polls/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='index'),
]
  1. point the root URLconf at the polls.urls module
# mysite/urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('polls/', include('polls.urls')),
    path('admin/', admin.site.urls),
]

urls to "polls/", let the "polls.urls" to take care the rest strings

2. Models and the admin site

(1)setup the DB, (2)create your first model, and (3)get a quick introduction to Django's automatically-generated admin site

(1) Database setup

mysite/settings.py

  • DATABASES 'default':
    • ENGINE:
      • 'django.db.backends.sqlite3'
      • 'django.db.backends.postgresql'
      • 'django.db.backends.mysql'
      • 'django.db.backends.oracle'
    • NAME:
      • the name of your database
      • should be the full absolute path, including filename, of that file

For DB other than SQLite: make sure you've created a database by this point. Do that with "CREATE DATABASE database_name;" with your database's interactive prompt.

  • INSTALLED_APPS:
    • django.contrib.admin – The admin site.
    • django.contrib.auth – An authentication system.
    • django.contrib.contenttypes – A framework for content types.
    • django.contrib.sessions – A session framework.
    • django.contrib.messages – A messaging framework.
    • django.contrib.staticfiles – A framework for managing static files.
$python manage.py migrate

to create tables in the database for these applications before we can use them

SHOW TABLES;

to check

(2) Creating Models

In our simple poll app, 2 models: Question and Choice.

  • Question:
    • a question
    • a publication date
  • Choice:
    • the text of the choice
    • a vote tally
  • each Choice is associated with a Question
# polls/models.py
from django.db import models


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
    
    def __str__(self):
        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, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)
    
    def __str__(self):
        return self.choice_text

Each model has a number of class variables, each of which represents a database field in the model.

The name of each Field instance is the field's name. You'll use this value in your Python code, and your database will use it as the column name.

(3) Activating models

  1. tell our project that the polls app is installed
  2. Create a database schema (CREATE TABLE statements) for this app
  3. Create a Python database-access API for accessing Question and Choice objects
# mysite/settings.py
INSTALLED_APPS = [
    'polls.apps.PollsConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
$python manage.py makemigrations polls

You should see something similar to the following:

Migrations for 'polls':
  polls/migrations/0001_initial.py:
    - Create model Choice
    - Create model Question
    - Add field question to choice

makemigrations tells django that you've made some changes to your models and that you'd like the changes to be stored as a migration

Migrations are how Django stores changes to your models - they're files on disk. You can read the migration for your new model if you like. It's the file polls/migrations/0001_initial.py.

run migrate again to create those model tables in your database:

$python manage.py migrate

(4) Playing with the API

$python manage.py shell

Let's hop into the interactive Python shell and play around with the free API Django gives you.

To be continue

2.1 Introducing the Django Admin

(1) Creating an admin user

First we’ll need to create a user who can login to the admin site. Run the following command:

$ python manage.py createsuperuser

Enter your desired username and press enter.

Username: admin

You will then be prompted for your desired email address:

Email address: [email protected]

The final step is to enter your password. You will be asked to enter your password twice, the second time as a confirmation of the first.

Password: **********
Password (again): *********
Superuser created successfully.

(2) Start the development server

runserver > open a Web browser and go to "/admin/" on your local domain

(3) Enter the admin site

try logging in with the superuser account you created in the previous step.

You should see a few types of editable content: groups and users.

They are provided by django.contrib.auth, the authentication framework shipped by Django.

(4) Make the poll app modifiable in the admin

To tell the admin that Question objects have an admin interface, open the polls/admin.py file and edit it to look like this:

# polls/admin.py
from django.contrib import admin

from .models import Question

admin.site.register(Question)

(5) Explore the free admin functionality

Now that we’ve registered Question, Django knows that it should be displayed on the admin index page:

Click “Questions”. Now you’re at the “change list” page for questions. This page displays all the questions in the database and lets you choose one to change it. There’s the “What’s up?” question we created earlier:

Click the “What’s up?” question to edit it:

  • The form is automatically generated from the Question model.
  • The different model field types (DateTimeField, CharField) correspond to the appropriate HTML input widget. Each type of field knows how to display itself in the Django admin.

The bottom part of the page gives you a couple of options:

  • Save – Saves changes and returns to the change-list page for this type of object.
  • Save and continue editing – Saves changes and reloads the admin page for this object.
  • Save and add another – Saves changes and loads a new, blank form for this type of object.
  • Delete – Displays a delete confirmation page.

3. views and templates

In our poll application, we’ll have the following four views:

  • Question “index” page – displays the latest few questions.
  • Question “detail” page – displays a question text, with no results but with a form to vote.
  • Question “results” page – displays results for a particular question.
  • Vote action – handles voting for a particular choice in a particular question.

web pages & other content are delivered by views - each view is represented by a simple Python function (or method, in the case of class-based views).

Djanpo will choose a view by examining the URL that's requested (the part of the URL after the domain name).

To get from a URL to a view, Django uses what are known as 'URLconfs'. A URLconf maps URL patterns to views.

(1) Write more views

# polls/views.py

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)
# polls/urls.py

from django.urls import path

from . import views

urlpatterns = [
    # ex: /polls/
    path('', views.index, name='index'),
    # ex: /polls/5/
    path('<int:question_id>/', views.detail, name='detail'),
    # ex: /polls/5/results/
    path('<int:question_id>/results/', views.results, name='results'),
    # ex: /polls/5/vote/
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

When somebody requests a page from your website – say, “/polls/34/”, Django will load the mysite.urls Python module because it’s pointed to by the ROOT_URLCONF setting. It finds the variable named urlpatterns and traverses the patterns in order. After finding the match at 'polls/', it strips off the matching text ("polls/") and sends the remaining text – "34/" – to the ‘polls.urls’ URLconf for further processing. There it matches 'int:question_id/', resulting in a call to the detail() view like so:

detail(request=<HttpRequest object>, question_id=34)

The question_id=34 part comes from int:question_id.

The :question_id> part of the string defines the name that will be used to identify the matched pattern, and the <int: part is a converter that determines what patterns should match this part of the URL path.

There’s no need to add URL cruft such as .html – unless you want to, in which case you can do something like this:

path('polls/latest.html', views.index),

But don't do this.

(2) Write views that actually do something - render()

Your view can read records from a database, or not.

It can use a template system such as Django’s – or a third-party Python template system – or not.

It can generate a PDF file, output XML, create a ZIP file on the fly, anything you want,using whatever Python libraries you want.

# polls/templates/polls/index.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 %}
# polls/views.py

from django.http import HttpResponse
from django.template import loader

from .models import Question

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = {
        'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context, request))

The context is a dictionary mapping template variable names to Python objects.

Load the page by pointing your browser at “/polls/”, and you should see a bulleted-list containing the “What’s up” question from Tutorial 2. The link points to the question’s detail page.

A shortcut: render()

It’s a very common idiom to :

  1. load a template
  2. fill a context
  3. return an HttpResponse object with the result of the rendered template.
# polls/views.py

from django.shortcuts import render

from .models import Question

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)

Note that once we’ve done this in all these views, we no longer need to import loader and HttpResponse (you’ll want to keep HttpResponse if you still have the stub methods for detail, results, and vote).

The render() function takes the request object as its first argument, a template name as its second argument and a dictionary as its optional third argument. It returns an HttpResponse object of the given template rendered with the given context.

(3) Raising a 404 error - get_object_or_404()

(4) Use the template system

detail() view for our poll application

# polls/templates/polls/detail.html

<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

The template system uses dot-lookup syntax to access variable attributes. In the example of {{ question.question_text }}, first Django does a dictionary lookup on the object question. Failing that, it tries an attribute lookup – which works, in this case. If attribute lookup had failed, it would’ve tried a list-index lookup.

Method-calling happens in the {% for %} loop: question.choice_set.all is interpreted as the Python code question.choice_set.all(), which returns an iterable of Choice objects and is suitable for use in the {% for %} tag.

template guide

(5) Removing hardcoded URLs in templates

Remember, when we wrote the link to a question in the polls/index.html template, the link was partially hardcoded like this:

<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>

The problem with this hardcoded, tightly-coupled approach is that it becomes challenging to change URLs on projects with a lot of templates. However, since you defined the name argument in the path() functions in the polls.urls module, you can remove a reliance on specific URL paths defined in your url configurations by using the {% url %} template tag:

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

The way this works is by looking up the URL definition as specified in the polls.urls module. You can see exactly where the URL name of ‘detail’ is defined below:

...
# the 'name' value as called by the {% url %} template tag
path('<int:question_id>/', views.detail, name='detail'),
...

If you want to change the URL of the polls detail view to something else, perhaps to something like polls/specifics/12/ instead of doing it in the template (or templates) you would change it in polls/urls.py:

...
# added the word 'specifics'
path('specifics/<int:question_id>/', views.detail, name='detail'),
...

(6) Namespacing URL names

The tutorial project has just one app, polls. In real Django projects, there might be five, ten, twenty apps or more. How does Django differentiate the URL names between them? For example, the polls app has a detail view, and so might an app on the same project that is for a blog.

How does one make it so that Django knows which app view to create for a url when using the {% url %} template tag?

The answer is to add namespaces to your URLconf. In the polls/urls.py file, go ahead and add an app_name to set the application namespace:

# polls/urls.py

from django.urls import path

from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/results/', views.results, name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

Now change your polls/index.html template from:

# polls/templates/polls/index.html

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

to point at the namespaced detail view:

# polls/templates/polls/index.html

<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>

4. Forms and generic views

When you’re comfortable with writing views, read part 4 of this tutorial to learn about simple form processing and generic views.

5. Testing

6. Static files

static files:

  • images
  • Javascript
  • CSS

django.contrib.staticfiles: it collects static files from each of your applications (and any other places you specify) into a single location that can easily be served in production.

Customize your app’s look and feel

  1. create a directory called static in your poll app directory.
    • Django will look for static files there, similarly to how Django finds templates inside polls/templates
    • looks for a "static" subdirectory in each of the INSTALLED_APPS
  2. within the static directory you have just created, create another directory called polls
  3. within the static/polls directory, create a file called style.css
  4. your stylesheet should be at polls/static/polls/style.css, you can just refer to this static file in Django simply as polls/style.css, similar to how you reference the path for templates
# polls/static/polls/style.css

li a {
    color: green;
}
# polls/templates/polls/index.html

{% load static %}

<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}" />

The {% static %} template tag generates the absolute URL of static files.

Adding a background-image

7. Customizing the admin site

import urllib2
import simplejson
 
response = urllib2.urlopen("http://172.0.0.1:8000/custom/get/")
data = simplejson.load(response)

print data
# => {'content': 'Hello World!', 'success': True} 
import urllib2
import simplejson
 
response = urllib2.urlopen("http://172.0.0.1:8000/custom/get/")
data = simplejson.load(response)

print data["content"]
# => Hello World!
# Array example

import urllib2
import json

req = urllib2.Request("http://vimeo.com/api/v2/video/38356.json")
opener = urllib2.build_opener()
f = opener.open(req)
json = json.loads(f.read())

print json
print json[0]['title']

Contents

  • Writing views
  • A simple view
  • Mapping URLs to views
  • Returning errors
  • The Http404 exception
  • Customizing error views

Writing views

view = a Python function that:

  • (1)takes a Web request
  • (2)returns a Web response
  • (3)arbitrary logic that is necessary to return that response

web response:

  • the HTML contents of a Web page
  • a redirect
  • a 404 error
  • an XML document
  • an image
  • ...etc.

put views in a file called views.py

A simple view

Contents

  • Templates
    • Support for template engines
      • Configuration
      • Usage
      • Built-in backends
      • Custom backends
      • Debug integration for custom engines
        • Template postmortem
        • Contextual line information
        • Origin API and 3rd-party integration
    • The Django template language
      • Syntax
        • Variables
        • Tags
        • Filters
        • Comments
      • Components
        • Engine
        • Template
        • Context
        • Loaders
        • Context processors

Syntax

a Django template = a text document / a Python string marked-up using the Django template language(DTL)

the main ones:

  • variable
  • tag

A template is rendered with a context.

Rendering replaces variables with their values, which are looked up in the context, and executes tags. Everything else is output as is.

Variables

A variable outputs a value from the context, which is a dict-like object mapping keys to values.

Variables are surrounded by {{ and }} like this:

My first name is {{ first_name }}. My last name is {{ last_name }}.

With a context of {'first_name': 'John', 'last_name': 'Doe'}, this template renders to:

My first name is John. My last name is Doe.

Dictionary lookup, attribute lookup and list-index lookups are implemented with a dot notation:

{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}

If a variable resolves to a callable, the template system will call it with no arguments and use its result instead of the callable.

Tags

Tags provide arbitrary logic in the rendering process.

A tag can:

  • output content
  • serve as a control structure
    • e.g. an “if” statement or a “for” loop
  • grab content from a database
  • enable access to other template tags

Tags are surrounded by {% and %} like this:

{% csrf_token %}

Most tags accept arguments:

{% cycle 'odd' 'even' %}

Some tags require beginning and ending tags:

{% if user.is_authenticated %}Hello, {{ user.username }}.{% endif %}

Filters

Filters transform the values of variables and tag arguments.

They look like this:

{{ django|title }}

With a context of {'django': 'the web framework for perfectionists with deadlines'}, this template renders to:

The Web Framework For Perfectionists With Deadlines

Some filters take an argument:

{{ my_date|date:"Y-m-d" }}

Comments

Comments look like this:

{# this won't be rendered #}

A {% comment %} tag provides multi-line comments.


Components

Engine

django.template.Engine encapsulates an instance of the Django template system. The main reason for instantiating an Engine directly is to use the Django template language outside of a Django project.

django.template.backends.django.DjangoTemplates is a thin wrapper adapting django.template.Engine to Django’s template backend API.

Template

django.template.Template represents a compiled template. Templates are obtained with Engine.get_template() or Engine.from_string()

Likewise django.template.backends.django.Template is a thin wrapper adapting django.template.Template to the common template API.

Context

django.template.Context holds some metadata in addition to the context data. It is passed to Template.render() for rendering a template.

django.template.RequestContext is a subclass of Context that stores the current HttpRequest and runs template context processors.

The common API doesn’t have an equivalent concept. Context data is passed in a plain dict and the current HttpRequest is passed separately if needed.

Loaders

Template loaders are responsible for locating templates, loading them, and returning Template objects.

Django provides several built-in template loaders and supports custom template loaders.

Context processors

Context processors are functions that receive the current HttpRequest as an argument and return a dict of data to be added to the rendering context.

Their main use is to add common data shared by all templates to the context without repeating code in every view.

Django provides many built-in context processors. Implementing a custom context processor is as simple as defining a function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment