项目和数据准备:
学会看django官网
可以切换展示语言
项目开始前的准备工作
入门1看完了,就可以了
- 创建django项目,及app并注册app (项目和app名字 随便写,如myProject myApp)
- 连接mysql,启动成功 表示连成功
- 新建app的urls.py 和templates文件夹,并调试打通MTV
- templates文件下新增test.html 文件
- render渲染 templates 文件中的html
def test(request): # 用来调试打通MTV的 return render(request,'test.html')
- 主urls.py中的写法,导入include,写法: 应用名.urls ()
from django.urls import path,include urlpatterns = [ path('admin/', admin.site.urls), path('polls/',include("myApp.urls")) ]
- 应用内urls.py中,路由关联视图函数
from django.urls import path from .views import test urlpatterns = [ path('test/', test, name="test"), # 用来调试的 ]
-
访问路由触发视图函数,就能渲染 templates中的页面
- templates文件下新增test.html 文件
开始做个小项目
第一步:建表
建立 问题 和选项表,展示问题列表,以及能够跳转到问题详情
1.models.py,然后生成迁移文件后同步(代码在入门1)
class Question(models.Model):
question_text =models.CharField(max_length=200)
pub_date =models.DateTimeField('注释')
class Choice(models.Model):
question = models.ForeignKey(Question,on_delete=models.CASCADE) # 外键被删除,这个也被删除
choice_text =models.CharField(max_length=200)
votes_num = models.IntegerField(default=0)
views.py
def test(request): # 用来调试打通MTV的
return render(request,'test.html')
def index(request):
question_list=Question.objects.all()
context = {"question_list": question_list}
return render(request, 'index.html', context)
def detail(request,question_id):
try :
question =Question.objects.get(pk=question_id)
context ={"question":question}
except Question.DoesNotExist:
raise Http404("quesion does not exist") #from django.http import Http404
return render(request, 'detail.html', context)
应用内urls.py 补充路由
urlpatterns = [
path('test/',views.test,name="test"), # 用来调试的
path('',views.index),
path('<int:question_id>/',views.detail,name='detail')
]
在 templates文件中,新增index.html,以下内容放到body里面, polls ,为应用名
{% if question_list %}
<ul>
{% for question in question_list %}
<li><a href="/polls/{{ question.id }}">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p> no polls are available</p>
{% endif %}
detail.html,以下内容放到body里面
详情页
<br>
问题:{{ question.question_text }}
<br>
选项:
访问 地址Http://127.0.0.1:8000/polls/, 一开始没有数据,然后新增用户去admin页面新增点数据,要先注册模型,查看入门1
添加后数据后
-------------------------------以上操作涉及的问题---------------------------------------------
- 1.on_delete 外键删除逻辑:
- 2.html中a标签 跳转路由的写法,有两种
- 3.render返回数据给 html, 和html模板中数据的使用,见 入门1.
- 4.主动 raise 一个404错误
1.on_delete 外键删除逻辑:
2.html中a标签 跳转路由的写法,有两种
在index.html中
访问详情,如下这种方式是 硬编码 url(推荐这个)
如果不要硬编码url,可以这么写(但一般不这样,麻烦..)
{% url 'hello:detail' question.id %}
写法如上:
第一个是url
第二个是 表示用哪个路由,用urls中定义的app_name : name
第三个是 要传递的参数
3.主动 raise 一个404错误
raise Http404("quesion does not exist") # from django.http import Http404
第二步:继续优化,和详情页展示 问题的选项
视图函数中,使用 get_object_or_404 来获取数据对象,
1.视图函数中:get_object_or_404的作用,是代替了这部分代码
如下是改用get_object_or_404,就方便多了
实现投票功能
接着先准备
detail.html改一下, 要把选项展示出来:
使用choice_set.all 。 可以获取所有这个问题的答案
(上面截图中,form单词写错了)
第二步涉及知识点:
- get_object_or_404 获取数据,获取不到就返回404 ---见上面不解释了
- 外键表名.表名_set.all 的用法: 用于查询哪些使用了某外键
外键表名.表名_set.all 的用法:
- 对象. 表名_set 点all 表示全部
- 对象. 表名_set 点get (pk=*)表示查询某一个
第三步:实现投票功能
form表单实现请求
就还需要定义属性 action (写路由的) 和method
需要定义一个表单,type为submit的。
类似这种:
下一步:就定义一个视图函数,以及配置一个路由触发视图函数
定义 vote的url,urls.py中添加
path('<int:question_id>/vote',views.vote,name='vote')
定义视图函数:功能是
views.py中添加 投票的视图函数
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):
# Redisplay the question voting form.
return render(request, 'detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else: # 这里的代码相当于是写在try里的
selected_choice.votes_num += 1
selected_choice.save()
用postman来触发 此视图函数。
完善form表单,用表单来实现请求:
<form action="/demo/{{ question.id }}/vote" method="post">
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" value="{{ choice.id }}">
<label>{{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="投票" />
</form>
接着再写一个 结果页面,投票完成后,可以跳转到这个页面。再吧上面投票视图中,最后改一下
使用HttpResponseRedirect 进行重定向
# return HttpResponse("投票成功") # 这句话改成下面这句话 return HttpResponseRedirect(f"/demo/{question.id}/results")
定义路由:
并且views.py中vote函数也用了 name为results 的url,这里先定义下
path('<int:question_id>/results',views.result,name='results')
views.py中
def result(reuqest,question_id):
question = get_object_or_404(Question, pk=question_id)
return render(reuqest, '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_num }} 票</li>
{% endfor %}
</ul>
<a href="/demo/{{ question.id }}/">再次投票</a>
接着优化,没有选择投票,就点击时,页面反馈
{% if error_message %} <p><strong>{{ error_message }}</strong>><</p> {% endif %}
成品效果
- form表单请求接口
- HttpResponseRedirect 重定向到某个页面
form表单请求接口
form标签中的 action接要请求的接口,和请求方式 post 还是get
form中的标签的 name属性,就是要传递的参数
HttpResponseRedirect重定向
detail.html 中,可以看见提交表单后,是访问的 ***/vote 请求投票接口
方式1:基本用法,加路由的参数如下:
from django.http import HttpResponseRedirect
方式2: 用reverse 使用命名来执行重定向
from django.urls import reverse
其他知识:generic来定义通用视图(有什么好处,之后再理解):
views中
class IndexView(generic.TemplateView):
template_name = "index.html"
def get_context_data(self, **kwargs):
question_list = Question.objects.all()
context = {"question_list": question_list}
return context
urls中
path('test2/',views.IndexView.as_view()),
一样能访问