django学习实践简单示例超详细版本

通过一个简单的django项目的学习和实践,来加深对django的理解。

安装和创建

安装django

pip install django

创建项目

django-admin startproject learning_log .

这个命令末尾的句点让新项目使用合适的目录结构,这样开发完成后可轻松地将应用程序部署到服务器
千万别忘了这个句点,否则部署应用程序时将遭遇一些配置问题。如果忘记了这个句点,要删除已创建的文件和文件夹(虚拟环境venv文件夹除外),再重新运行这个命令
绿色文件是执行命令之后生成的文件
在这里插入图片描述
settings.py指定Django如何与系统交互以及如何管理项目。在开发项目的过程中,我们将修改其中一些设置,并添加一些设置。
urls.py告诉Django,应创建哪些页面来响应浏览器请求。
wsgi.py帮助Django提供它创建的文件,这个文件名是Web服务器网关接口(Web server gateway interface)的首字母缩写。

创建数据库

python manage.py migrate

执行结果
在这里插入图片描述
执行后会生成一个db.sqlite3

启动查看项目

此时项目已经生成,启动项目

python manage.py runserver

Development server已经启动在本地的8000端口,如果想关闭使用Ctrl+C
浏览器访问效果
在这里插入图片描述

创建应用程序

python manage.py startapp learning_logs

红色文件是执行命令之后生成的文件
在这里插入图片描述

编写实体模型models

最初的models.py文件
在这里插入图片描述
开始编写我们需要的实体
参考文档:https://docs.djangoproject.com/zh-hans/5.0/ref/models/fields/

classTopic(models.Model):#继承Model,即Django中定义了模型基本功能的类
"""用户学习主题"""
text=models.CharField(max_length=200)#由字符组成的数据,即文本
date_added=models.DateTimeField(auto_now=True)#日期和时间的数据,参数属性表示自动设置当前日期和时间

def__str__(self):
"""返回模型的字符串表示"""
returnself.text#告诉Django,默认使用哪个属性来显示有关主题的信息

激活模型

让Django将上面我们写的应用程序包含到项目中,settings.py中的INSTALLED_APPS片段就是这个作用。

添加我们的应用程序

INSTALLED_APPS=[
#我自己的应用程序
'learning_logs'
#默认添加的应用程序
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]

迁移数据库

因为我们修改了models,所以为了同步到数据库,需要迁移

 python manage.py makemigrations learning_logs

第一次报了一个错误:ModuleNotFoundError: No module named ‘learning_logsdjango’
原因是因为我忘记了写逗号
在这里插入图片描述

修改后执行结果,会在migrations目录下新建一个0001_initial.py迁移文件
在这里插入图片描述
在这里插入图片描述
然后应用这个迁移

 python manage.py migrate

总结,每次修改数据模型的时候都要执行三个步骤:
1. 修改models.py
2. 生成迁移文件:python manage.py makemigrations learning_logs
3. 应用迁移:python manage.py migrate

django的管理网站

django会默认提供一个管理网站

创建超级用户

python manage.py createsuperuser

在这里插入图片描述

一些敏感信息可能会向网站管理员隐藏。例如,Django并不存储你输入的密码,而是存储从该密码派生出来的一个字符串,称为散列值。每当你输入密码时,Django都计算其散列值,并将结果与存储的散列值进行比较。如果这两个散列值相同,你就通过了身份验证。由于存储的是散列值,即便黑客获得了网站数据库的访问权,也只能获取其中存储的散列值,无法获得密码。在网站配置正确的情况下,几乎无法根据散列值推导出原始密码。

向管理网站注册模型

Django自动在管理网站中添加了一些模型,如User和Group,但对于我们创建的模型,必须手工进行注册

fromdjango.contribimportadmin
from.modelsimportTopic

#Registeryourmodelshere.
admin.site.register(Topic)#django通过管理网站管理模型

访问管理网站

http://127.0.0.1:8000/admin/
在这里插入图片描述

添加主题

点击add之后save添加
在这里插入图片描述

定义模型Entry

条目Entry和主题Topic多对一

classTopic(models.Model):#继承Model,即Django中定义了模型基本功能的类
"""用户学习主题"""
text=models.CharField(max_length=200)#由字符组成的数据,即文本
date_added=models.DateTimeField(auto_now=True)#日期和时间的数据,参数属性表示自动设置当前日期和时间

def__str__(self):
"""返回模型的字符串表示"""
returnself.text#告诉Django,默认使用哪个属性来显示有关主题的信息


classEntry(models.Model):
"""学到的某个主题的具体知识"""
topic=models.ForeignKey(Topic,on_delete=models.CASCADE)
#外键(foreignkey)是一个数据库术语,它指向数据库中的另一条记录,这里是将每个条目关联到特定主题
#创建每个主题时,都分配了一个键(ID)。需要在两项数据之间建立联系时,Django使用与每项信息相关联的键.
#on_delete=models.CASCADE让Django在删除主题的同时删除所有与之相关联的条目,这称为级联删除(cascadingdelete)
text=models.TextField()
date_added=models.DateTimeField(auto_now=True)

classMeta:
verbose_name_plural='entries'
#Django在需要时使用Entries来表示多个条目。如果没有这个类,Django将使用Entrys来表示多个条目

def__str__(self):
"""返回字符串表示"""
returnf"{self.text[:50]}..."

然后迁移数据库模型,三步骤。

向管理网站注册Entry

admin.site.register(Entry)

添加条目

在这里插入图片描述
在这里插入图片描述

django shell的使用

每次修改模型后,都需要重启shell,这样才能看到修改的效果。要退出shell会话,可按Ctr +
D。如果你使用的是Windows系统,应按Ctr + Z,再按回车键。

python manage.py shell

在这里插入图片描述
执行一些遍历等操作
在这里插入图片描述
根据id获取topic的属性
在这里插入图片描述
使用外键获取关联数据
要通过外键关系获取数据,可使用相关模型的小写名称、下划线和单词set
在这里插入图片描述

创建页面

三个部分:定义URL,编写视图(views),编写模板(html)。

映射URL

urls.py
fromdjango.contribimportadmin
fromdjango.urlsimportpath,include

urlpatterns=[
path('admin/',admin.site.urls),
path('',include('learning_logs.urls'))
]

默认的urls.py包含在文件夹learning_log中,现在需要在文件夹learning_logs中再创建一个urls.py文件。

"""定义learning_logs的URL模式"""
fromdjango.urlsimportpath

fromlearning_logsimportviews

app_name='learning_logs'#变量app_name让Django能够将这个urls.py文件同项目内其他应用程序中的同名文件区分开来
urlpatterns=[
path('',views.index,name='index')
]

实际的URL模式是对函数path()的调用,这个函数接受三个实参:
第一个是一个字符串’ ‘,帮助Django正确地路由(route)请求。收到请求的URL后,Django力图将请求路由给一个视图。为此,它搜索所有的URL模式,找到与当前请求匹配的那个。Django忽略项目的基础URL(http://localhost:8000/),因此空字符串(’')与基础URL匹配.
第二个实参views.index指定了要调用view.py中的哪个函数。请求的URL与前述正则表达式匹配时,Django将调用view.py中的函数index().
第三个实参name='index’将这个URL模式的名称指定为index,让我们能够在代码的其他地方引用它。每当需要提供到这个主页的链接时,都将使用这个名称,而不编写URL。

编写视图

fromdjango.shortcutsimportrender


#Createyourviewshere.

defindex(request):
"""学习笔记的主页"""
returnrender(request,'learning_logs/index.html')#函数render(),它根据视图提供的数据渲染响应

编写模板

一般保存在templates目录下
在这里插入图片描述
效果
在这里插入图片描述

父模板

创建网站时,一些通用元素几乎会在所有页面中出现。在这种情况下,可编写一个包含通用元素的父模板,并让每个页面都继承这个模板,而不必在每个页面中重复定义这些通用元素。

父模板的好处:
模板继承的优点开始显现出来了:在子模板中,只需包含当前页面特有的内容。这不仅简化了每个模板,还使得网站修改起来容易得多。要修改很多页面都包含的元素,只需修改父模板即可,所做的修改将传导到继承该父模板的每个页面。在包含数十乃至数百个页面的项目中,这种结构使得网站改进起来更容易、更快捷。

<p>
<ahref="{%url'learning_logs:index'%}">LearningLog</a>
</p>
{%blockcontent%}{%endblockcontent%}
模板标签:用花括号和百分号({% %})表示的

这里的模板标签{% url ‘learning_logs:index’%}生成一个URL,该URL与在learning_logs/urls.py中定义的名为’index’的URL模式匹配
learning_logs是一个命名空间,而index是该命名空间中一个名称独特的URL模式。这个命名空间来自在文件learning_logs/urls.py中赋给app_name的值。
在这里插入图片描述
作用:通过使用模板标签来生成URL,能很容易地确保链接是最新的:只需修改urls.py中的URL模式,Django就会在页面下次被请求时自动插入修改后的URL。

块标签:这个块名为content,是一个占位符,其中包含的信息由子模板指定。

子模板并非必须定义父模板中的每个块,因此在父模板中,可使用任意多个块来预留空间,而子模板可根据需要定义相应数量的块。

创建其他页面

创建页面的步骤均是:url+视图+模板+模板入口添加

创建topics页面
path('topics/',views.topics,name='topics')

deftopics(request):
"""显示所有主题"""
topics=Topic.objects.order_by('date_added')
context={'topics':topics}#定义一个将发送给模板的上下文。上下文是一个字典,其中的键是将在模板中用来访问数据的名称,而值是要发送给模板的数据。
returnrender(request,'learning_logs/topics.html',context)

在这里插入图片描述
在这里插入图片描述
将新的模板添加到base中
在这里插入图片描述
访问效果
在这里插入图片描述

创建单个topic页面
path('topics/<int:topic_id>',views.topic,name='topic')
#第一部分让Django查找在基础URL后包含单词topics的URL,第二部分(/<int:topic_id>/)与包含在两个斜杠内的整数匹配,并将这个整数存储在一个名为topic_id的实参中

deftopic(request,topic_id):
"""显示单个主题的所有条目"""
topic=Topic.objects.get(id=topic_id)
entries=topic.entry_set.order_by('date_added')
context={'topic':topic,'entries':entries}
returnrender(request,'learning_logs/topic.html',context)

在这里插入图片描述
“|”:模板过滤器,对模板变量的值进行修改的函数

创建表单

在Diango中,创建表单的最简单方式是使用ModelForm,根据models模型中的信息自动创建表单。

创建topic的表单
创建forms
fromdjangoimportforms

fromlearning_logs.modelsimportTopic


classTopicForm(forms.ModelForm):#继承forms.ModelForm
classMeta:
model=Topic#根据哪个模型创建表单
fields=['text']#表单只包含字段text
labels={'text':''}#不为字段text生成标签
创建页面
path('new_topic/',views.new_topic,name='new_topic')

defnew_topic(request):
"""添加新主题"""
ifrequest.method!='POST':#如果不是post而是get请求,那么提交空表单
form=TopicForm()#建一个TopicForm实例,将其赋给变量form,再通过上下文字典context将这个表单发送给模板
else:
form=TopicForm(data=request.POST)
ifform.is_valid():#方法is_valid()核实用户填写了所有必不可少的字段(表单字段默认都是必不可少的),且输入的数据与要求的字段类型一致
form.save()#将表单中的数据写入数据库
returnredirect('learning_logs:topics')#函数redirect将视图名作为参数,并将用户重定向到这个视图
context={'form':form}
returnrender(request,'learning_logs/new_topic.html',context)#无论是用户刚进入new_topic页面还是提交的表单数据无效,这些代码都将执行

在这里插入图片描述
然后在topics页面添加new_topic的链接。
效果图
在这里插入图片描述

创建entry表单

更新forms,url+views+html

classEntryForm(forms.ModelForm):
classMeta:
model=Entry
fields=['text']
labels={'text':'Entry'}
#小部件(widget)是一个HTML表单元素,如单行文本框、多行文本区域或下拉列表。通过设置属性widgets,可覆盖Django选择的默认小部件。通过让Django使用forms.Textarea,我们定制了字段
#'text'的输入小部件,将文本区域的宽度设置为80列,而不是默认的40列
widgets={'text':forms.Textarea(attrs={'cols':80})}

path('new_entry/<int:topic_id>/',views.new_entry,name='new_entry')

在这里插入图片描述
在topic.html中添加链接到new_entry
在这里插入图片描述在这里插入图片描述
效果

在这里插入图片描述

编辑条目页面
path('edit_entry/<int:entry_id>/',views.edit_entry,name='edit_entry')

defedit_entry(request,entry_id):
"""编辑条目"""
entry=Entry.objects.get(id=entry_id)
topic=entry.topic
ifrequest.method!='POST':
#初次请求,回显当前条目
form=EntryForm(instance=entry)
else:
form=EntryForm(instance=entry,
data=request.POST)#传递实参instance=entry和data=request.POST,让Django根据既有条目对象创建一个表单实例
ifform.is_valid():
form.save()
returnredirect('learning_logs:topic',topic=topic.id)
context={'entry':entry,'topic':topic,'form':form}
returnrender(request,'learning_logs/edit_entry.html',context)

在这里插入图片描述
在这里插入图片描述
效果
在这里插入图片描述

添加users用户管理

创建应用程序users

python manage.py startapp users

添加到settings中

INSTALLED_APPS=[
#我自己的应用程序
'learning_logs',
'users',
#默认添加的应用程序
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]

添加到根目录的urls映射中

urlpatterns=[
path('admin/',admin.site.urls),
path('users/',include('users.urls')),
path('',include('learning_logs.urls')),
]
login

添加到当前应用urls映射

"""
定义users的url模式
"""
fromdjango.urlsimportpath,include

app_name='users'#变量app_name让Django能够将这个urls.py文件同项目内其他应用程序中的同名文件区分开来
urlpatterns=[
#包含默认的身份认证url
path('',include('django.contrib.auth.urls'))
]

使用django默认的login视图,所以不需要编写views。

创建模板

默认的身份验证视图在文件夹registration中查找模板
在目录learning_log/users/中新建一个名为templates的目录,再在这个目录中新建一个名为registration的目录
在这里插入图片描述

在base.html添加登录的链接,让每个页面都显示
在这里插入图片描述
效果
在这里插入图片描述

logout

在这里插入图片描述
注销模板
默认的注销视图使用模板logged_out.html渲染注销确认页面。
在这里插入图片描述
效果
在这里插入图片描述

register

使用Django提供的表单UserCreationForm,不需要单独创建forms。

path('register/',views.register,name='register')

fromdjango.contrib.authimportlogin
fromdjango.contrib.auth.formsimportUserCreationForm
fromdjango.shortcutsimportrender,redirect


#Createyourviewshere.
defregister(request):
"""注册新用户"""
ifrequest.method!='POST':
form=UserCreationForm()
else:
form=UserCreationForm(data=request.POST)
ifform.is_valid():
new_user=form.save()
login(request,new_user)#django默认的登录视图方法
returnredirect('learning_logs:index')
context={'form':form}
render(request,'registration/register.html',context)

在这里插入图片描述
效果
在这里插入图片描述

登录访问限制

使用装饰器login_required包裹views中每个方法,除了首页index之外,如果你在未登录的情况下尝试访问这些页面,将被重定向到登录页面。
在这里插入图片描述

数据关联用户

需要将数据关联到提交它们的用户。只需将最高层的数据关联到用户,更低层的数据就会自动关联到用户。

修改模型models

在这里插入图片描述
获取admin用户的id,将所有主题关联到admin用户
在这里插入图片描述

因为新增了owner字段,需要执行数据库迁移

在这里插入图片描述使用shell验证是否迁移成功(查看所有topic是否属于admin用户)

在这里插入图片描述

调整只允许用户访问自己的主题

在这里插入图片描述
对于单个主题的访问也需要添加限制,否则输入id之后依旧可以访问不属于自己的主题
在这里插入图片描述

限制编辑条目页面只允许修改属于自己的条目
在这里插入图片描述
因为topic添加了owner,所以新建topic的时候要输入owner
在这里插入图片描述
最终项目就编写完成,之后可以用过bootstrap调整项目的样式,让项目更加好看一些。

  • 30
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值