• Django Web开发入门基础


    官方有很详细的文档,但是看过几遍之后如果要翻找还是有点麻烦,本文算作是学习笔记,提取一些关键点记录下来,另附上官方教程 编写你的第一个 Django 应用

    注: 文中的指令使用py,是在Windows上,macOS要使用 python3

     1. 安装Django

    Django 是一个基于 Python 的Web开发框架,安装前可以用下面的命令检查是否安装了 Django,如果已经安装,会显示版本,没有安装会提示没有该模块

    py -m django --version

    如果没有安装,可以使用下面的命令安装

    py -m pip install Django

    2. 创建项目

    项目就是一个 project,一个项目可以包含多个 app,也可以理解为多个模块,创建项目使用如下命令,其中 mysite 是项目名称:

    django-admin startproject mysite

    在令窗口中,切到刚刚创建的项目的根目录(有 manage.py),在项目中创建一个app,名字就叫 polls

    py manage.py startapp polls

     然后修改几个文件

    polls/views.py

    1. from django.http import HttpResponse
    2. def index(request):
    3. return HttpResponse("Hello World!")

    polls/urls.py

    1. from django.urls import path
    2. from . import views
    3. urlpatterns = [
    4. path("", views.index, name="index"),
    5. ]

    mysite/urls.py

    1. from django.contrib import admin
    2. from django.urls import include, path
    3. urlpatterns = [
    4. path("polls/", include("polls.urls")),
    5. path("admin/", admin.site.urls),
    6. ]

     最后启动服务,浏览器访问 http://localhost:8000/polls/

    py manage.py runserver

    3. 配置语言和时区 

    项目配置在 mysite/settings.py

    语言标识可以在这里查找 Language Identifiers (RFC 3066)

    1. # 语言设置为中文
    2. LANGUAGE_CODE = 'zh-Hans'

    时区标识可以在这里查找 List of tz database time zones 

    1. # 时区设置为北京时间
    2. TIME_ZONE = 'Asia/Shanghai'

    4. 数据库

    就使用自带的 SQLite 吧,方便又简单,如果开发商用的Web App,建议使用其他数据库,要进行额外的配置。

    (1)创建数据模型

    修改 polls/models.py

    1. import datetime
    2. from django.db import models
    3. from django.utils import timezone
    4. class Question(models.Model):
    5. question_text = models.CharField(max_length=200)
    6. pub_date = models.DateTimeField("date published")
    7. def __str__(self):
    8. return self.question_text
    9. def was_published_recently(self):
    10. return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
    11. class Choice(models.Model):
    12. # Choice属于一个Question
    13. question = models.ForeignKey(Question, on_delete=models.CASCADE)
    14. choice_text = models.CharField(max_length=200)
    15. votes = models.IntegerField(default=0)
    16. def __str__(self):
    17. return self.choice_text

    (2)激活模型

    修改 mysite/settings.py,在 INSTALLED_APP 中添加 polls.apps.PollsConfig

    1. INSTALLED_APPS = [
    2. "polls.apps.PollsConfig",
    3. "django.contrib.admin",
    4. "django.contrib.auth",
    5. "django.contrib.contenttypes",
    6. "django.contrib.sessions",
    7. "django.contrib.messages",
    8. "django.contrib.staticfiles",
    9. ]

    (3)创建数据迁移(尚未提交)

    py manage.py makemigrations polls

    查看创建的迁移使用的SQL语句,下面命令中的 0001 是上面创建迁移时生成的 polls/migrations/0001_initial.py 文件名中的数字

    py manage.py sqlmigrate polls 0001

    (4)提交迁移

    py manage.py migrate

    总结起来就三步:修改模型 -> 创建迁移 -> 提交迁移

     (5)玩转数据库API

    打开交互式窗口

    py manage.py shell
    >>> from polls.models import Choice, Question
    >>> Question.objects.all()
    
    >>> from django.utils import timezone
    >>> q = Question(question_text="What's new?", pub_date=timezone.now())
    >>> q.save()
    >>> q.id
    1
    >>> q.question_text
    "What's new?"
    >>> q.pub_date
    datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=datetime.timezone.utc)
    >>> q.question_text = "What's up?"
    >>> q.save()
    >>> Question.objects.all()
    ]>
    
    >>> from polls.models import Choice, Question
    >>> Question.objects.all()
    ]>
    >>> Question.objects.filter(id=1)
    ]>
    >>> Question.objects.filter(question_text__startswith="What")
    ]>
    >>> from django.utils import timezone
    >>> current_year = timezone.now().year
    >>> Question.objects.get(pub_date__year=current_year)
    
    >>> Question.objects.get(id=2)
    Traceback (most recent call last):
        ...
    DoesNotExist: Question matching query does not exist.
    >>> Question.objects.get(pk=1)
    
    >>> q = Question.objects.get(pk=1)
    >>> q.was_published_recently()
    True
    >>> q = Question.objects.get(pk=1)
    >>> q.choice_set.all()
    
    >>> q.choice_set.create(choice_text="Not much", votes=0)
    
    >>> q.choice_set.create(choice_text="The sky", votes=0)
    
    >>> c = q.choice_set.create(choice_text="Just hacking again", votes=0)
    >>> c.question
    
    
    >>> q.choice_set.all()
    , , ]>
    >>> q.choice_set.count()
    3
    >>> Choice.objects.filter(question__pub_date__year=current_year)
    , , ]>
    >>> c = q.choice_set.filter(choice_text__startswith="Just hacking")
    >>> c.delete()

    5. 创建管理员

     输入下面的命令,然后根据提示设置账户名,邮箱,密码

    py manage.py createsuperuser

    启动服务,浏览器访问 http://127.0.0.1:8000/admin/

    py manage.py runserver

    修改 polls/admin.py 让管理员可管理数据

    1. from django.contrib import admin
    2. from .models import Question
    3. admin.site.register(Question)

    管理员登录后

    6. 使用 html 模板

    (1)创建 HTML 文件

    在 polls/ 目录下新建一个 templates 文件夹,在 polls\templates\ 目录下新建一个 polls 文件见,如果新建一个 HTML 文件,比如 index.html,其最终的路径为 mysite\polls\templates\polls\index.html,代码中将使用 polls\index.html

    polls\templates\polls\index.html

    1. {% if latest_question_list %}
    2. <ul>
    3. {% for question in latest_question_list %}
    4. <li><a href="{% url 'index' question.id %}">{{ question.question_text }}a>li>
    5. {% endfor %}
    6. ul>
    7. {% else %}
    8. <p>No polls are available.p>
    9. {% endif %}

     polls\templates\polls\detail.html

    1. <h1>{{ question.question_text }}h1>
    2. <ul>
    3. {% for choice in question.choice_set.all %}
    4. <li>{{ choice.choice_text }}li>
    5. {% endfor %}
    6. ul>

    (2)配置 view

    修改 polls/views.py

    1. from django.http import HttpResponse
    2. from django.shortcuts import render, get_object_or_404
    3. from .models import Question
    4. def index(request):
    5. latest_question_list = Question.objects.order_by("-pub_date")[:5]
    6. context = {"latest_question_list": latest_question_list}
    7. return render(request, "polls/index.html", context)
    8. def detail(request, question_id):
    9. question = get_object_or_404(Question, pk=question_id)
    10. context = {"question": question}
    11. return render(request, "polls/detail.html", context)
    12. def results(request, question_id):
    13. return HttpResponse("Results")
    14. def vote(request, question_id):
    15. return HttpResponse("Vote")

    (3)配置 url

    修改 polls/urls.py

    1. from django.urls import path
    2. from . import views
    3. urlpatterns = [
    4. # ex: /polls/
    5. path("", views.index, name="index"),
    6. # ex: /polls/5/
    7. path("/", views.detail, name="detail"),
    8. # ex: /polls/5/results/
    9. path("/results/", views.results, name="results"),
    10. # ex: /polls/5/vote/
    11. path("/vote/", views.vote, name="vote"),
    12. ]

    (4)URL命名空间

    当项目存在多个应用时,可能需要借助命名空间来确定url,在应用的 urls.py 中配置 app_name

    1. from django.urls import path
    2. from . import views
    3. app_name = "polls"
    4. urlpatterns = [
    5. # ex: /polls/
    6. path("", views.index, name="index"),
    7. # ex: /polls/5/
    8. path("/", views.detail, name="detail"),
    9. # ex: /polls/5/results/
    10. path("/results/", views.results, name="results"),
    11. # ex: /polls/5/vote/
    12. path("/vote/", views.vote, name="vote"),
    13. ]

    index.html 中添加 app_name:

    1. {% if latest_question_list %}
    2. <ul>
    3. {% for question in latest_question_list %}
    4. <li><a href="{% url 'polls:index' question.id %}">{{ question.question_text }}a>li>
    5. {% endfor %}
    6. ul>
    7. {% else %}
    8. <p>No polls are available.p>
    9. {% endif %}

    (5)创建表单

     修改 detail.html

    1. <form action="{% url 'polls:vote' question.id %}" method="post">
    2. {% csrf_token %}
    3. <fieldset>
    4. <legend><h1>{{ question.question_text }}h1>legend>
    5. {% if error_message %}<p><strong>{{ error_message }}strong>p>{% endif %}
    6. {% for choice in question.choice_set.all %}
    7. <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
    8. <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}label><br>
    9. {% endfor %}
    10. fieldset>
    11. <input type="submit" value="Vote">
    12. form>

    表单中涉及投票页面和投票结果页面,得新增一个 results.html,并修改 views.py

    results.html

    1. <h1>{{ question.question_text }}h1>
    2. <ul>
    3. {% for choice in question.choice_set.all %}
    4. <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}li>
    5. {% endfor %}
    6. ul>
    7. <a href="{% url 'polls:detail' question.id %}">Vote again?a>

    views.py 中修改 results 和 vote 方法

    1. from django.http import HttpResponse, HttpResponseRedirect
    2. from django.shortcuts import render, get_object_or_404
    3. from django.urls import reverse
    4. from .models import Question, Choice
    5. def index(request):
    6. latest_question_list = Question.objects.order_by("-pub_date")[:5]
    7. context = {"latest_question_list": latest_question_list}
    8. return render(request, "polls/index.html", context)
    9. def detail(request, question_id):
    10. question = get_object_or_404(Question, pk=question_id)
    11. context = {"question": question}
    12. return render(request, "polls/detail.html", context)
    13. def results(request, question_id):
    14. question = get_object_or_404(Question, pk=question_id)
    15. return render(request, "polls/results.html", {"question": question})
    16. def vote(request, question_id):
    17. question = get_object_or_404(Question, pk=question_id)
    18. try:
    19. selected_choice = question.choice_set.get(pk=request.POST["choice"])
    20. except (KeyError, Choice.DoesNotExist):
    21. return render(
    22. request,
    23. "polls/detail.html",
    24. {
    25. "question": question,
    26. "error_message": "You didn't select a choice."
    27. },
    28. )
    29. else:
    30. selected_choice.votes += 1
    31. selected_choice.save()
    32. return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))

    7. 编写测试用例 

    首先得有个bug,巧了,我们的 polls 应用现在就有一个小 bug 需要被修复:我们的要求是如果 Question 是在一天之内发布的, Question.was_published_recently() 方法将会返回 True ,然而现在这个方法在 Question 的 pub_date 字段比当前时间还晚时也会返回 True(这是个 Bug)。

     在 polls\tests.py 中编写测试代码

    1. import datetime
    2. from django.test import TestCase
    3. from django.utils import timezone
    4. from .models import Question
    5. class QuestionModelTests(TestCase):
    6. def test_was_published_recently_with_future_question(self):
    7. """
    8. 检测异常:发布时间比当前时间还要晚
    9. """
    10. time = timezone.now() + datetime.timedelta(days=30)
    11. future_question = Question(pub_date=time)
    12. self.assertIs(future_question.was_published_recently(), False)

    运行测试(指令是在项目跟目录执行的,该目录有 manage.py)

    py manage.py test polls
    • py manage.py test polls 将会寻找 polls 应用里的测试代码
    • 查找 django.test.TestCase 子类
    • 创建一个特殊的数据库供测试使用
    • 在类中寻找测试方法——以 test 开头的方法。
  • 相关阅读:
    史上超级详细:银行外包java面试题目
    网络时钟程序Net_Clock
    Monkey命令
    Unity实现设计模式——状态模式
    数字货币--暗池
    opengl 学习(三)-----着色器
    FFmpeg开发简介1
    软件确认测试有什么作用?确认测试报告的价格是多少?
    Sora:AI视频模型的无限可能与挑战
    正确理解redux Toolkits中createSlice的action.payload
  • 原文地址:https://blog.csdn.net/jjf19891208/article/details/133122951