Mac docker creates the first Django application, Part 3

Time:2020-2-23

Step 3: MAC docker creates the first Django application, Part 3

Writing your first Django app, Part 3
In this article, Python is built in Django compose + Django to execute python, which needs to enter the web server container. Please refer to [step 1: build Django container on MAC]
Translation: CK

Part 3: development front end

1. overview

A view is a web page serving a specific function. For example, in this example, there are four views:

  • Question “index” page – shows the latest questions
  • Question “detail” page – displays a question and provides an answer sheet without an answer
  • Question “results” page – shows the answer to a specific question
  • Vote action – handles voting on a specific issue

In djanog, web pages and other contents are displayed through views. Each view is equivalent to a simple Python function (or method, in class based view). URL to view mapping is done in urlconf.

2. Write more views

Add to poll / 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)

Add to poll.urls

from django.conf.urls import url

from . import views

urlpatterns = [
    # ex: /polls/
    url(r'^$', views.index, name='index'),
    # ex: /polls/5/
    url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
    # ex: /polls/5/results/
    url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
    # ex: /polls/5/vote/
    url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]

Take http://127.0.0.1:8000/polls/34/ for example. The URL matches the part other than the domain name, and the URL in root’urlconfurl(r'^polls/', include('polls.urls')),After matching “poll /”, send the remaining “34 /” to “poll. URLs’ urlconf” for further processing,(?P<question_id>[0-9]+)Parentheses are used to capture values, and “? P<question id>” is used to define the name of the pattern to be matched. [0-9] + matches 1 to more than one number. Finally, the matching 34 is passed to the detail method as a parameter.

3. Write some useful views

Each view is responsible for returning an httpresponse object or an exception such as http404
List the last five questions:

from django.http import HttpResponse

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    output = ', '.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)

# Leave the rest of the views (detail, results, vote) unchanged

The disadvantage of this is that the content of the page is written in the view code. If you want to change the appearance of the page, you have to modify the Python code. You can use a template system to distinguish Python from page design. How Django loads and renders templates is described in the templates setting of setting.py. It is customary for Django to look up the Templates folder in the directory of each installed app.

Establishpolls/templates/polls/index.htmlWrite in:

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

modifypolls/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))

This code loadspolls/templates/polls/index.htmlAnd pass in a context. This context is a dictionary that maps the variable names of the template to Python objects.

A quick render () method, the common method is to load the template, fill in the context, and return an httpresponse object containing the template after rendering. Django provides a shortcut as follows:

Rewritepolls/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)

4. Report a 404 error

modifypolls/views.py

from django.http import Http404
from django.shortcuts import render

from .models import Question
# ...
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})

Establishpolls/templates/polls/detail.html

{{ question }}

5. shortcut:A shortcut: get_object_or_404()

Override the detail method:

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

The reason for the model API to report http404 error instead of objectdoesnotexist exception is that if not, the coupling between the model layer and the view layer will occur.In other words, views.py should not care about model level things, but should only focus on how to show and what content to show. Whether the content you go to is the correct value or the error message should be the model or the controller’s business

Alikeget_list_or_404()The function, as before, uses filter () instead of get (). Error 404 returned when the retrieved list is empty

5. Use template system

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>

6. Remove the URL fixed code in the template

modifypolls/index.html

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

Because this is a tightly coupled approach (when you modify the URL of a project, you also need to change the template), you can use the template tag to remove the template’s dependence on a specific URL path, and change it to:

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

The advantage is that in the poll.urls module, the URL named ‘detail’ has been defined. According to this jump, if you want to change the point in the future, just change poll.urls, for example:

url(r'^specifics/(?P<question_id>[0-9]+)/$', views.detail, name='detail'),

7. Use URL name with namespace

If there are more than one in the projectappMore than one app hasdetail View, how to use template tags{% url %} template tag?

staypolls/urls.pyJoin inapp_name = 'polls'Become

from django.conf.urls import url

from . import views

app_name = 'polls'
urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
    url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
    url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]

modifypolls/templates/polls/index.html

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

In this way, Django knows how to generate dynamic hyperlink points, and only needs to modify the corresponding URL to modify the appapp/urls.py, there is no need to modify the template. Because templates often contain hyperlinks, this benefit is still great.