# Python编程从入门到实践项目:Web应用程序
## 一、整体思维导图
### 1.整体总结
![Django Web开发思维导图](Python编程从入门到实践:Web应用程序.assets/Django Web开发思维导图.png)
### 2.文件目录架构
![image-20240428173524835](Python编程从入门到实践:Web应用程序.assets/image-20240428173524835.png)
每个应用的目录
![image-20240428173618781](Python编程从入门到实践:Web应用程序.assets/image-20240428173618781.png)
## 二、django-bootstrap3演示有关地址的设置
### bootstrap.py
文件位置:C:\python\learning_log\ll_env\Lib\site-packages\bootstrap3
后续设置样式的时候,代码没有问题,但是不显示效果,经查询是css和js地址需要修改为国内地址,还必须联通网络
```python
--snip--
# Default settings
BOOTSTRAP3_DEFAULTS = {
"css_url": {
#"url": "https://stackpath.bootstrapcdn.com/bootstrap/3.4.1./css/bootstrap.min.css",
#换成国内地址
"url": "https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1./css/bootstrap.min.css",
"integrity": "sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1.+c8xmyTe9GYg1.l9a69psu",
"crossorigin": "anonymous",
},
"theme_url": None,
"javascript_url": {
#"url": "https://stackpath.bootstrapcdn.com/bootstrap/3.4.1./js/bootstrap.min.js",
#换成国内地址
"url": "https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1./js/bootstrap.min.js",
"integrity": "sha384-aJ21.OjlMXNL5UyIl/XNwTMqvzeRMZH2w8c5cRVpzpU8Y5bApTppSuUkhZXN0VxHd",
"crossorigin": "anonymous",
},
```
## 三、learning_log文件夹部分文件内容
### 1.settings.py
```python
--snip--
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
#第三方应用程序
'bootstrap3',
#我的应用--- 学习笔记 learning_log,users 两个应用
'learning_logs',
'users',
]
--snip--
#我的设置
LOGIN_URL = '/users/login/'
#django-bootstrap3的设置
BOOTSTRAP3 = {
'include_jquery':True,
}
--snip--
```
### 2.urls.py
```python
"""
URL configuration for learning_log project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
1.. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1.. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1.. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path
from django.conf.urls import include
urlpatterns = [
path('admin/', admin.site.urls),
path('users/',include('users.urls',namespace='users')),
path('',include('learning_logs.urls',namespace='learning_logs')),
]
```
## 四、learning_logs文件夹文件内容
### 1.modes.py
相当于定了数据库中表及其字段信息,是一个类,定义了属性和方法
```python
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Topic(models.Model):
"""用户学习的主题"""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User,on_delete=models.CASCADE)
def __str__(self):
"""返回模型的字符串表示"""
return self.text
class Entry(models.Model):
"""学到的有关某个主题的详细内容"""
#从django1..9开始ForeignKey中on_delete参数是必须的
topic = models.ForeignKey(Topic,on_delete=models.CASCADE)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'entrie'
def __str__(self):
"""返回模型的字符串表示"""
return self.text[:50]+"..."
```
### 2.urls.py
```python
""" 定义learnling_logs的url模式"""
from django.urls import path
from . import views
app_name = 'learning_logs'
urlpatterns =[
# 主页
path('',views.index,name='index'),
#显示所有的主题
path('topics/',views.topics,name='topics'),
#显示特定主题的详细页面path(r'topics/(?P<topic_id>\d+)/$/',views.topic,name='topic'),
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'),
#编辑条目
path('edit_entry/<int:entry_id>/',views.edit_entry,name='edit_entry'),
]
```
3、forms.py
只包含一个内嵌的Meta类,他告诉Django根据哪个模型创建表单,以及在表单中包含哪些字段。
```python
from django import forms
from .models import Topic,Entry
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text':''}
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['text']
labels ={'text':''}
widgets = { 'text':forms.Textarea(attrs={'cols':80})}
```
### 3.views.py
接受请求信息,准备数据处理,并发给浏览器
基本每一个函数代表一个动作
```python
from django.shortcuts import render
from django.http import HttpResponseRedirect,Http404
from django.urls import reverse # django.core.urlresolverses django2.0 修改为django.urls
from django.contrib.auth.decorators import login_required
from .models import Topic,Entry
from .forms import TopicForm,EntryForm
# Create your views here.
def index(request):
""" 学习笔记的主页"""
return render(request,'learning_logs/index.html')
@login_required
def topics(request):
"""显示所有的主题"""
topics = Topic.objects.filter(owner=request.user).order_by('date_added')
context = {'topics':topics}
return render(request,'learning_logs/topics.html',context)
@login_required
def topic(request,topic_id):
"""显示特定主题及主题下的所有条目"""
topic = Topic.objects.get(id=topic_id)
#确认请求的主题属于当前用户
if topic.owner !=request.user:
raise Http404
# -表示按降序排列
entries = topic.entry_set.order_by('-date_added')
context = {'topic':topic,'entries':entries}
return render(request,'learning_logs/topic.html',context)
@login_required
def new_topic(request):
#添加新主题
if request.method !='POST':
#未提交数据,创建一个新表单
form = TopicForm()
else:
#POSt提交的数据,对数据进行处理
form =TopicForm(request.POST)
if form.is_valid():
new_topic = form.save(commit=False)
new_topic.owner = request.user
new_topic.save()
return HttpResponseRedirect(reverse('learning_logs:topics'))
context = {'form':form}
return render(request,'learning_logs/new_topic.html',context)
@login_required
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 HttpResponseRedirect(reverse('learning_logs:topic',args=[topic_id]))
context = {'topic':topic,'form':form}
return render(request,'learning_logs/new_entry.html',context)
@login_required
def edit_entry(request,entry_id):
"""编辑既有条目"""
entry = Entry.objects.get(id=entry_id)
topic = entry.topic
#确认请求的主题属于当前用户
if topic.owner !=request.user:
raise Http404
if request.method != 'POST':
#未提交数据,创建一个新表单
form = EntryForm(instance=entry)
else:
#post提交的额数据,对数据进行处理
form = EntryForm(instance=entry,data=request.POST)
if form.is_valid():
new_entry = form.save(commit=False)
new_entry.topic = topic
new_entry.save()
return HttpResponseRedirect(reverse('learning_logs:topic',args=[topic.id]))
context = {'entry':entry,'topic':topic,'form':form}
return render(request,'learning_logs/edit_entry.html',context)
```
### 4.下级templates\learning_logs文件夹及相关内容
#### 4.1base.html
模版文件夹,使用bootstrap3设置样式
```html
{% load bootstrap3 %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title> 学习笔记--lxy </title>
{% bootstrap_css %}
{% bootstrap_javascript %}
</head>
<body>
<!-- Static navbar -->
<nav class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#navbar"
aria-expanded="false" aria-controls="navbar">
</button>
<a class="navbar-brand" href="{% url 'learning_logs:index' %}">
学习笔记 </a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="{% url 'learning_logs:topics' %}">Topics</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
{% if user.is_authenticated %}
<li><a> Hello,{{ user.username }}.</a></li>
<li><a href="{% url 'users:logout' %}"> log out </a></li>
{% else %}
<li><a href="{% url 'users:register' %}">register</a></li>
<li><a href="{% url 'users:login' %}">log in</a></li>
{% endif %}
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="container">
<div class="page-header">
{% block header %}{% endblock header %}
</div>
<div>
{% block content %}{% endblock content %}
</div>
</div><!-- /container -->
</body>
</html>