python_new
  • Introduction
  • First Chapter
  • 一、python基础
    • 1.1 常识
      • sys
    • 1.2 基础语法(1)
    • 1.2 基础语法(2)
    • 1.3 常见问题求解
    • 1.4 算法
  • 二、爬虫
    • urllib库(1)
      • urllib库(2)
    • requests模块(1)
      • requests模块(2)
    • 2.1 爬虫基础(3)HTTP原理
    • 2.1 爬虫基础(4)会话和Cookies
    • 2.1 爬虫基础(5)数据存储
      • Mysql存储
      • MongoDB存储
      • Redis存储
    • 2.3 正则表达式
    • 2.4 解析库lxml
      • BeautifulSoup
      • pyquery(1)
      • pyquery(2)
    • 2.5 selenium(1)
    • 2.5 seleium(2)
    • 2.6 Json
    • 2.7 scrapy
      • scrapy(2)
    • 2.9 异步加载
    • 2.6 Splash
  • ORM框架
    • SQLAlchemy
  • Django
    • 1、初阶(一)
    • 初学:投票教程(一)
    • 初学:投票教程(二)
    • 初学:投票教程(三)
    • 初学:投票教程(总结)
    • 模型(一)
    • 模型(二)
    • 视图(一)
    • 视图(二)
    • 模板(一)
    • django实际使用笔记
  • 面试题收集总结
    • 数据结构原理
    • 算法篇
      • 排序
    • 题目篇
  • python数据分析
    • 基础了解(一)
    • 基础了解(二)
    • 基础了解(三)
  • 多线程
  • 深度学习
    • 疑问
  • keras(一)
  • 神经网络
  • 图像识别
  • Docker
    • 一、基础了解
Powered by GitBook
On this page

Was this helpful?

  1. Django

初学:投票教程(二)

(二)

# project_name/urls.py
from django.urls import path
from django.contrib import admin
from app_name import views

urlpatterns = [path('app_name/', views.index), path('admin/', admin.site.urls)]

到底urlpatterns是如何分割访问的url的?其次path中的name可有可无吗?有什么作用?

在方式一中,是不是进行了两次url的分割匹配?

path详解

path(route, view, kwargs, name)
  • route:类似于正则表达式,用来匹配url中‘?’前的部分,也就是不包括get和post请求

  • view:当找到匹配的url后,会调用view并传入一个HttpRequest对象

  • kwargs:

  • name:为url取名,并可以在django任何地方任意地引用它

urlpatterns可能有多个path,每个path匹配一段url后可能会有一些返回值,这些返回值如何组合?还是说只能匹配其中的一个path,一旦匹配处理之后,就会形成结果?name的引用还是没有清楚的概念,不知道如何使用

settings.py文件

  • Application definition

  • Database

  • Internationalization+

python manage.py migrate

在使用应用(不论是默认还是新创)的时候,至少需要在数据库创建一张表,该命令只会创建在INSTALLED_APPS中声明的应用。

创建模型应该是开发web应用的第一步,也就是数据库结构设计和附加的其它元数据

# app_name/models.py
from django.db import models

class Table_name(models.Model):
    # field_name = data_type(limitation)
    string = models.CharField(max_length=200)
    number = models.IntegerField(default=0)
    date = models.DateField('Datetime')
class Table_name_2(models.Model):
    table_1 = models.ForeignKey(Table_name, on_delete=models.CASCADE)
    number = models.IntegerField(default=0)

据说Datetime是一个可选选项,所谓可选就是为变量添加一个人类友好的名字,那这个人类友好名到底在什么时候会被使用?是在web界面吗?这个外键中‘on_delete=models.CASCADE’是什么意思?(好像是一对一的关系,那其他类型如何表示?)

INSTALLED_APPS = ['app_name.apps.App_nameConfig',]

之前有提到过把app应用放进settings中INSTALLED_APPS的,但目前看到使用这一部分的也只有与数据库相关的,所以是否可以理解为不涉及数据库的时候,不放入该列表也可以?

python manage.py makemigrations app_name

这部分还未涉及到数据库的改变,而是把模型前后变化存储在“迁移”这种形式之中,当再次使用python manage.py migrate命令的时候,才会将这些未执行的迁移与数据库同步。

models.py文件,改变模型。 运行python manage.py makemigrations为模型的改变生成迁移文件。 运行python manage.py migrate来应用数据库迁移。

为什么要存在迁移?直接使用前面的命令,同步到数据不就可以吗?

Thereasonthatthereareseparatecommandstomakeandapplymigrationsisbecauseyou'llcommitmigrationstoyourversioncontrolsystemandshipthemwithyourapp;theynotonlymakeyourdevelopmenteasier,they'realsousablebyotherdevelopersandinproduction.

据说原因是为了版本开发系统,也就是方便开发,可是暂时还是不能理解。

如果我把models.py定义好,并且把app加入到settings.py中,但是没有做migrate的命令,直接开启运行服务,会报错吗?也即是说,在开启服务时,会不会自动同步数据库?

API,djangoshell

python manage.py shell

使用shell的优点还不清楚

>>> from app_name.models import Table_name, Table_name_2
>>> Table_name.objects.all()   # 查看已创建的Table_name
<QuerySet []>    # 当没有创建时,返回空列表
>>> from django.utils import timezone
>>> t0 = Table_name(string = 'Hello World', number = 1, date = timezone.now())
>>> t0.save()    # save到数据库
>>> t0.id
1
>>> t0.string
'Hello World'
>>> t0.number
1
>>> t0.string = 'Bye World'
>>> t0.save()

之前觉得没什么用,后来发现可以直接操作数据库,也就是说通过migrate,在数据库中建立了表和字段,然后使用shell可以手动添加数据到里面去,当然也可以查询数据库中的数据。可是,做这个应用不是要从别人的访问中得到数据吗?比如说这个投票应用,数据的来源应该是网上访问的人,所以也就是只能通过shell查看一下数据了吧?

# 优化类的显示
# app_name/models.py
from django.db import models

class Table_name(models.Model):
    ....
    def __str__(self):
        return self.string

django数据库管理:shell

此外也可以使用shell进行查询,基本上还是前面和数据库交互的内容

>>> from app_name.models import Table_name, Table_name_2
>>> from django.utils import timezone
>>> Table_name.objects.all()
>>> Table_name.objects.filter(field_name = field_value) # 得到符合条件的类的列表
>>> Table_name.objects.get(field_name = field_value)  # 得到特定的类,不存在时报错
>>> q = Table_name.objects.get(pk=1) # pk是primary key,主键
# 假设Table_name中的主键是Table_name_2的外键
>>> q.table_name_2_set.all()   # 所有table2中以q为外键的行
>>> q.table_name_2_set.create(field = field_value...)  # 可以通过外键来创建,这样不用设置外键
>>> q.table_name_2_set.count() # 还可以计算以q为外键的行的个数
>>> Choice.objects.filter(question__pub_date__year=current_year)
>>> Choice.objects.filter(question__pub_date__year=current_year)
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')

居然还可以这样操作?那这样来说choice中外键存储的就不是简单的question中的主键值,而是把整个question实例对象作为值

django数据库管理:管理界面

python manage.py createsuperuser
Username: adminEmail 
address: admin@example.com
Password: **********
Password (again): *********
Superuser created successfully.

如果在管理界面看到自己的应用,还要修改

# app_name/admin.py
from django.db import admin
from .models import Table_name

admin.site.register(Table_name)

这里的添加应用只是为了让管理人员在可视化的环境下工作吧?即便不进行这一步,是不是也可以完成整个web应用的正常运行呢?

进一步优化视图,视图包括两点:实现特定功能,模板,目前还不知道模板如何使用,视图往往对应不同的网页

在Django中,网页和其他内容都是从视图派生而来。

如果说视图指的是网页中对应操作的具体实现,我可以理解,但整个网页U又是如何制作的呢?(虽然已经涉及到前端了),另外前端和视图之前的数据和功能连接是如何实现的呢?

为了将URL和视图关联起来,Django使用了'URLconfs'来配置。URLconf将URL模式映射到视图。

此外还有URL调度器,有时间可以详细了解一下。

较复杂的视图

# app_name/views.py
from django.http import HttpResponse

# 查看问题的详细信息
def detail(request, question_id):
    return HttpResponse(f'you are looking for the detail of {question_id}')

# 查看投票结果
def results(request, question_id):
    return  HttpResponse(f'you are looking for the results of {question_id}')

# 实现投票
def vote(request, question_id):
    return HttpResponse(f'you are voting on {question_id}')
# app_name/urls.py
from django.url import path
from . import views

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')]

name到底什么用?

视图应该返回HttpResponse对象或者异常,那么如果我要返回一个pdf文件或者一个其他格式的数据,也要放在HTTPResponse对象之中吗?

# app_name/views.py
from django.http import HttpResponse
from .models import Question  # Field_name
from django.template import loader

def index(request):
    latest_question_list = Question.order_by('-pub_date')[:5]
    template = loader.get_template('app_name/index.html')
    context = {'latest_question_list': latest_question_list,}
    return HttpResponse(template.render(context, request))

这里明明是‘pub_date’,为什么前面要加‘-’

如果想要修改网页的样式,就要用到模板了

# app_name/templates/app_name/index.html
{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <li><a href="/app_name/{{question.id}}">{{question.question_text}}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No app_name are available.</p>
{% endif %}

虽然我们现在可以将模板文件直接放在polls/templates文件夹中(而不是再建立一个polls子文件夹),但是这样做不太好。Django将会选择第一个匹配的模板文件,如果你有一个模板文件正好和另一个应用中的某个模板文件重名,Django没有办法区分它们。我们需要帮助Django选择正确的模板,最简单的方法就是把他们放入各自的命名空间中,也就是把这些模板放入一个和自身应用重名的子文件夹里。

确实不能理解其中的意思,主要的问题在于在模板之下的app目录到底是如何起到区分不同模板的,如果是遍历,就会忽略文件名,如果不是,那它说也可以不用这个目录,那找不到目录不会导致报错吗?如何没有问题,很好奇是如何做到的?

另外,这个HTML!?真的看不懂!据说html的结构中可以运行、获取后台代码或值,可以写服务器端代码,但这也太奇怪了,必须了解细节。

还有对于Question类的使用,是否意味着所有程序都可以实现与数据库的互动,而不只是在shell或管理平台才可以?

在使用模板时,和之前的区别大概有三点:1)使用loader导入模板 2)将模板所需的变量或对象(上下文变量)存储在context中 3)编写html文件,其中会用很多`

`类的代码来动态输出网页,由于这几个操作经常使用,所以有了快捷render函数

# app_name/views.py
from django.shorcuts import render
from .models import Question

def detail(request):
    latest_question_list = Question.objects.order_by('-pb_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'app_name/detailhtml', context)

一个异常加一个html输出

# app_name/views.py
from django.http import Http404
from django.shorcuts 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, 'app_name/detail.html', {'question':question})
# app_name/templates/app_name/detail.html
{{question}}

好像也对,他是不是直接找到了内层的‘app_name/detail.html’呢?这样合理一些,之前说了为了避免不同应用html重名的问题,这里倒是可接受了,在templates文件夹里,假设有两个重名html文件,只需要‘app_name1/html’和‘appname2/html’就不出现重复的情况,但是问题还是为什么不同应用的重名文件会放在其中一个应用的templates文件夹里呢?模板文件夹又不是公共空间,而是在每个应用底下单独创建,为什么会有别的应用的html文件?

简化版get_object_or_404()

# app_name/views.py
from django.shorcuts import get_objects_or_404, render
from .models import Question

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

还有get_list_or_404(),只是get被换成了filter 这里关键其实是空是否合法,假如我要查到的结果允许为空,也就是那是正常的,这里的报错是不是就..其实也不应该这样讲,空可以从是否异常来判断,也就是说把这部分判断放到外面来做就是了,都一样。

完全版模板系统

# app_name/templates/app_name/detail.html
<h1>{{ question.question_context}} </h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

如果不学习模板语言的话,应该是不能熟练制作网页的,这也是学习django看不到的必要知识。

模板中的硬编码url 回想index.html,其中每个问题的链接的形式,被他们称为“硬编码和强耦合的链接”,一看到这样的名词,我都想抽自己一巴掌。。。 Ok,接下来,我们会看到url的name终于体现出它的作用了

# part code of app_name/index.html
<li><a href="% url 'detail' question.id %">{{question.question_text}}</a></li>

原本url的定义是

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

为了方便比较,原本是'/app_name/',那么datail代表的到底是那部分的url?奥,我知道了,它虽然匹配了一个整数,但是代表的url中并不包括整数那部分,而是整数前的部分

如果你想改变投票详情视图的 URL,比如想改成 polls/specifics/12/ ,你不>用在模板里修改任何东西(包括其它模板),只要在 polls/urls.py 里稍微修改>一下就行:

# added the word 'specifics'
path('specifics/<int:question_id>/', views.detail, name='detail'),

多个项目url名称重复问题

首先,在url文件中添加‘app_name='app_name'’,其次修改html文件中的url引用为{% url 'app_name:detail'}

Previous初学:投票教程(一)Next初学:投票教程(三)

Last updated 6 years ago

Was this helpful?

创建管理员账号,运行服务之后,通过类似""这样的网址访问管理界面

http://127.0.0.1:8000/admin/