Python 编程从入门到实践 第18章

                                   Django  (D不发音)学习入门

如果在一台计算机下,想开发多个不同的项目,需要用到同一个包的不同版本,如果还使用命令在同一个目录下安装或者更新,可能影响到其它项目,或新项目用到的包的版本与当前版本有冲突,这样会导致其它项目无法运行,因此,要使用虚拟环境,在不同的虚拟环境下,制作不同的项目,彼此互不干涉;

Django 只在虚拟环境激活的情况下才能使用;

一、首先是 安装虚拟环境包:

DOS终端下输入 pip install  --user virtualenv

linux 下         sudo apt-get install python-virtualenv

二、安装完虚拟环境后,建立虚拟环境:(虚拟环境名称 ll_env)

virtualenv ll_env

三、启动虚拟环境

Windows 下,ll_env\Scripts\activate

四、在虚拟环境中安装Django

pip install Django==2.11

五、创建项目

django-admin.py startproject learning_log (空格).  (结尾的点很重要)

建立了名为 learning_log 的项目;

六、数据库迁移(创建数据库)

python manage.py migrate (这里默认使用的是SQLite 数据库)

七、查看项目

python manage.py runserver

启动服务器

在电脑web网页输入

http:// localhost:8000/  #查看页面

18-1 课后习题

在dos 环境下输入 mkdir InstaBook  #创建文件夹

然后再输入  pip install --user virtualenv #安装虚拟环境包

输入  virtualenv env #创建虚拟环境,名称为env

输入 env\Scripts\activate  #激活虚拟环境

输入 pip install django==2.2  #安装django版本指定2.2

输入 django-admin.py startproject instabook . #建立项目instabook(这里不要忘记在 ‘.’ 前面有个空格,PS:这块其实挺坑

(若出现系统让升级Pip 版本,请输入 pip install --upgrade pip==20.2.2)

若pip 升级失效并丢失,在dos环境下进入虚拟环境目录,然后输入:

easy_install.exe pip

18.2 创建程序

python manage.py startapp learning_logs #创建应用程序 learning_logs

也有用下一个命令创建app的:

django-admin.py startapp learning_logs

以上两个命令都可以。

定义模型

在models.py这个文件中,定义一个类 Topic,代码如下:

from django.db import models    #导入模块Models

class Topic(models.Model):   #Topic是你的学习笔记的主题,这里以类的形式进行定义
    """A topic the user is learning about."""
    text = models.CharField(max_length=200)
    date_added = models.DateTimeField(auto_now_add=True) 

    def __str__(self):
        """Return a string representation of the model."""
        return self.text

这里面我们需要详细说明一下,以方便我们理解:

Model是你数据信息的唯一,确定的来源。它包含了基础字段(fields)和存储数据时的行为。总的来说,每一个Model都匹配一个数据表。

  • 每一个Model都是一个继承于django.db.models.Model的class
  • Model的每一个属性都代表着数据表中的一个字段
  • Django提供了一个自动生成的数据库访问的API,参见Making queries.

这里定义了一个类Topic,它继承了Model,而text与data_added 都是Topic的属性,因此可以理解为,其也是Model的属性;

这里text 是一个Charfield-由字符或文本组成的数据,它是model中的一个字段,需要存储少量文本,因此,必须在数据库中定义它的长度;

date_add是一个记录时间和日期的数据,实参auto_now_add=True ,表示每当用户创建新主题时,Django将自动将该日期作为当前日期和时间进行记录;

__str__函数主要作用就是告诉Django应该显示有关主题的信息。这里返回存储在属性text里面的信息。

这里面要引申一下Field的用法;

字段是模型当中最重要的部分,是数据库列表定义的模型唯一需要的部分;字段有类的属性进行定义,主要在命名字段的时候不要与模型API 接口名称相同,避免产生歧义;

Fieds的主要用法如下:

首先引入model模型,即:from django.db import models

字段(fields)

1、models.AutoField  自增列 = int(11)
  如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
2、models.CharField  字符串字段
  必须 max_length 参数, 即 models.CharField(max_length=200)
3、models.BooleanField  布尔类型=tinyint(1) ;不能为空,Blank=True
4、models.ComaSeparatedIntegerField  用逗号分割的数字=varchar;继承CharField,所以必须 max_lenght 参数
5、models.DateField  日期类型 date,对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
6、models.DateTimeField  日期类型 datetime
  同DateField的参数
7、models.Decimal  十进制小数类型 = decimal
  必须指定整数位max_digits和小数位decimal_places
8、models.EmailField  字符串类型(正则表达式邮箱) =varchar
  对字符串进行正则表达式
9、models.FloatField  浮点类型 = double
10、models.IntegerField  整形
11、models.BigIntegerField  长整形
  integer_field_ranges = {
    'SmallIntegerField': (-32768, 32767),
    'IntegerField': (-2147483648, 2147483647),
    'BigIntegerField': (-9223372036854775808, 9223372036854775807),
    'PositiveSmallIntegerField': (0, 32767),
    'PositiveIntegerField': (0, 2147483647),
  }
12、models.IPAddressField  字符串类型(ip4正则表达式)
13、models.GenericIPAddressField  字符串类型(ip4和ip6是可选的)
  参数protocol可以是:both、ipv4、ipv6
  验证时,会根据设置报错
14、models.NullBooleanField  允许为空的布尔类型
15、models.PositiveIntegerFiel  正Integer
16、models.PositiveSmallIntegerField  正smallInteger
17、models.SlugField  减号、下划线、字母、数字
18、models.SmallIntegerField  数字
  数据库中的字段有:tinyint、smallint、int、bigint
19、models.TextField  字符串=longtext
20、models.TimeField  时间 HH:MM[:ss[.uuuuuu]]
21、models.URLField  字符串,地址正则表达式
22、models.BinaryField  二进制
23、models.ImageField   图片
24、models.FilePathField 文件

参数

1、null=True
  数据库中字段是否可以为空
2、blank=True
  django的 Admin 中添加数据时是否可允许空值
3、primary_key = False
  主键,对AutoField设置主键后,就会代替原来的自增 id 列
4、auto_now 和 auto_now_add
  auto_now   自动创建---无论添加或修改,都是当前操作的时间
  auto_now_add  自动创建---永远是创建时的时间
5、choices

sex_choice=((“F”,“FEMAL”),(“M”,’Male’),)    #admin专用下拉选项        

gender=models.CharFiled(max_length=2,choice=sex_choice)

6、max_length
7、default  默认值
8、verbose_name  Admin中字段的显示名称
9、name|db_column  数据库中的字段名称
10、unique=True  不允许重复
11、db_index = True  数据库索引
12、editable=True  在Admin里是否可编辑
13、error_messages=None  错误提示
14、auto_created=False  自动创建
15、help_text  在Admin中提示帮助信息
16、validators=[]
17、upload-to

因为我们已经建立的应用,因此,必须在项目中将该应用进行添加,这里打开settings.py文件,在INSTALLED_APPS中添加该app的名字;

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    # My apps
    'learning_logs',
)

可以看出,INSTALLED_APPS是一个元组,这里面有很多的元素,料想其余元素若为app的话,应该是建立项目的时候自动生成的,这里我们不去管它;

因为我们已经建立了新的app应用,因此要为他迁移数据库,形成数据列表,这里需要在dos环境下,输入:

python manage.py makemigrations learning_logs # 创建更改文件,可以看见这时生成了迁移文件00001_initial.py,这个文件将在数据库中为模型Topic创建一个表;

python manage.py migrate #迁移刚才生成的表,将刚才生成.py文件应用到数据库;

每当我们要修改数据时,首先修改models.py , 然后调用makemigrations,形成迁移文件,最后,执行迁移动作,migrate!

18.2.3 Django管理网站;

创建超级用户:

python manage.py createsuperuser

这里有一种特殊情况,如果你忘记了之前创建的超级用户名或密码怎么办?

首先,在虚拟环境中进入shell模式,python manage.py shell 

然后输入以下代码,对原有密码重置:

from django.contrib.auth.models import User # 引入管理员密码存放的数据库;

user=User.objects.filter() #查找该数据库存有哪些用户

user   #查看有哪些用户

重置密码

user = User.objects.get(username='admin') #获取名称为admin的用户

user.set_password('123456') #设置新密码为123456

user.save() #保存user对象,完事儿了!

 

我们创建的模型必须手工注册,找到admin.py 文件,输入下列代码:

from django.contrib import admin

from learning_logs.models import Topic, Entry

admin.site.register(Topic)

注册了Topic模型!

18.2.4 定义模型Entry

这里定义一个Entry类,让Topic主题下包含多个条目,使之具备内容;

from django.db import models

class Topic(models.Model):
   --------snip-----------

class Entry(models.Model):
    """Something specific learned about a topic."""
    topic = models.ForeignKey(Topic)
    text = models.TextField()
    date_added = models.DateTimeField(auto_now_add=True)
    
    class Meta:
        verbose_name_plural = 'entries'
 
    def __str__(self):
        """Return a string representation of the model."""
        return self.text[:50] + "..."

topic是一个外键(foreign Key)实例,这里面涉及到数据了,外键引用数据库的一条记录;

 Meta 类的具体用法,请参考一下链接:

https://www.cnblogs.com/jasonhaven/p/7497322.html

verbose_name_plural='entries' 这个是指定模型的复数形式是什么,其实就是给你的模型起个名字,这个名字可以是中文,不过表达的是复数;

这里不要忘记,在定义完模型之后,要在数据库中给它分配一个位置,用来存储信息,这就要我们迁移数据库;

dos下输入 : python manage.py makemigrations learning_logs

python manage.py migrate

迁移数据库以后,要进行网站注册

from django.contrib import admin

from learning_logs.models import Topic, Entry

admin.site.register(Topic)
admin.site.register(Entry)

18.2.7 Django shell 的使用实例

这里不再赘述,直接把代码上了吧:

python manage.py shell  # 启动shell

from learning_logs.models import Topic  # 导入models模型,引入Topic类

Topic.objects.all()     #    获取模型Topic中的所有实例

topics = Topic.objects.all()  # 将所有实例导入到topics中,此时它是一个元组

for topic in topics:    #例遍所有元素

      print(topic.id, topic)   # 打印元素的id, 和元素内容

t = Topic.objects.get(id=1)

t.text

t.date_added

t.entry_set.all()

课后习题:

18-2 

 def __str__(self):
        """Return a string representation of the model."""

        if len(self.text)>50:
            return self.text[:50] + "..."
        else:
            return self.text

18-4 创建名为pizzeria的项目:

DOS下: python manage.py startproject pizzeria .  # 一定不要忘了空格后面的点哦!

创建应用:

django-admin.py startapp pizzas #创建app,名称为pizzas

还是在models.py 里面,定义Pizza模型,代码如下:

from django.db import models

# Create your models here.

class Pizza(models.Model):
    name=models.CharField(max_length=200)
    data_added=models.DateTimeField(auto_now_add=True)

    def __str__(self):
        # """返回木星字符串表示"""
        return self.name

class Topping(models.Model):
    pizza=models.ForeignKey(Pizza,on_delete=models.CASCADE)
    name=models.TextField()
    date_add=models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name_plural='entries'

    def __str__(self):
        return  self.name[:50]+'...'

 

18.3创建网页:学习笔记主页

创建网页三步骤:一、定义URL(链接);二、编写视图(view);三、编写模板(templates)

打开learning_log主文件夹下的urls.py ,输入以下代码:(书中代码是基于django1.0的,2.0版本往上请输入以下代码:)

from django.contrib import admin
from django.urls import path, include
from django.conf.urls import url


urlpatterns = [
    path('admin/', admin.site.urls),# 这个是课程后面代码,定义的管理员页面链接
    path('',include('learning_logs.urls',namespace='learning_logs')), #这里面有个include,从中我们可以看出,需要在learning_logs文件夹中新建一个urls.py文件,来与learning_log文件夹下的urls相呼应;
    path('users/',include('users.urls',namespace='users')),# 这个也是后面课程代码,定义使用者页面链接
]
app_name = 'learning_logs'

在learning_logs文件夹下新建一个urls.py文件,代码如下:(书中代码还是老版本的)

from django.urls import path,include
from . import views


app_name = 'learning_logs'

urlpatterns =[#主页
    path('',views.index, name='index'),
    #显示所有主题
    path('topics/',views.topics,name='topics'),  #显示所有主题页
    #特定主题的详细页面
    path("topics/(?p<topic_id>\d+)/",views.topic, name='topic'), #特定主题的详细页面
    # 用于添加新主题网页
    path("new_topic/",views.new_topic,name='new_topic'),
    # 用于添加新条目
    path("new_entry/(?p<topic_id>\d+)/", views.new_entry,name='new_entry'),
    # 编辑条目
    path("edit_entry/(?p<entry_id>\d+))",views.edit_entry, name='edit_entry'),

    
]

由上面的代码,我们可以看到,里面应用了正则表达式,正则表达式是几乎所有语言都会用到的,大家后续找资料好好学习吧!

简单举一个例子说一下吧:

 path('',views.index, name='index') #主页下的网页,path 后面什么也没有,就表示主页,views.index 是指要调用的视图函数,由此可知,需要在views.py 内建立index函数,以供调用!name='index' 是将这个URL的名称命名为index,每当要调用这个页面的时候,我们直接提供这个名称就可以了,不用提供URL地址!

URL定义完了,现在我们要开始定义视图函数了views.py

打开views.py文件,输入以下代码:

from django.shortcuts import render


# Create your views here.

def index(request):
    return render(request,'learning_logs/index.html')

解释一下 render(request,'learning_logs/index.html')

首先是render()的使用:

render(request, template_name, context=None, content_type=None, status=None, using=None)

Returns a HttpResponse whose content is filled with the result of calling django.template.loader.render_to_string() with the passed

request: 收到的请求

template_name: templates 中网页模板. 比如’templates\learn\index.html’, 参数就要写‘learn\index.html’

context: 要传入文件中用于渲染呈现的数据, 默认是字典格式

content_type: 生成的文档要使用的MIME 类型。默认为DEFAULT_CONTENT_TYPE 设置的值。

status: http的响应代码,默认是200.

using: 用于加载模板使用的模板引擎的名称。

常见的MIME类型(通用型): 
超文本标记语言文本 .html text/html 
xml文档 .xml text/xml 
XHTML文档 .xhtml application/xhtml+xml 
普通文本 .txt text/plain 
RTF文本 .rtf application/rtf 
PDF文档 .pdf application/pdf 
Microsoft Word文件 .word application/msword 
PNG图像 .png image/png 
GIF图形 .gif image/gif 
JPEG图形 .jpeg,.jpg image/jpeg 
au声音文件 .au audio/basic 
MIDI音乐文件 mid,.midi audio/midi,audio/x-midi 
RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio 
MPEG文件 .mpg,.mpeg video/mpeg 
AVI文件 .avi video/x-msvideo 
GZIP文件 .gz application/x-gzip 
TAR文件 .tar application/x-tar 
任意的二进制数据 application/octet-stream

由以上可知,render就是URL匹配后,响应网页请求而做的反应,这里顾名思义,request就是请求,然后,反馈这个‘learning_logs/index.html’ 模板;

此时,我们要定义Index.html了,对于html 我们又要仔细学习了:

HTML称为超文本标记语言,是一种标识性的语言。

HTML基础,可以参考以下链接:

https://www.runoob.com/html/html-tutorial.html

下面编辑index.html模板,输入以下代码:

 <p>Learning Log helps you keep track of your learning, for any topic you're 
  learning about.</p>

标签<p>代表段落,这里需要补一下基础HTML

课后习题18-5

在dos 环境下输入 mkdir meal_planner

进入该文件夹,输入 django-admin.py startproject food

进入meal_planner文件夹,然后输入 django-admin.py startapp meal_plans

首先在setting.py 文件中,输入app的名字,代码如下:

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = ')kt84#hb3cgv5)=h&ln!&pyg^szfh3#9jt+-hv@j3(_zg20pe3'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'meal_plans',
]

然后在models.py 文件中,输入以下代码:

from django.db import models

class food(models.Model):
    name=models.CharField(max_length=200)
    date_added=models.DateTimeField(auto_now_add=True)

    def __str__(self):

        return self.text

在vies.py 文件中输入以下代码:

from django.shortcuts import render

def index(request):

    return render(request,'index.html')

在所建项目的urls.py 文件中,输入以下代码:(我建的项目是food)

from django.contrib import admin
from django.urls import path
from meal_plans import views

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

最后,进行注册,在admin.py中输入:

from django.contrib import admin

from meal_plans.models import food

admin.site.register(food)

这里忘记添加模板了,在meal_plans文件夹下简历模板文件夹templates,然后在该文件夹下建立index.html 文件,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>food</title>
</head>
<body>
<p> Welcome to my resturant</p>

</body>
</html>

18.4 创建其它网页

18.4.1 模板继承,这里没啥可说的,base.html直接贴代码:

<p>
  <a href="{% url 'learning_logs:index' %}">Learning Log</a> -
  <a href="{% url 'learning_logs:topics' %}">Topics</a>
</p>

{% block content %}{% endblock %}

这里面基础也是html,将index及topics的链接贴里面,然后显示是Learning Log 和 Topics,这个代码里面体现了django的优越性,他直接找到了index的名称,这里边与url.py 中代码:path('',views.index,name='index'), 这里边name直接命名了!

上面母模板定义完了,该定义子模板了,index.html代码改为:

{% extends "learning_logs/base.html" %}

{% block content %}
  <p>Learning Log helps you keep track of your learning, for any topic you're 
  learning about.</p>
{% endblock content %}

learning_logs/urls.py 代码:

from django.urls import path,include
from . import views
# from django.conf.urls import url

app_name = 'learning_logs'

urlpatterns =[#主页
    path('',views.index, name='index'),
    #显示所有主题
    path('topics/',views.topics,name='topics'),
]

vies.py 代码

from django.shortcuts import render

from .models import Topic

def index(request):
    """The home page for Learning Log."""
    return render(request, 'learning_logs/index.html')

def topics(request):
    """Show all topics."""
    topics = Topic.objects.order_by('date_added')
    context = {'topics': topics}
    return render(request, 'learning_logs/topics.html', context)

topics.html代码

{% extends "learning_logs/base.html" %}

{% block content %}

  <p>Topics</p>

  <ul>
    {% for topic in topics %}
      <li>
        <a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
	  </li>
    {% empty %}
      <li>No topics have been added yet.</li>
    {% endfor %}
  </ul>

{% endblock content %}

learning_logs/urls.py代码:

from django.urls import path,include
from . import views
# from django.conf.urls import url

app_name = 'learning_logs'

urlpatterns =[#主页
    path('',views.index, name='index'),
    #显示所有主题
    path('topics/',views.topics,name='topics'),
    #特定主题的详细页面
    path("topics/(?p<topic_id>\d+)/",views.topic, name='topic'),]

views.py代码:

from django.shortcuts import render

from .models import Topic

def index(request):
    """The home page for Learning Log."""
    return render(request, 'learning_logs/index.html')

def topics(request):
    """Show all topics."""
    topics = Topic.objects.order_by('date_added')
    context = {'topics': topics}
    return render(request, 'learning_logs/topics.html', context)

def topic(request, topic_id):
    """Show a single topic, and all its entries."""
    topic = Topic.objects.get(id=topic_id)
    entries = topic.entry_set.order_by('-date_added')
    context = {'topic': topic, 'entries': entries}
    return render(request, 'learning_logs/topic.html', context)

这段代码定义的topic段涉及到数据库知识了,补基础请参考以下链接:

http://www.manongjc.com/sqlite/sqlite_syntax.html

所以大家看到了,一个django带大家入了好多坑,截止目前,涉及到前端的有html,JavaScript,涉及到后端的sqlite, mysql。继续挑战!

模板topics.html

{% extends "learning_logs/base.html" %}

{% block content %}

  <p>Topics</p>

  <ul>
    {% for topic in topics %}
      <li>
        <a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
	  </li>
    {% empty %}
      <li>No topics have been added yet.</li>
    {% endfor %}
  </ul>

{% endblock content %}

 

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值