0
点赞
收藏
分享

微信扫一扫

Django学习笔记06

小时候是个乖乖 2022-03-30 阅读 76
djangopython

6. 添加新条目

用于添加新条目的表单

创建一个与模型Entry相关联的表单

forms.py

from django import forms

from .models import Topic, Entry

class TopicForm(forms.ModelForm):
	class Meta:
		model = Topic  	# 根据模型Topic创建表单
		fields = ['text'] 	# 只包含字段text
		labels = {'text': ''} 	# 不要为text生成表单

class EntryForm(forms.ModelForm):
	class Meta:
		model = Entry
		fields = ['text']
		labels = {'text': ''} # 给字段'text'指定了标签'Entry:'
		widgets = {'text': forms.Textarea(attrs={'cols': 80})}

小部件(widget)是一个HTML表单元素,如单行文本框、多行文本框区域或下拉列表。

使用forms.Textarea定制了字段text'的输入小部件,将文本框宽度设置为80列(默认40列)

URL模式 new_entry

urls.py

"""定义learning_logs的URL模式"""
from django.urls import path

from . import views	# 句点让Python从当前urls.py模块所在的文件夹导入views.py

app_name = 'learning_logs' #区分其他应用程序中的同名文件
urlpatterns = [
	# 主页
	path('', views.index, name='index'),
	# 显示所有的主题
	path('topics/', views.topics, name='topics'),
	# 特定主题的详细页面
	path('topics/<int:topic_id>/', views.topic, name='topic'),
	# 用于添加新主题的页面
	path('new_topic/', views.new_topic, name='new_topic'),
	# 用于添加新条目的页面。
	path('new_entry/<int:topic_id>/', views.new_entry,name='new_entry'),
]

其中的id是一个与主题ID匹配的数。

<int:topic_id>捕获一个值,并将其赋值给变量topic_id。

请求的URL与这个模式匹配时,Django将请求和主题ID发送给函数new_entry()。

视图函数new_entry()

from django.shortcuts import render, redirect

from .models import Topic  # 导入模型
from .forms import TopicForm, EntryForm

def index(request):
	"""学习笔记的主页"""
	return render(request, 'learning_logs/index.html')

def topics(request):
	"""显示所有的主题"""
	topics = Topic.objects.order_by('date_added') # 查询数据库————请求提供Topic对象,并根据属性date_added进行排序
	comtext = {'topics':topics}		# 定义一个将发送给模板的上下文
	return render(request, 'learning_logs/topics.html', comtext)

def topic(request, topic_id):
	"""显示单个主题及其所有的条目"""
	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)

def new_topic(request):
	"""添加新主题"""
	if request.method != 'POST':
		# 未提交数据:创建一个新表单
		form = TopicForm()
	else:
		# POST提交的数据:对数据进行处理
		form = TopicForm(data=request.POST) # 使用用户输入的数据(存储在resquest.POST中)创建一个TopicForm实例
		if form.is_valid(): #方法is_valid()核实用户填写了所有必不可少的字段,且输入的数据与要求的字段类型一致。
			form.save() # 将表单中的数据写入数据库
			return redirect('learning_logs:topics') # 存完数据,将浏览器重定向到页面topics。

	# 显示空表单或指出表单数据无效
	context = {'form': form}
	return render(request, 'learning_logs/new_topic.html', context)

def new_entry(request,topic_id):
	"""在特定主题中添加新条目。"""
	topic = Topic.objects.get(id=topic_id)

	if request.method != 'POST':
		# 未提交数据:创建一个空表单
		form = EntryForm()
	else:
		# POST提交的数据:对数据进行处理
		form = EntryForm(data=request.POST)
		if form.is_valid():
			new_entry = form.save(commit=False)
			new_entry.topic = topic
			new_entry.save()
			return redirect('learning_logs:topic',topic_id=topic_id)

	# 显示空表单或指出表单数据无效。
	context = {'topic':topic, 'form':form}
	return render(request, 'learning_logs/new_entry.html', context)

调用save()时,传递实参commit=False,让Django创建一个新的条目对象,并将其赋值给new_entry,但不保存到数据库中。

将new_entry的属性topic设置为在这个函数开头从数据库中获取的主题,再调用save()且不指定任何实参。这将把条目保存到数据库,并将其与正确的主题相关联。

模板new_entry

new_entry.html

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

{% block content %}

  <p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>

  <p>Add a new entry:</p>
  <form action="{% url 'learning_logs:new_entry' topic.id %}" method='post'>
  	{% csrf_token %}
  	{{ form.as_p }}
  	<button name='submit'>Add entry</button>
  </form>

{% endblock content %}

表单的实参action包含URL中的topic_id值,让视图函数能够将新条目关联到正确的主题。

链接到页面new_entry

topic.html

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

{% block content %}

  <p>Topic: {{ topic }}</p>

  <p>Entries:</p>
  <p>
  	<a href="{% url 'learning_logs:new_entry' topic.id %}">Add new entry</a>
  </p>
  
  <ul>
  {% for entry in entries %}
    <li>
    	<p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
    	<p>{{ entry.text|linebreaks }}</p>
    </li>
  {% empty %}
    <li>There are no entries for this topic yet.</li>
  {% endfor %}
  </ul>

{% endblock content %}

将这个链接放在条目列表前面。

完成效果如图:

 

举报

相关推荐

0 条评论