Note 6: Django basis

Django-MVT

(1) View python version:

python -m django --version

(2) Create a Django project

django-admin startproject mysite

(3) successful test development server

Desktop\bncDjango\mysite>python manage.py runserver

Django comes with a writing pure Python lightweight Web server. In order to let you quickly develop what they want, because you do not need production-level server configuration work (such as Apache) terms, unless you are ready to put into the production environment. Never will this server be used anywhere and production of environment-related. The server just for the development and design. (We are specialists in Web framework, not in terms of the Web server.)

(4) create application modules

python manage.py startapp polls

Application definition

INSTALLED_APPS = [
'django.contrib.admin', # 管理员站点
'django.contrib.auth', # 认证授权系统
'django.contrib.contenttypes', # 内容类型框架
'django.contrib.sessions', # 会话框架
'django.contrib.messages', # 消息框架
'django.contrib.staticfiles', #管理静态文件的框架
'polls', # 投票模块]

(5) the view edit view polls Model


from django.shortcuts import render

Create your views here.

from django.http import HttpResponse

def index(request):
return HttpResponse("Hello,this is my frist polls index.")

Mapping the url (6) polls module


from django.urls import path
from . import views

urlpatterns = [
path('', views.index,name='index'),]

Url the configuration (7) mysite main module


from django.contrib import admin
from django.urls import path,include # 注意导入include模块

urlpatterns = [
path('polls/', include('polls.urls')), # 配置polls子模板url,支持正则
path('admin/', admin.site.urls),]

(8) query page http: // localhost: 8000 / polls /

1560157077719

(9) database configuration and migration

DATABASES = {
'default': {
# 'django.db.backends.sqlite3',
# 'django.db.backends.postgresql',
# 'django.db.backends.mysql',
# 'django.db.backends.oracle'
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
# MySQL数据库配置
# 'mysql': {
# 'ENGINE': 'django.db.backends.mysql',
# 'NAME': 'all_news', # 数据库名
# 'USER': 'root',
# 'PASSWORD': 'root',
# 'HOST': '127.0.0.1',
# 'PORT': '3306',
# }
}

python manage.py migrate

(10) the preparation of model M


from django.db import models

Create your models here.

class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_data = models.DateField('date published')

def __str__(self):
    return self.question_text

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

(11) activation model

Generate migrate files to change the model

python manage.py makemigrations polls

1560158954875

Another view, select, execute name to receive a migration, then returns the corresponding SQL

python manage.py sqlmigrate polls 0001

Application database migration

python manage.py migrate

(12) Automatic admin page

12.1 can create a login user management page, both admin

python manage.py createsuperuser

12.2 start the development server:

python manage.py runserver

http://127.0.0.1:8000/admin/login/?next=/admin/

12.3 Enter site

1560159957646

12.4 Application Configuration Management page added


from django.contrib import admin

Register your models here.

from .models import Question,Choice

admin.site.register(Question)
admin.site.register(Choice)

(13) write more views

views at 13.1 polls

from django.shortcuts import render
from django.http import HttpResponse

问题索引页

def index(request):
return HttpResponse("Hello,this is my frist polls index.")

问题详情页

def detail(request,question_id):
return HttpResponse("You're looking at question %s." % question_id)

问题结果页

def results(request,question_id):
return HttpResponse("You're looking at the results of question %s." % question_id)

投票处理器

def vote(request,question_id):
return HttpResponse("You're voting on question %s." % question_id)

Urls at 13.2 polls remember to add the namespace


from django.urls import path
from . import views
app_name = 'polls' #添加命名空间
urlpatterns = [
# ex: /polls/
path('', views.index,name='index'),
# ex: /polls/5/
path(' /', views.detail, name='detail'),
# ex: /polls/5/results/
path(' /results/', views.results, name='results'),
# ex: /polls/5/vote/
path(' /vote/', views.vote, name='vote'),]

13.3 query database information and display the page

问题索引页

def index(request):
latest_question_list = Question.objects.order_by('pub_data')[:3]
output = '
'.join([q.question_text for q in latest_question_list])
HttpResponse(template.render(context,request))
return HttpResponse(output)

1560224171794

(14) the preparation of template T

14.1 created under mysite templates, and create polls folder, create a index.html


<!DOCTYPE html>


投票页面


{% if latest_question_list %}


{% else %}

No polls are available.


{% endif %}


It can be modified (common) would like to change. polls/specifics/12/You do not change anything in the template (including other template), as long as polls/urls.pya little tinkering on the line:

{% for question in latest_question_list %}

  • {{ question.question_text }}

  • {% endfor %}

    14.2 modify the settings mysite of DIRS


    TEMPLATES = [
    {
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [os.path.join(BASE_DIR,'template/')],
    'APP_DIRS': True,
    'OPTIONS': {
    'context_processors': [
    'django.template.context_processors.debug',
    'django.template.context_processors.request',
    'django.contrib.auth.context_processors.auth',
    'django.contrib.messages.context_processors.messages',
    ],
    },
    },]

    14.3 polls / views.py modification


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

    from polls.models import Question

    问题索引页

    def index(request):
    latest_question_list = Question.objects.order_by('pub_data')[:5]
    # output = '
    '.join([q.question_text for q in latest_question_list])
    template = loader.get_template('polls/index.html')
    context = {
    'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context,request))

    It is further modified to (common):

    问题索引页

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

    Access 14.4 "/ polls /" in your browser to view:

    1560225187403

    (15) View detail page

    Under 15.1 polls views.py


    from django.http import Http404

    问题详情页

    def detail(request,question_id):
    try:
    question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
    raise Http404("Question does not exist")
    return render(request,'polls/detail.html', {'question':question,'question_id':question_id})

    Algorithm (used) optimized


    from django.shortcuts import render,get_object_or_404

    问题详情页

    def detail(request,question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question,'question_id':question_id})

    15.2 template下detail.html


    <!DOCTYPE html>


    详细问题页面


    {{ question.question_text }}



      {% for choice in question.choice_set.all %}
    • {{ choice.choice_text }}

    • {% endfor %}

    15.3 operating results

    1560232295937

    (16) polls / detail.html detail page add a form form



    {{ question.question_text }}

    {% if error_message %}

    {{ error_message }}


    {% endif %}

    {% csrf_token %} {% for choice in question.choice_set.all %}
    {% endfor %}

    • Each radio button valueattribute corresponding to the respective Choice's ID. Each radio button nameShi "choice". This means that when someone chooses a radio button and submit the form submission, it will send a POST data choice=#, where # is the selected Choice of ID. This is the basic concept of the HTML form.

    • We set the form actionto {% url 'polls:vote' question.id %}, and set method="post". Use method = "post" is very important because this will change the behavior of the submission form data on the server side. When you need to change the form to create a server-side data, use ` method="post". This is not specific skills of Django; this is an excellent web development skills.
    • forloop.counterIndicating forlabel has cycled many times.
    • As we create a POST form (which has the effect of modifying data), so we need to be careful cross-site request forgery. Thankfully, you do not have to worry too much, because Django already has a system to defend against it very easy to use. In short, for all the internal URL of the POST form should use {% csrf_token %}template tags.

    (17) polls/views.pyView Edit

    投票处理器

    def vote(request,question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
    selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
    return render(request, 'polls/detail.html', {
    'question': question,
    'error_message': "You didn't select a choice.",})
    else:
    selected_choice.votes +=1
    selected_choice.save()
    return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

    • request.POSTIt is a dictionary-like object, so you can get the data submitted by name keywords. In this example, request.POST['choice']go back and select a string Choice's ID. request.POSTThe value is always a string.
    • If you request.POST['choice']do not provide the data choice, POST will lead to a KeyError. The above code checks KeyError, if not given choicethe form and redisplay Question an error message.
    • After the increase of the number of votes Choice, a code is returned HttpResponseRedirectinstead of the usual HttpResponse, HttpResponseRedirectreceives only one parameter: the user will be redirected in the URL. Using the constructor reverse()functions. This function avoids us hard-coded URL in the view function. The URL will redirect calls 'results'view to display the final page.

    (18) redirects results.html


    from django.shortcuts import get_object_or_404, render

    def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question': question})

    (19) General view refactoring

    19.1 detail()view is almost identical. The only difference is the name of the template.

    问题索引页

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

    问题详情页

    def detail(request,question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question,'question_id':question_id})

    问题结果页

    def results(request,question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question': question})

    19.2 Creating a polls/results.htmltemplate


    {{ question.question_text }}

      {% for choice in question.choice_set.all %}
    • {{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}
    • {% endfor %}

    Vote again?

    19.3 General view of the system

    General view of the common mode of abstraction, you can make when writing applications do not even need to write Python code. Convert our poll application to use the generic views system, so we can remove a lot of our code. We just need to do the following steps to complete the conversion,

    • Conversion URLconf.
    • Delete some of the old view is no longer needed.
    • Introducing new view based on a common view of Django

    1 modified URLconf

    Open polls/urls.pythe URLconf and it is modified to: the path name string has been matched by the pattern <question_id>changed <pk>.


    from django.urls import path
    from . import views

    app_name = 'polls'
    urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path(' /', views.DetailView.as_view(), name='detail'),
    path(' /results/', views.ResultsView.as_view(), name='results'),
    path(' /vote/', views.vote, name='vote'),]

    2 Improved view

    Remove the old index, detailand resultsthe view, and replaced with generic views Django. Open the polls/views.pyfile and modify it to:


    from django.http import HttpResponseRedirect
    from django.shortcuts import get_object_or_404, render
    from django.urls import reverse
    from django.views import generic

    from .models import Choice, Question

    class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        return Question.objects.order_by('pub_date')[:5]

    class DetailView(generic.DetailView):
    model = Question
    template_name = 'polls/detail.html'

    class ResultsView(generic.DetailView):
    model = Question
    template_name = 'polls/results.html'

    def vote(request,question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
    selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
    return render(request, 'polls/detail.html', {
    'question': question,
    'error_message': "You didn't select a choice.",
    })
    else:
    selected_choice.votes +=1
    selected_choice.save()
    return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

    • Each generic view needs to know which model it will act on. This is done by modelproviding property.
    • DetailViewWe expect to capture from the URL named "pk"primary key, so we put the generic view question_idchanged pk.

    19.4 run the program

    main page

    1560238410789

    Subpage

    1560238566648

    Details page

    1560238740884

    (20) automated testing

    20.1 Testing Strategies

    • Test drive: the first to write tests before you write code. Development methodology "test drive" the only problem will be described in the abstract test case for Python.
    • More generally the case that a novice new to automated testing more inclined to write the code, and then write the test.
    • If you only write thousands of lines of Python code, choose where to start writing tests really very simple. If this is the case, then write a test before the next time you modify the code (such as adding new features or fix Bug) is a more reasonable and effective.

    20.2 The first test

    Requirements: Our requirement is that if Question is released in one day, was_published_recently () 方法将会返回True ,然而现在这个方法在Question pub_date` field will also return True, later than the current time

    Write test code:


    from django.test import TestCase

    Create your tests here.

    from django.utils import timezone
    from .models import Question

    class QuestionModelTests(TestCase):
    def test_was_published_recently_with_future_question(self):
    """
    was_published_recently() returns False for questions whose pub_date
    is in the future.
    """
    time = timezone.now() + datetime.timedelta(days=30)
    future_question = Question(pub_date=time)
    self.assertIs(future_question.was_published_recently(), False)

    Run the code: $ python manage.py test polls

    1560239307381

    Test Results:

    • python manage.py test pollsYou will find pollsapplication in the test code
    • It found django.test.TestCaseone of its subclasses
    • It creates a special database for testing
    • It is looking for test methods in a class - A testmethod beginning.
    • In the test_was_published_recently_with_future_questionprocess, it creates a pub_datevalue of 30 days Questioninstance.
    • Then use the assertls()method, we discovered was_published_recently()returns True, and we expect it to return False.

    Tell us what the test system test sample fails, the test fails and causes the line number of the code is located.

    (21) static files (pictures / script / style)

    For small projects, in which static files easily, as long as the server can find them on the line. However, in large projects, working static files needed for different applications becomes a bit of trouble. This is the django.contrib.staticfilesmeaning of existence

    Created staticfolder, create pollsa file folder, and then in the pollsCreate a folder named style.cssfile. Stylesheet path should be polls/static/polls/style.css. Because AppDirectoriesFinderof the presence, you can simply use the order in Django polls/style.cssform reference this file, similar to the way you quote template path.

    li a {
        color: green;
    }

    The polls cited index.html



    投票页面
    {% load static %}


    add pictures

    We will create a directory for the presence of the image. In polls/static/pollsCreate a directory named imagessubdirectories. In this directory, called a put background.gifpicture. In other words, in the catalog polls/static/polls/images/background.jpgput a picture.


    body {
    background: white url("images/background.gif") no-repeat;
    }

    1560241682953

    For more information on setting the framework and reference static files doubts and static files guide . Deploy static files describes how to use a static file on the real servers.

    (22) the first to write a django application

    22.1 polls / admin form defined background, the display order list for the field


    from django.contrib import admin

    Register your models here.

    from .models import Question,Choice

    class QuestionAdmin(admin.ModelAdmin):
    # fieldsets = [
    # ('问题内容', {'fields': ['question_text']}),
    # ('发布时间', {'fields': ['pub_data']}),
    # ]
    # fields = ['pub_data', 'question_text']
    list_display = ('question_text', 'pub_data')

    admin.site.register(Question, QuestionAdmin)

    class ChoiceAdmin(admin.ModelAdmin):
    # fields = ['question','choice_text', 'votes']
    list_display = ('question','choice_text', 'votes')

    admin.site.register(Choice, ChoiceAdmin)

    Field filter 22.2


    class QuestionAdmin(admin.ModelAdmin):
    list_display = ('question_text', 'pub_data')
    list_filter = ['pub_data'] # 过滤器
    admin.site.register(Question, QuestionAdmin)

    1560245385467

    22.3 custom background and style of interface

    • Open your settings file ( mysite/settings.pyand remember), in TEMPLATESadding setting DIRSoptions:
    • In the templatesCreate a directory named in the admindirectory, then the default directory where Django template ( django/contrib/admin/templatestemplate files) within admin/base_site.htmlcopied into this directory. Where Django source files? $ Python -c "import django; print (django .__ path__)"1560246196010

    • Then, replace [in the file with the name of your site ](https://docs.djangoproject.com/zh-hans/2.2/intro/tutorial07/#id1){{ site_header|default:_('Django administration') }}(curly braces). Upon completion, you should see the following code:


    {% block branding %}

    Polls Administration


    {% endblock %}

    1560246347716

    Guess you like

    Origin www.cnblogs.com/baiboy/p/11014392.html