zoukankan      html  css  js  c++  java
  • django2.0基础

    一.安装与项目的创建

    1.安装

      pip install django

    2.查看版本

      python -m django --version

    3.创建项目

      django-admin startproject mysite    

        manage.py 实用的与django项目进行交互的命令行工具
        mysite 项目中的实际python包
        mysite/__init__.py 空文件,表示这是一个python包
        mysite/settings.py 此项目的配置文件
        mysite/urls.py url声明文件
        mysite/wsgi.py wsgi服务器的配置文件

    4.启动开发模式下的服务器

      python manage.py runserver 0.0.0.0:8000

        浏览器访问:http://127.0.0.1:8000/

    5.创建应用

      在manage.py的同级目录下执行:

        python manage.py startapp molin

    6.第一个视图文件

    polls/views.py

    #_*_coding:utf8_*_
    from django.shortcuts import HttpResponse
    def index(request):
        return HttpResponse("你好,欢迎来到投票系统的主页")

    7.配置URL

      新增polls/urls.py文件

    #_*_coding:utf8_*_
    from django.urls import path
    from . import views
    urlpatterns = [
        path('', views.index, name='index'),
    ]

    8.将polls/urls.py引入到mysite/urls.py文件中, 因为所有的url配置入口都是源于mysite/urls.py

      mysite/urls.py

    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path('polls/', include('polls.urls')),
        path('admin/', admin.site.urls),
    ]
    当浏览器访问 http://127.0.0.1:8000/polls/ 时,匹配到url规则path('polls/', include('polls.urls')), 然后读到polls/urls.py的配置:path('', views.index, name='index'), 从而去执行polls/views.py的index方法

    二.模型与数据库的交互

    1.数据库的设置

      打开mysite/settings.py,可看到默认情况下,django使用的是sqlite3数据库
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }

    有些应用要求我们必须至少要有一个数据库,如,django的后台,因此,让我们先来执行以下命令: $ python manage.py migrate

      将django激活的应用所需的数据表创建好

    2.创建模型

      polls/models.py

    #_*_coding:utf8_*_
    
    from django.db import models
    
    class Question(models.Model):
        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)

    类中的每个属性映射为一个字段,并标识了这些字段的类型

    3.激活模型

      mysite/settings.py

    INSTALLED_APPS = [
        'polls.apps.PollsConfig',
        # ...
    ]

    4.生成迁移

      $ python manage.py makemigrations polls

      自动生成了polls/migrations/0001_initial.py文件,现在还没有真正创建数据表,需要再执行数据迁移才能生成数据表

      执行迁移:$ python manage.py migrate

    5.让django的命令行交互更友好

      polls/models.py

    from django.db import models
    
    class Question(models.Model):
        # ...
        def __str__(self):
            return self.question_text
    
    class Choice(models.Model):
        # ...
        def __str__(self):
            return self.choice_text

    __str__()函数将会返回我们定义好的数据格式。此外,我们还可以在models中添加自定义方法:

    import datetime
    
    from django.db import models
    from django.utils import timezone
    
    
    class Question(models.Model):
        # ...
        def was_published_recently(self):
            return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

    6.进入交互模式对数据库进行操作

      $ python manage.py shell

    In [1]: from polls.models import Question, Choice
    
    In [2]: Question.objects.all() # 获取所有问题
    Out[2]: <QuerySet [<Question: 问题2>]>
    
    In [3]: Question.objects.filter(id=1) # 获取id为1的数据
    Out[3]: <QuerySet [<Question: 问题2>]>
    
    In [8]: Question.objects.filter(question_text__startswith='问题') # 获取内容包含'问题'的数据
    Out[8]: <QuerySet [<Question: 问题2>]>
    
    In [9]: from django.utils import timezone
    
    In [10]: current_year = timezone.now().year
    
    In [11]: Question.objects.get(pub_date__year=current_year)
    Out[11]: <Question: 问题2>
    
    In [12]: Question.objects.get(id=2) # 当获取的数据不存在时,会报以下错误
    ---------------------------------------------------------------------------
    DoesNotExist                              Traceback (most recent call last)
    <ipython-input-12-75091ca84516> in <module>()
    ----> 1 Question.objects.get(id=2)
    
    
    In [13]: Question.objects.get(pk=1)
    Out[13]: <Question: 问题2>
    
    In [14]: q = Question.objects.get(pk=1)
    
    In [15]: q.was_published_recently() # 调用自定义的方法
    Out[15]: True
    
    In [16]: q = Question.objects.get(pk=1)
    
    In [17]: q.choice_set.all()
    Out[17]: <QuerySet []>
    In [19]: q.choice_set.create(choice_text='选项1', votes=0)
    Out[19]: <Choice: 选项1>
    
    In [20]: q.choice_set.create(choice_text='选项2', votes=0)
    Out[20]: <Choice: 选项2>
    
    In [21]: c = q.choice_set.create(choice_text='选项3', votes=0)
    
    In [22]: c.question
    Out[22]: <Question: 问题2>
    
    In [23]: q.choice_set.all()
    Out[23]: <QuerySet [<Choice: 选项1>, <Choice: 选项2>, <Choice: 选项3>]>
    
    In [24]: q.choice_set.count()
    Out[24]: 3
    In [25]: Choice.objects.filter(question__pub_date__year=current_year)
    Out[25]: <QuerySet [<Choice: 选项1>, <Choice: 选项2>, <Choice: 选项3>]>
    
    In [26]: c = q.choice_set.filter(choice_text__startswith='选项3')
    
    In [27]: c.delete()
    Out[27]: <bound method QuerySet.delete of <QuerySet [<Choice: 选项3>]>>
    
    In [29]: Choice.objects.filter(question__pub_date__year=current_year)
    Out[29]: <QuerySet [<Choice: 选项1>, <Choice: 选项2>]>
    

    7.创建后台管理员   

    django自带了一个管理后台,我们只需创建一个管理员用户即可使用
    创建一个后台管理员用户: $ python manage.py createsuperuser

    8.引入模型

      polls/admin.py

    #_*_coding:utf8_*_
    from django.contrib import admin
    from .models import Question
    admin.site.register(Question)

    登陆后台可以对模型进行操作

    三.视图views和模板template的操作

    1.django的视图用于处理url请求,并将响应的数据传递到模板,最终浏览器将模板数据进行渲染显示,用户就得到了想要的结果

      增加视图:polls/views.py

    #_*_coding:utf8_*_
    from django.shortcuts import HttpResponse
    def index(request):
        return HttpResponse("你好,欢迎来到投票系统的主页")
    
    def detail(request, question_id):
        return HttpResponse('你正在查看问题%s' % question_id)
    
    def results(request, question_id):
        response = '你正在查看问题%s的结果'
        return HttpResponse(response % question_id)
    
    def vote(request, question_id):
        return HttpResponse('你正在给问题%s投票' % question_id)

      配置url:polls/urls.py

    #_*_coding:utf8_*_
    from django.urls import path
    from . import views
    urlpatterns = [
        # /polls/
        path('', views.index, name='index'),
        # /polls/1/
        path('<int:question_id>/', views.detail, name='detail'),
        # /polls/1/results/
        path('<int:question_id>/results/', views.results, name='results'),
        # /polls/1/vote/
        path('<int:question_id>/vote/', views.vote, name='vote'),
    ]

    2.通过视图直接返回的数据,显示格式很单一,要想显示丰富的数据形式,就需要引用模板,用独立的模板文件来呈现内容。

       新增模板: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>问题为空</p>
    {% endif %}

      修改视图: polls/views.py 传递变量给模板

    #_*_coding:utf8_*_
    from django.shortcuts 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))

    开发中,直接使用render()即可,尽可能精简代码

    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)

    详情页的展示:polls/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('问题不存在')
        return render(request, 'polls/detail.html', {'question': question})

    404页面抛出的便捷写法:get_object_or_404()

    polls/views.py

    from django.shortcuts import render, get_object_or_404
    from .models import Question
    # ...
    def detail(request, question_id):
        question = get_object_or_404(Question, pk=question_id)
        return render(request, 'polls/detail.html', {'question': question})

    详情页输出关联数据表:

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

    3.优化

      去掉url的硬编码格式

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

      修改url配置 

      将polls/urls.py的详情页url由:path('<int:question_id>/', views.detail, name='detail')改为:
        path('specifics/<int:question_id>/', views.detail, name='detail')

        此时,index.html的url会自动由 http://127.0.0.1:8000/polls/1/ 转为 http://127.0.0.1:8000/polls/specifics/1/

    4.一个项目中多个应用的区分需要使用命名空间

    #_*_coding:utf8_*_
    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'),
    ]

    将index.html的url生成代码加上命名空间:

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

    四.在前台进行投票操作

    1.构建一个简单的表单提交页

      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 %}" method="post">
        {% csrf_token %}
        {% for choice in question.choice_set.all %}
        <input id="choice{{ forloop.counter }}" type="radio" name="choice" value="{{ choice.id }}">
        <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br />
        {% endfor %}
        <br />
        <input type="submit" name="" id="" value="投票" />
    </form>

    代码解析:

      form表单提交的url为{%url 'polls:vote' question.id %}, 即表示访问polls/views.py的vote方法,并携带问题id作为参数。

      将问题的相关选项遍历,以单选框显示

      form表单用post方式提交数据

    配置url: polls/urls.py

    path('<int:question_id>/vote/', views.vote, name='vote'),

    2.视图层处理提交结果

      polls/views.py

    from django.shortcuts import render, get_object_or_404
    from django.http import HttpResponse, HttpResponseRedirect
    from django.urls import reverse
    from .models import Question, Choice
    # ...
    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': "必须选择一个选项",
            })
        else:
            selected_choice.votes += 1
            selected_choice.save()
            return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

    代码解析:

    request.POST['choice']接收表单页面提交的数据

    将投票次数加1,并更新数据库

    3.显示投票结果

      polls/views.py

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

      results.html

    <h1>{{ question.question_text }}</h1>
    <ul>
    {% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }} -- {{choice.votes}}</li>
    {% endfor %}
    </ul>
    
    <a href="{% url 'polls:detail' question.id %}">再投一次?</a>

    4.优化url和view写法

      将主键id代替question_id
      polls/urls.py

    #_*_coding:utf8_*_
    from django.urls import path
    from . import views
    app_name = 'polls'
    urlpatterns = [
        path('', views.IndexView.as_view(), name='index'),
        path('<int:pk>/', views.DetailView.as_view(), name='detail'),
        path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
        path('<int:question_id>/vote/', views.vote, name='vote'),
    ]

    使用<pk>代替<question_id>会更加灵活,<pd>代表主键

    相应的视图也需要修改成另一种写法,vote方法保持原样,用于比较两种写法的不同

    polls/views.py

    #_*_coding:utf8_*_
    from django.shortcuts import render, get_object_or_404
    from django.http import HttpResponseRedirect
    from django.urls import reverse
    from django.views import generic 
    from .models import Question, Choice
    
    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):
        # ...

      

    
    
    
    
    
    
  • 相关阅读:
    shell变量解析
    visual studio code(vscode)使用
    linux虚拟机安装
    算法总结系列之八:复读机的故事散列表及其在.NET中的应用浅析(上集)
    对改善Dictionary时间性能的思考及一个线程安全的Dictionary实现
    算法总结系列之八:复读机的故事 散列表.NET应用的研究(下集)
    使用WiX打包你的应用程序之二向WiX脚本传递信息(属性)的几种方式
    当心Dictionary带来的一种隐式内存泄漏
    从DWG到XAML (II) DWFx格式解析及其和XPS的关系
    从DWG到XAML (I) 浅谈DWG历史,现状及方向
  • 原文地址:https://www.cnblogs.com/feiyumo/p/8377725.html
Copyright © 2011-2022 走看看