91django_基本使用

 

目錄

django. 1

django-admin startproject. 3

django-admin startapp. 5

model... 7

view中使用model... 10

template. 11

view中使用template... 13

去掉urlstatic硬編碼:... 15

url反解析:... 15

url命名空間:... 15

form處理:... 16

 

 

 

django

py下一款著名的web框架;

 

框架,是整個或部分系統的可重用設計,表現爲一組抽象構件及構件實例間交互的方法;

是可被應用開發者定製的應用骨架;

其它web框架:flasktornado

 

django優:

自帶輪子衆多,方便快速開發,如ORMAuthCacheTemplateFrom核心組件;

天生的MVC設計模式;

實用且強大的管理後臺;

簡潔的url設計;

周邊插件豐富;

 

django缺:

重;

同步阻塞;

 

django設計哲學:

大而全;

快速開發;

 

django歷史:

最初開發者,AdrianSimon

開發背景,World Online維護幾個新聞站點,要求快速發佈新聞,快速建立其它新聞站點(快速開發、數據驅動);

World Online05年夏天開源;

 

https://www.djangoproject.com/

 

(django) C:\django>pip install django==1.11

(django) C:\django>ipython

In [1]: import django

In [2]: django.get_version()

Out[2]: '1.11'

 

django version

python versions

1.8

2.7,3.2,3.3,3.4,3.5

1.9,1.10

2.7,3.4,3.5

1.11

2.7,3.4,3.5,3.6

2.0

3.4,3.5,3.6

2.1

3.5,3.6,3.7

 

響應流程:

1.jpg

 

django-admin startproject

pycharmNew Project-->webprojectC:\webproject

(webproject) C:\webproject>django-admin startproject mysite   #或用python manage.py startproject mysite;此命令腳本在虛擬環境的C:\Users\Administrator\py_env\webproject\Scriptsdjango-admin.exe

2.jpg

3.jpg

4.jpg

mysite/mysite/sessings.py   #項目配置

 

mysite/mysite/urls.py   #入口url

def url(regex, view, kwargs=None, name=None):   #viewfunction object,不是函數調用;view函數的第一參數永遠是request,不探討CBVview函數的返回值永遠是HttpResponse對象,顯式或隱式;

url(r'^hello/$', hello),   #django默認會給url後加/,此處定義,hello前不帶/hello後一定要有/,這樣即使用戶訪問http://127.0.0.1:8000/hello也會自動跳到http://127.0.0.1:8000/hello/上;若此處配置爲r'^hello$',用戶訪問http://127.0.0.1:8000/hello/,訪問的地址無論是否帶/都會報404;所以記住,此處定義的urlhello前沒有/hello後要有/

url(r'^$', views.index, name='index')   #app中的urls.py,可通過name反解出url

url(r'^polls/', include('polls.urls')),   #項目中的urls.pyinclude裏是str,在用到時才動態導入;

 

mysite/mysite/wsgi.py   #生產部署時調用

 

注:

include源碼,from django.conf.urls import url, include

def include(arg, namespace=None, app_name=None):

 

 

例:

urls.py

from django.conf.urls import url

from django.contrib import admin

 

from django.http import HttpResponse

 

def index(request):

    return HttpResponse('this is index')

 

def hello(request):   #view函數的第一個參數永遠是request,不探討CBV

    return HttpResponse('Hello world')

 

urlpatterns = [   #urlpatterns約定俗成的名字

    url(r'^$', index),

    url(r'^hello/$', hello),   #django默認會給url後加/,此處定義,hello前不帶/hello後一定要有/,這樣即使用戶訪問http://127.0.0.1:8000/hello也會自動跳到http://127.0.0.1:8000/hello/上;若此處配置爲r'^hello$',用戶訪問http://127.0.0.1:8000/hello/,訪問的地址無論是否帶/都會報404;所以記住,此處定義的urlhello前沒有/hello後要有/

    url(r'^admin/', admin.site.urls),

]

 

(webproject) C:\webproject\mysite>python manage.py runserver   #可自定義ip:portpython manage.py runserver 0.0.0.0:8080,啓動的是django內置webserver,用於測試

 

5.jpg

6.jpg

 

 

django-admin startapp

 

django appdjango project區別:

app中才能用model

app設計是可插拔的,app不一定在project中;

settings.py中有內置的app,可根據項目情況禁用;

 

 

(webproject) C:\webproject\mysite>django-admin startapp polls   #或用python manage.py startapp polls,新建投票app,在項目根下操作

7.jpg

admin.py   #後臺管理

apps.py   #1.8ver後加的,app的獨立配置

tests.py   #測試用例

views.py   #業務邏輯

migrations/   #model的版本控制有關

 

 

例:

mysite/mysite/settings.py   #在項目settings.py中導入app

INSTALLED_APPS = [

    'polls.apps.PollsConfig',

    'django.contrib.admin',

    'django.contrib.auth',

    'django.contrib.contenttypes',

    'django.contrib.sessions',

    'django.contrib.messages',

    'django.contrib.staticfiles',

]

 

mysite/polls/views.py

from django.shortcuts import render

from django.http import HttpResponse

 

def index(request):

    return HttpResponse('this is index at polls')

 

mysite/polls/urls.py   #app中的urls.py默認不存在,新建

urlpatterns = [

    url(r'^$', views.index, name='index')

]

 

mysite/mysite/urls.py

urlpatterns = [

    url(r'^polls/', include('polls.urls')),   #include中是str,在用到時才動態導入

    url(r'^admin/', admin.site.urls),

]

 

8.jpg

 

 

model

支持sqlitemysqlpostgresqloracle

py3.5以上版本,不支持MySQLdb驅動;

可用pymysqlpy寫的;

可用mysqlclientc寫的,速度快,forkMySQLdb,官方推薦;

 

ORM,用py的方法、數據結構,來訪問db,可兼容不同的DB

 

一個class代表一張表,多對多會產生額外一張關係表;

默認pkid,也可自定義pk

表名默認爲$APP_NAME$CLASS_NAME.lower(),表名小寫(跨平臺支持),可重寫;

 

models migrations

定義好models.py需應用到dbdjango爲了能跟蹤表結構的變化,增加了migration版本控制功能,如果沒有該功能,需手動編寫表結構變化的語句,重新導入數據;

 

models CRUD

增:

q = Question(**kwargs)   #方式1

q.save()

 

q = Question.objects.create(**kwargs)   #方式2

 

刪:

q = Question.objects.get(id=1)

q.delete()

 

Question.objects.filter(id=1).delete()

Question.objects.all().delete()

 

改:

q = Question.objects.get(id=1)

q.question_text = 'some text'

q.save()

 

Question.objects.filter(id=1).update(question_text='why ?')

 

查:

Question.objects.all()

Question.objects.filter(question_text="what's up?")   #objectsmodel默認的manager管理器

Question.objects.get(id=1)

latest_question_list = Question.objects.order_by('-pub_date')[:3]   #默認升序,加上-倒序

 

注:

>>> from django.utils import timezone

>>> import datetime

>>> timezone.now()   #datetime.datetime.now()多了時區,在頁面展示時,django內部會轉爲適合用戶所在的時區

datetime.datetime(2019, 1, 2, 7, 2, 18, 244920, tzinfo=<UTC>)

>>> datetime.datetime.now()

datetime.datetime(2019, 1, 2, 15, 2, 32, 837755)

 

models中方法:

def __str__(self):

         return self.question_text

def was_published_recently(self):

         return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

 

 

mysite/mysite/settings.py

DATABASES = {

    'default': {

        'ENGINE': 'django.db.backends.sqlite3',

        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),

    }

}

 

 

mysite/polls/models.py

from django.db import models

 

class Question(models.Model):   #一個class代表一張表,多對多會產生額外一張關係表;默認pkid,也可自定義pk;表名默認爲$APP_NAME$CLASS_NAME.lower(),可重寫

    question_text = models.CharField(max_length=200)

    pub_date = models.DateTimeField('date published')

 

class Choice(models.Model):

    question = models.ForeignKey(Question, on_delete=models.CASCADE)

    choice_text = models.CharField(max_length=200)

    votes = models.IntegerField(default=0)

 

(webproject) C:\webproject\mysite>python manage.py makemigrations   #生成遷移記錄

(webproject) C:\webproject\mysite>python manage.py migrate   #應用到db

(webproject) C:\webproject\mysite>sqlite3 db.sqlite3

sqlite> .tables

auth_group                  django_admin_log

auth_group_permissions      django_content_type

auth_permission             django_migrations

auth_user                   django_session

auth_user_groups            polls_choice

auth_user_user_permissions  polls_question

sqlite> .quit

 

(webproject) C:\webproject\mysite>dir polls\migrations\

 驅動器 C 中的卷是 OS

 卷的序列號是 000B-5D26

C:\webproject\mysite\polls\migrations 的目錄

2019/01/02  14:24    <DIR>          .

2019/01/02  14:24    <DIR>          ..

2019/01/02  14:24             1,266 0001_initial.py

2019/01/02  11:29                 0 __init__.py

2019/01/02  14:25    <DIR>          __pycache__

               2 個文件          1,266 字節

               3 個目錄 77,168,365,568 可用字節

(webproject) C:\webproject\mysite>python manage.py sqlmigrate polls 0001_initial   #查看sql語句是否是指定要求的

 

(webproject) C:\webproject\mysite>python manage.py shell   #進入交互式命令行

>>> from django.utils import timezone

>>> from polls.models import Question,Choice

>>> q = Question(question_text="what's new", pub_date=timezone.now())

>>> q.save()

>>> q.id

1

>>> q.pk

1

>>> q.question_text

"what's new"

>>> q.pub_date

datetime.datetime(2019, 1, 2, 6, 49, 16, 612213, tzinfo=<UTC>)

 

>>> from polls.models import Question,Choice

>>> from django.utils import timezone

>>> q = Question.objects.create(question_text="how are you?", pub_date=timezone.now())

>>> q = Question.objects.create(question_text="what's the weather?", pub_date=timezone.now())

>>> q = Question.objects.create(question_text="fuck you!", pub_date=timezone.now())

>>> q

<Question: fuck you!>

>>> q.was_published_recently()

True

>>> d = timezone.now() - timezone.timedelta(days=2)

>>> q.pub_date = d

>>> q.save()

>>> q.was_published_recently()

False

 

 

view中使用model

from django.http import HttpResponse

from .models import Question

 

def index(request):

    latest_question_list = Question.objects.order_by('-pub_date')[:3]   #默認升序,加上-倒序

    output = ', '.join([q.question_text for q in latest_question_list])

    return HttpResponse(output)

 

def detail(request, question_id):

    return HttpResponse('Your are looking at question {}'.format(question_id))

 

def results(request, question_id):

    response = 'Your are looking at results of question {}'.format(question_id)

    return HttpResponse(response)

 

def vote(request, question_id):

    return HttpResponse('Your are voting on question {}'.format(question_id))

 

 

template

django內置了自己的模板引擎,和jinja很像,使用簡單;

 

django默認會在app_name/templates/下尋找模板,在app_name/templates/下再建立app_name,這樣app_name/templates/app_name/下存放與該app相關的模板,因爲默認django會去所有的app下找模板,可能會優先找到其它app下的模板;

默認會到app_name/static/下尋找靜態文件;

 

設置公用templates和公用static

mysite/mysite/settings.py

TEMPLATES = [

    {

        'BACKEND': 'django.template.backends.django.DjangoTemplates',

        'DIRS': [os.path.join(BASE_DIR, 'templates')],

        'APP_DIRS': True,

……

STATIC_URL = '/static/'

STATICFILES_DIRS = [

    os.path.join(BASE_DIR, 'static'),

]

 

 

>>> from django.template import Template,Context

>>> t = Template('My name is {{ name }}')

>>> c = Context({'name':'jowin'})   #context可以是 dict、屬性、方法、tuple|list

>>> t.render(c)

'My name is jowin'

 

>>> t = Template('my name is {{ name }}')

>>> d = {'name':'jowin'}

>>> c = Context(d)

>>> t.render(c)

'my name is jowin'

 

>>> t = Template('my name is {{ user.name }}')   #變量查找,dictattrmethodlisttuple

>>> class Person:

...     def __init__(self,name):

...             self.name = name

...

>>> user = Person('jowin')

>>> user.name

'jowin'

>>> c = Context({'user':user})

>>> t.render(c)

'my name is jowin'

 

>>> t = Template('my name is {{ user.name }}')

>>> class Person:

...     def name(self):

...             return 'jowin'

...

>>> user = Person()

>>> user.name()

'jowin'

>>> c = Context({'user':user})

>>> t.render(c)

'my name is jowin'

 

模板引擎支持循環、判斷、過濾器:

for

{% for person in person_list %}

<li> {{ person.name }} </li>

{% endfor %}

 

if

{% if max > 10 %}

<li>max value is {{ max }} </li>

{% else %}

<li>max value is 10 </li>

{% endif %}

 

過濾器:

{{ now | date:"F j,Y" }}

{{ name | length }}

 

 

view中使用template

 

render源碼,from django.shortcuts import render

def render(request, template_name, context=None, content_type=None, status=None, using=None):

    """

    Returns a HttpResponse whose content is filled with the result of calling

    django.template.loader.render_to_string() with the passed arguments.

    """

    content = loader.render_to_string(template_name, context, request, using=using)

    return HttpResponse(content, content_type, status)

 

另,render_to_response(),老版本1.6用;

 

 

mysite/polls/views.py

from django.http import HttpResponse

from .models import Question

from django.template import loader

 

# def index(request):

#     latest_question_list = Question.objects.order_by('-pub_date')[:4]

#     template = loader.get_template('polls/index.html')

#     context = {'latest_question_list': latest_question_list}

#     # output = ', '.join([q.question_text for q in latest_question_list])

#     return HttpResponse(template.render(context))   #1

def index(request):

    latest_question_list = Question.objects.order_by('-pub_date')[:4]

    context = {'latest_question_list': latest_question_list}

    return render(request, 'polls/index.html', context)   #2

 

mysite/polls/templates/polls/index.html

<img src="/static/django.png">   #mysite/polls/static/django.png

{% if latest_question_list %}

    <ul>

        {% for question in latest_question_list %}

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

        {% endfor %}

    </ul>

{% endif %}

 

(webproject) C:\webproject\mysite>python manage.py runserver

9.jpg

 

 

去掉urlstatic硬編碼:

 

mysite/polls/templates/polls/index.html

{% load static %}

 

<img src="{% static 'django.png' %}">

{% if latest_question_list %}

    <ul>

        {% for question in latest_question_list %}

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

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

        {% endfor %}

    </ul>

{% endif %}

 

注:

{% url 'detail' question.id %}   #appurls.py中定義的name有關;app namespace改後,'detail'改爲'polls:detail'

 

 

url反解析:

 

正解析,url-->view

反解析,view-->url

 

>>> from django.shortcuts import reverse

>>> reverse('detail',kwargs={'question_id':1})

'/polls/1/'

 

另,reverse_lazy(),爲解決循環依賴;

 

 

url命名空間:

 

app namespaceinstance namespace

通常使用app namespace

app有多個include,使用instance namespace

 

app namespace

 

mysite/polls/urls.py   #1,建議使用,在app_name/urls.py中定義

app_name = 'polls'

 

mysite/mysite/urls.py

url(r'^polls/', include('polls.urls', app_name='polls')),   #2,在項目下定義mysite/mysite/urls.py

 

 

instance namespace

instance級別,名稱不可以重複;

 

mysite/mysite/urls.py

url(r'^polls/', include('polls.urls', namespace='polls')),

 

 

form處理:

 

mysite/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 %}">

{% csrf_token %}

    {% 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>

 

 

mysite/polls/views.py

from django.shortcuts import render, get_object_or_404, reverse

from django.http import HttpResponse, HttpResponseRedirect

from .models import Question, Choice

from django.template import loader

# from django.core.urlresolvers import reverse

 

 

# def index(request):

#     latest_question_list = Question.objects.order_by('-pub_date')[:4]

#     template = loader.get_template('polls/index.html')

#     context = {'latest_question_list': latest_question_list}

#     # output = ', '.join([q.question_text for q in latest_question_list])

#     return HttpResponse(template.render(context))

def index(request):

    latest_question_list = Question.objects.order_by('-pub_date')[:4]

    context = {'latest_question_list': latest_question_list}

    return render(request, 'polls/index.html', context)

 

def detail(request, question_id):

    # try:

    #     question = Question.objects.get(id=question_id)

    # except Question.DoesNotExist:

    #     return HttpResponse('Not Found', status=404)

    question = get_object_or_404(Question, pk=question_id)

    return render(request, 'polls/detail.html', {'question': question})

 

def results(request, question_id):

    question = get_object_or_404(Question, pk=question_id)

    return render(request, 'polls/results.html', {'question': question})

 

def vote(request, question_id):

    question = get_object_or_404(Question, pk=question_id)

    print(request)

    if request.method == 'POST':

        choice_id = request.POST.get('choice', 0)

        try:

            selected_choice = question.choice_set.get(pk=choice_id)

        except Choice.DoesNotExist:

            return render(request, 'polls/detail.html', {

                'question': question, 'error_message': 'You did not select a choice',

            })

        else:

            selected_choice.votes += 1

            selected_choice.save()

            return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

 

 

mysite/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>

 

 

 

項目中使用:

pip install pymysql

pip install pillow   #ImageField依賴

 

 

1、  數據庫使用mysql

項目目錄的__init__.py

import pymysql

pymysql.install_as_MySQLdb()

 

DATABASES = {

  'default': {

      'ENGINE': 'django.db.backends.mysql',

      'NAME': 'mxonline',

      'USER': 'mxonline',

      'PASSWORD': '123456',

      'HOST': '192.168.88.222',

      'PORT': 3306

  }

 

 

2apps目錄下統一放app

右鍵apps-->Mark directory as-->Source Root   #解決編輯器查找import時可在apps中找

 

import sys

sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))   #解決命令行環境查找

 

 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章