Django 2 零基础 - 待办清单网站

根据b站视频https://www.bilibili.com/video/BV1bW411N7xN?p=8整理的
不清楚可以去看视频哟

1前期准备

Django 2 零基础 - 待办清单网站_第1张图片
Django 2 零基础 - 待办清单网站_第2张图片

pip freeze  # 查看已安装的包
pip install django==2.0.5  # 安装django2.0.5
cd .. #返回上一级
cd Django_Projects
django-admin startproject to_do_list  # 创建项目
cd to_do_list  # 进入项目文件夹
python manage.py runserver  # 启动服务器
# 在浏览器网址栏输入 localhost:8000
ctrl + c  # 关闭服务器

成功显示如下
Django 2 零基础 - 待办清单网站_第3张图片

2准备app

  • 激活虚拟环境
    Django 2 零基础 - 待办清单网站_第4张图片
 cd desktop
 cd Django_venv # 到虚拟环境文件夹
cd Scripts  # 执行该文件
activate
cd ..
cd Django_Projects
cd to_do_list  # 进入todo项目文件夹
python manage.py runserver  # 启动服务器
ctrl+c 关闭服务器
  • 一个app负责一种功能 创建一个 todolist App 负责实现 待办事项 功能
 python manage.py startapp todolist

Django 2 零基础 - 待办清单网站_第5张图片
将to_do_list整个拖到文本编辑器

  • 注册该app,告诉服务器我存在
在settings.py INSTALLED_APPS 中加入
'todolist',
  • 在这个app里面做个html网页,放在templates(网页模板)文件夹中
    在这里插入图片描述
右键 new file home.html

在这里插入图片描述

!tab
h1 tab 会自动生成

Django 2 零基础 - 待办清单网站_第6张图片
右键 open in browser 选default 选择其他可能会出现找不到文件chromeDjango 2 零基础 - 待办清单网站_第7张图片

这种问题主要是因为在pycharm中关于chrome的安装路径配置不正确造成的,具体的解决办法为:

打开pycharm–》File–》setting–》Tools–》Web Browsers

然后添加chrome安装路径,然后就成功啦~

3配置url和view

  • 设置好网址, 给这个页面起个什么网址
  • 当用户通过这个网址发出请求时,将网页发送给他
  • 因为这个网页是待办事项网页, 网址设置和用户请求都让 todolist APP处理
to_do_list/to_do_list/urls.py [所有网址首先由它接手]
                       ||
                       ||
                      \  /
                       \/
to_do_list/todolist/urls.py [与待办事项相关的网址交给我接手]
                       ||
                       ||
                      \  /
                       \/
to_do_list/todolist/views.py [用户通过这些网址发出的请求的由我来处理]

这里django可能下滑波浪线 可以在settings把环境选在scripts下 因为刚开始装的时候是吧django装在scripts下 Django 2 零基础 - 待办清单网站_第8张图片

4.bootstrap导航栏

https://v4.bootcss.com/docs/4.0/examples/ 找到Navbar static 复制源代码
替换cdn

在这里插入图片描述

5.bootstrap表格

https://v4.bootcss.com/docs/4.0/content/tables/

6.bootstrap表单

https://v4.bootcss.com/docs/components/forms/

7.网址名,网页名

关于include()
大项目 -> 要避免网址名 网页名冲突
render() 如何找到网页 ?
根据所提供的网页名称,找所有的templates的文件夹,取第一个匹配的
网页名字重复怎么办?
给个前缀
建个新文件夹在templates下,以 app的名字 命名

   templates/app的名字/网页名字
    views.py -> return render(request, "todolist/home.html")

    <a href="hostname/urlpattern"></a>

想改网址怎么办?要改的地方好多o(╥﹏╥)o
给网址起名字

   <a href="{% url 'url_name' %}"></a>  template tag{% tag_name  %}

Django 2 零基础 - 待办清单网站_第9张图片
在这里插入图片描述

网址名跟其他app里面的网址名字重复怎么办?
给个前缀
Django 2 零基础 - 待办清单网站_第10张图片

在这里插入图片描述

8 模版继承

我想改变导航栏的样式怎么办? 3个网页都要改?
Template inheritance
做个模板html(所有网页的风格主题), 其他网页继承它,拓展它, 类似python的类继承
extends

{% extends "base.html" %}

block tag
{% block blockname %}

{% endblock blockname %}

three-level 大网站建议三级,小网站两级 

                              article.html
                            / 
             base_news.html  
           /                \
base.html                     live.html
           \
             base_sports.html

Django 2 零基础 - 待办清单网站_第11张图片
到main之前的 和之后的粘贴下来 做成base.html

{% block 主体%}
{% endblock 主体 %}
 在被剪切的那个网页放入
{ % extends "todolist/base.html"%}

{% block 主体 %}
 

9.静态文件

新建static文件夹,存放 图片 css javascript
里面,再新建一个app文件夹,避免与其他app的static文件夹里面的静态文件冲突

app/static/app/images
app/static/app/js
app/static/app/css
app/static/app/icons


{% load static %}
{% static "路径" %}

10.处理用户请求

 
request GET
HTML form -> action="" method="POST" button->submit
{% csrf_token %} 跨站请求伪造
name="" 给input的起名字
request.POST是什么? QueryDict
content dictionary 在html中通过var访问字典
{{ var }} 变量{{ }} 和标签{% %}
post是发送请求 action='' 表发送到自己的服务器

11.增删改查

Django 2 零基础 - 待办清单网站_第12张图片
刷新后会出现如图错误 因为我们定义的是post 而刷新方法是get
所以 要承担用户的post和get请求

增删改查 用字典存储, 只要服务器开着…
如果是get请求怎么办? 比如刷新 判断request.method 如果是get 只要将原来页面返回给他即可

 
def edit(request):
    # 显示回给用户
    if request.method=='POST':
        content = {'待办事项': request.POST['待办事项']}  # 因为request.post是字典 可以找他的key 而找到所对应的值
        return render(request,"todolist/edit.html",content) #值显示在这个网页中
    elif request.method=='GET':
        return render(request, "todolist/edit.html")

如果是get请求怎么办? request.POST 中不存在’待办事项’这个键
如果是post请求, 但用户不写内容怎么办? request.POST 中的’待办事项’这个键对应值为 空的字符串 ‘’

def edit(request):
    # 显示回给用户
    if request.method=='POST':

        if request.POST['待办事项']==' ':#如果用户在待办里什么都不写 返回给页面警告
            return render(request,"todolist/edit.html", {'警告':'请输入内容!'})
        else:
            content = {'待办事项': request.POST['待办事项']}  # 因为request.post是字典 可以找他的key 而找到所对应的值
            return render(request,"todolist/edit.html",content) #值显示在这个网页中
    elif request.method=='GET':
        return render(request, "todolist/edit.html")

用GET方法删除,划掉真的对吗? 用隐藏的form
全局列表

{% for  in  %}

    {{ forloop.counter }}

    {% if  %}
        
    {% else %}
        
    {% endif %}

{% endfor %}

"{% url 'todolist:删除' forloop.counter %}" #中间的空格相当于/
 del/<forloop_counter>  

#按照序号删除
def delete(request,forloop_counter):
    lst.pop(int(forloop_counter)-1)
    return redirect("todolist:编辑") #不是渲染 render 而是跳转到网址去(有名字的地方 不是网站)  
redirect()




重点在于 查找路径todo/ del/ 当你删除序号的待办事项 是todo/ del/2

12.bootstrap弹窗

https://v4.bootcss.com/docs/4.0/components/alerts/

<div class="alert alert-warning alert-dismissible fade show" role="alert">
  <strong>Holy guacamole!</strong> You should check in on some of those fields below.
  <button type="button" class="close" data-dismiss="alert" aria-label="Close">
    <span aria-hidden="true">&times;</span>
  </button>
</div>

js

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js" integrity="sha384-smHYKdLADwkXOn1EmN1qk/HfnUcbVRZyYmZ4qpPea6sjB/pTJ0euyQp0Mk8ck+5T" crossorigin="anonymous"></script>

Modal https://v4.bootcss.com/docs/4.0/components/modal/

13.数据库

数据库,建标

CREATE TABLE 待办事项表
(
    序号 INT NOT NULL AUTO_INCREMENT,
    待办事项 VARCHAR(100) NOT NULL,
    已完成 tinyint(1) NOT NULL DEFAULT 0,
    PRIMARY KEY (序号) 
)ENGINE=InnoDB CHARSET=utf8;
增加数据
INSERT INTO 待办事项表 (待办事项) VALUES ('看电影');
INSERT INTO 待办事项表 (待办事项) VALUES ('逛街');
INSERT INTO 待办事项表 (待办事项) VALUES ('陪客户吃饭');
建表 和 增删改查 django都能帮我们搞定
设置数据库连接
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

create Model
创建Model类,用来描述表的构成: 有哪些列(待办事项,完成状态,序号…)
这是给网站开发者看的

makemigrations -> 中文:制作迁移文件
例如:0001_initial.py 也是用来描述表的构成
django会利用这个文件来建表改表
每次新增model() 或者 修改model(表的构成) 都要 makemigrations
这是给django自己看的,它用这个文件来建表或修改表
python manage.py sqlmigrate todolist 0001 不会真的建表,只是查看
查看django用 0001_initial.py 文件, 转化成了什么sql语句(不同的数据库服务器,语句不一样)帮我们建表, todolist是app的名字
BEGIN;
--
-- Create model Todo
--
CREATE TABLE "todolist_todo" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
     "thing" varchar(50) NOT NULL,
      "done" bool NOT NULL
);
COMMIT;
migrate -> 中文:迁移,即运行这个文件 0001_initial.py 真正在数据库中建表,或修改表的结构
python mange.py shell
from todolist.models import Todo
Todo.objects.all() -> QuerySet 查询集合 简单理解为表中的所有数据 
                   -> 所有行的集合__str__  显示更友好,命令行以及admin界面
Todo.objects.count() -> 行的数量

a_row = Todo(thing='逛街', done=False) -> 创建一行数据, 但并未保存
a_row.save() -> 真正保存到库中
a_row.id -> 保存之后才有id(序号)

a_row.thing -> 获取这一行的 thing(待办事项) 的值

Todo.objects.filter(done=False) -> 获取 [[所有]] done 为 False 的行, 即未完成的事项, 结果是个集合
another_row = Todo.objects.get(thing='逛街') -> 获取 thing 为 的行,仅一行
get不到会报错

another_row.thing = '去超市' -> 修改这一行的thing为 '去超市'
another_row.save() -> 改完别忘了保存

another_row.delete() -> 删除这一行
Todo.objects.all() -> 看看现在有什么

exit()    ctrl+z 回车

Register Models -> 注册model  注册后, 可以通过django自带的app -> admin后台界面来管理表数据

a = Todo.objects.get(id=2)
a.delete()

Django 2 零基础 - 待办清单网站_第13张图片

def cross(request,i_id):
    if request.POST['完成状态']=='已完成':
    
        a = Todo.objects.get(id=i_id)
        a.done=True
        return redirect("todolist:编辑")
    else:
        a = Todo.objects.get(id=i_id)
        a.done= False
        return redirect("todolist:编辑")

    #点击划掉按钮 会向划掉网址发送一个请求  post请求里面包含来了一个‘完成状态’信息
     其对应的值是已完成 然后交给views.py 的cross处理 

—————————————————————————————————————————————

登录注册

思路

1auth.urls

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


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

2 myauth.urls

from django.urls import path,include
from . import views
app_name='myauth'
urlpatterns = [
    path('',views.主页,name='主页'),
    path('login/',views.登录,name='登录'),
]

3 views.py

def 主页(请求):
    return render(请求,'myauth/home.html')

4 html

创建超级管理员
python manage.py createsuperuser

python manage.py runserver 开启服务器

在model中建表 建注册的新要求

from django.db import models
from django.contrib.auth.models import User



# Create your models here.


class 普通会员表(models.Model):
    用户=models.OneToOneField(User,on_delete=models.CASCADE)
    昵称=models.CharField(blank=True,max_length=50)
    生日=models.DateField(blank=True,null=True)#生日可以为空  修改model后要重新建立迁移文件

    class Meta:
        verbose_name_plural="普通会员表s"

之后在cmd输入以下两句 真正的建表

python manage.py makemigrations
python manage.py migrate

在admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User
from .models import 普通会员表

class 普通会员表Inline(admin.TabularInline):#两张表一起显示 表格显示法 一对一
    model= 普通会员表
    can_delete = False
    verbose_name_plural = '普通会员表'


class UserAdmin(BaseUserAdmin):
    inlines = (普通会员表Inline,)

admin.site.unregister(User)
admin.site.register(User,UserAdmin) #重新注册 前者注册model这个表 后者注册配置文件

新建forms.py

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django import forms
#创建一个表单给用户填写 之前的UserCreationForm是django帮我们写的 所以现在新建的继承UserCreationForm

class 自定义注册表单(UserCreationForm):
    昵称 = forms.CharField(required=False, max_length=50)#required=False昵称不一定写
    生日 = forms.DateField(required=False)

    class Meta:
        model=User #自定义注册表属于普通会员表 而其又属于User(UserCreationFor创建产生的
        fields=('username','password1','password2','email','昵称','生日')#指定非超级用户(管理员)什么地方可以编辑什么地方不可以

        

之后再views.py 导入

from .forms import 自定义注册表单

将UserCreationForm替换成自定义注册表单

若不满意django自带的错误提示 可以用if else 自己写
或者自定义错误 但是一般比较麻烦的是不知道对应的键值 所以输入as.json

Django 2 零基础 - 待办清单网站_第14张图片
在这里插入图片描述
这样就知道键值是 invalid
可以在def 中修改invalid的值
Django 2 零基础 - 待办清单网站_第15张图片
建立个人中心

现有网址再有网页再有函数
urls.py

 path('user_center/',views.user_center,name='个人中心'),
    path('user_center/edit_profile',views.编辑个人信息,name='编辑个人信息'),
    path('user_center/change_password',views.修改密码,name='修改密码'),

views.py

from django.contrib.auth.decorators import login_required
 
@login_required(login_url="myauth:登录") #一定要登录 没登录的话跳到登录页面
def 个人中心(请求):
    return render(请求,'myauth/user_center.html')

@login_required(login_url="myauth:登录")
def 编辑个人信息(请求):
    if 请求.method == 'POST':#编辑成功到中心
        return redirect(请求,'myauth/user_center.html')
    else:#get 是想编辑
        return render(请求, 'myauth/edit_profile.html')

@login_required(login_url="myauth:登录")
def 修改密码(请求):
    if 请求.method == 'POST':  # 编辑成功到中心
        return redirect(请求, 'myauth/user_center.html')
    else:  # get 是想编辑
        return render(请求, 'myauth/change_password.html')

待更新…

你可能感兴趣的:(django,python,web)