python-Django-学习笔记
Django
点击这里还可以去我的博客主页o
学习django一段时间,
1.可以virtualenv[name]创建一个名字叫django_env 如果要选择自己想要的解释器可以virtualen -p C:\Users\E\AppData\Local\Programs\Python\Python37\python.exe+[name],然后pip install django
- 进入虚拟activate后就执行django-admin startproject[name]
会自动生成几个配置文件 init setting设置数据库 静态文件位置等相关设置,model设置ROM的映射相关 还有一个mannage.py:一些相关的命令都得使用它比如 python manage.py makemigrations - 因为这个没用Pycharm所以要执行就得 cd python_code/django_env/[name]里面再执行python manage.py runsever就行啦
2.使用pycharm就更方便 - pycharm的自己创建的虚拟环境只需要在创建django时选择你想呀的解释器,最好用一个总的解释器,比如我用的都在D:\Python_code\django_env\Lib\site-packages选择解释器时也都是用的D:\Python_code\django_env\Scripts\python.exe
然后生成一个django项目而且和命令行生成不一样在于多一个templates
不同在于setting 里面的路径问题
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
#指明绝对路径,如果不要这个在下面的'DIRS'就得改
#改为这种
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
- pycharm中,右上角->项目配置->port就改成自己想要的端口号
让局域网中其他电脑访问本机的项目需要让项目运行的时候host为0.0.0.0
如在终端执行 python manage.py runserver 0.0.0.0:8000并且在setting.py的配置ALLOWLD_HOSTS中将本机的ip加进去如 (用ipconfig查看本机ip)
ALLOWED_HOSTS = [' 169.254.157.141']
-然后就是写项目的操作
1视图一般写在app中的views中,也可以叫做url发射器,并且第一个参数永远是request(一个HttpRequest)对象,直接返回字符串是会报错的
视图函数只会返回django.http.request.HttpResposeBase的对象而它的对象有HttpRequest,html等
from django.http import HttpResponse
def book_link(request):
return HttpResponse('书籍列表')
然后需要在url.py中把路径加进去
from book import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/',views.book_link)
]
- 但是如果有两个app和以上就这样
from book import views
from front import views as front_views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/',views.book_link)
path('front/',front_views.index)
]
再访问首页不能进去,是因为django的默认首页为admin新加入了path就失效了改为这样就可以看到首页的
from django.http import HttpResponse
from book import views
def index(request):
return HttpResponse('首页')
urlpatterns = [
path('', index),
path('book/',views.book_link)
]
再访问http://127.0.0.1:8000/book/就能看到放回'书籍列表'文字了
这就是基本的url与视图关系也是开启hello world一样的开端
- 在url.py中设置好参数
urlpatterns = [
path('', index),
path('book/<book_id>',views.book)
]
- 在views中写好视图函数配合参数
def book(request,book_id):
text='你输入的id是 %s' %book_id
return HttpResponse(text)
就能在http://127.0.0.1:8000/book/1看到 '你输入的id是 1',关键是url中的<>必须与views里的参数一致book_id
同理
path('book/<book_id>/<price>',views.book)
def book(request,book_id,price):
text='你输入的id是 %s,价格是%s' %(book_id,price)
return HttpResponse(text)
在http://127.0.0.1:8000/book/1/111中显示:'你输入的id是 1,价格是111'
- 第二种方式就是查询字符串的方式,不需要再url中单独匹配查询字符串部分,只需要在views中用request.GET.get('')方法
url.py
path('book/author/',views.author)
views.py,记住id有单引号不然为错
def author(request):
author_id=request.GET.get('id')
text='作者id是: %s' % author_id
return HttpResponse(text)
然后在http://127.0.0.1:8000/book/author/?id=2(问号不能少)中就是作者id是: 2
- url命名与反转url
先创建两个APP一个book一个font并且添加一个urls.py
在总urls中
from django.urls import path,include
urlpatterns = [
path('',include('font.urls')),
path('book/',include('book.urls')),
]
font的views.py
from django.http import HttpResponse
def index(request):
return HttpResponse('font首页')
def login(request):
return HttpResponse('font登录')
font的urls中
from django.urls import path
from . import views
urlpatterns = [
path('',views.index),
path('login',views.login)
]
book的views中
# Create your views here.
from django.http import HttpResponse
def index(request):
return HttpResponse('book首页')
def login(request):
return HttpResponse('book登录')
book的urls中
from django.urls import path
from . import views
urlpatterns = [
path('',views.index),
path('/login',views.login),
]
千万记住在总的urls里path('book/',include('book.urls'))指向app的book后面一定加/因为浏览器访问时自动加了不加就会错
然后就是在网站访问http://127.0.0.1:8000 为 : font首页
http://127.0.0.1:8000/login 为 : font登录
(这里就是我错的地方没加/访问不到)
http://127.0.0.1:8000/book/ 为 :book首页
访问出错因为上面book的login没有在后面加/改了之后
在book 的 urls中
path('login/',views.login),
访问http://127.0.0.1:8000/book/login/ 为 :book登录
正确
- 命名
path('',views.index,name='index'),
path('login',views.login,name='login')
- 反转
from django.http import redirect,reverse
login_url= reverse('login')
print('='*30)
print('login_url')
return redirect(login_url)
反转的是name所以以后就算改了path前面的浏览器名字一样有用
再引用html基本的网站已经形成了
return render(request,'index.html'
在此基本的
- 在代码的执行中会引用静态模板等html,css,js,png等,这时就 需要考虑路径的问题
1 首先要确保 'django.contrib.staticfiles',已经在INSTALLED_APPS 中,一般创建django都有,如果没有就无法加载,
2 确保有
STATIC_URL = '/static/'
要有这个,如果在浏览器请求静态文件url就需要用这个127.0.0.1/static/xxx.jpng
3 如果在app中创建static并添加静态文件,先把app放在INSTALLED_APPS然后
<img src='/static/logo.jpg/' alt=''>
这样就可以把静态照片加载出来了
都是因为STATIC_URL = '/static/'
如果改为STATIC_URL = '/abc/'
则这样
<img src='/abc/logo.jpg/' alt=''>
也可以
但是为了以后改名字等复杂操作也可以这样,用static便签,不过需要先下载load一下,然后他就会自动在static文件中找叫这个名字的如logo.fpg
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ today|date:'y/m/d' }}
<img src="{% static 'logo.jpg' %}" alt="">
</body>
</html>
当这些都行了。那么问题来了,如果我两个APP都有一个static,而且名字还一样,怎么区分和正确引用呢,可以这样
在static下面又创建一个文件,文件名和app一致这样再引用时要多加这个路径就不会重叠了如
<img src="{% static 'front/logo.jpg' %}" alt="">
这样就区别了
4告别了3的app里面的静态文件,但有些静态文件和app没关系,可以添加一个
STATICFILES_DIRS={
os.path.join(BASE_DIR,'static')
}
base_dirs是配置文件有的绝对路径BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file))),这样static在app里没有找到的就会在外面的static找,就有点像templates
5 templates一般是'DIRS': [os.path.join(BASE_DIR, 'templates')]
也可以这样用直接目录带入
在前端的页面中经常跳转,一般的跳转是
在urls.py中有
path('book/',views.book)
<li><a href='/book/'>读书</a></li>
使用url后
path('book/',views.book,name='book')
<li><a href='{% url 'book' %}'>读书</a></li>
若是要传参的话
path('book/detail/<book_id>/',views.book_detail,name='detail')
def book_detail(request,book_id):
text='图书id:%s'%book_id
<li><a href='{% url 'book' book_id='1'%}'>读书</a></li>
过滤器是模板在传参时方便使用如add,cut等
{{'hello world'|cut:''}}
这样就把所有空白字符剪掉
最好用莫过于date
{{today|date:'y/m/d}}
urls中
path('date/',views.date_views,name='date'),
views中
from datetime import datetime
def date_views(request):
content={
'today': datetime.now()
}
return render(request,'date.html',context=content)
html中
{{ today|date:'y/m/d' }}
最后访问http://127.0.0.1:8000/date/得到 : '19/04/19'
ORM 一种数据库的映射使用可以更加方便,把数据库映射为一个类
放在app的models.py中
from django.db import models
# Create your models here.
class Book(models.Model):
num=models.AutoField(primary_key=True)
name=models.CharField(max_length=100,null=False)
author=models.CharField(max_length=100,null=False)
price=models.FloatField(null=False,default=0)
写完并且连接上数据库后‘就需要映射到数据库中
在终端(虚拟环境下)python manage.py makemigrations
再 python manage.py migrate
之后数据库就有了,表名为app名加class名字 如 front_book
- 连接数据库
因为python3.0以上不支持mysql 需要在项目的_init_中添加
import pymysql
pymysql.install_as_MySQLdb()
并且需要 pip install pymysql
然后在setting 中
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'book_manager',
'USER':'root',
'PASSWORD':'root',
'HOST':'127.0.0.1',
'PORT':'3306',
}
}
连接在app的views中
from django.shortcuts import render,redirect,reverse
from django.db import connection
from django.shortcuts import render,redirect,reverse
from django.db import connection
# Create your views here.
from .models import Book
def get_cursor():
return connection.cursor()
#连接数据库
def index(request):
cursor=get_cursor()
cursor.execute("select num,name,author from book")
books=cursor.fetchall()
#fetchall,fetchone都是获得数据
#并且现在books.o就是num book.1就是name这样
# {
# #两种方法
# cursor.execute("insert into book values(1,'python','yj')")
# books=cursor.fetchall()
# book1=Book(name='西游记',author='吴承恩',price='100')
# book1.save()
return render(request,'index.html',context={'books':books})
在对应的html中#
table>
<thead>
<tr>
<th>序号</th>
<th>书名</th>
<th>作者</th>
</tr>
</thead>
<tbody>
{% for book in books %}
<tr>
<td>{{ forloop.counter }}</td>
#forloop.count显示序号
<td><a href="{% url 'book_detail' book_id=book.0%}">{{ book.0 }}</a></td>
<td>{{ book.1 }}</td>
<td>{{ book.2 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
#
def add_book(request):
if request.method == 'GET':
return render(request, 'add_book.html')
else:
print(request.POST)
name = request.POST.get('name')
author = request.POST.get('author')
cursor = get_cursor()
cursor.execute("insert into book(name,author) values('{0}','{1}') ".format(name, author))
return redirect(reverse('index'))
对应的html为
<form action="." method="post">
<table>
<tbody>
<tr>
<td>书名:</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>作者:</td>
<td><input type="text" name="author"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"></td>
</tr>
</tbody>
</table>
def book_detail(request,book_id):
cursor=get_cursor()
cursor.execute("select num,name,author from book where num=%s" % book_id)
book=cursor.fetchone()
return render(request,'book_detail.html',context={'book':book})
html为
<p>书名:{{ book.1 }}</p>
<p>作者:{{ book.2 }}</p>
<form action="{% url 'book_delete' %}"method="post">
<input type="hidden" name="'book_id" value="{{ book.0 }}">
<input type="submit"value="删除">
</form>
#
def delete_book(request):
if request.method=='post':
book_id=request.POST.get('book_id')
cursor=get_cursor()
cursor.execute('delete from book where num=%s' %book_id)
return redirect(reverse('index'))
else:
raise RuntimeError('删除错误')
ORM映射流程
1创建一个数据库命名[name]
2在setting中的databases设置相关参数
3创建一个app python manage.py startapp [name]
4在app中的models连接数据库from django.db import models并且创建类class book(models.Model):
5映射到数据库python manange.py makemigrations
python manage.py migrate移植到数据库中
6再就是urls和views的操作
在views操作时记得加上
from .models import book
其他操作参考点击这里 url和views
7一些基本操作
增
book1=book(name='三国演义',author='罗贯中',price=100)
book1.save()
查询(默认的查询都是通过objects查询)
pk=primary key就不用管主键到底叫什么
book_1=book.objects.get(pk=1)
print(book_1)
就会在终端打印出了 book object [1]
如果想要打印的时候好看就在models中的book类里写
class Book(models.Model):
num=models.AutoField(primary_key=True)
name=models.CharField(max_length=100,null=False)
author=models.CharField(max_length=100,null=False)
price=models.FloatField(null=False,default=0)
都是在这个类中写的
def _str_(self):
return print('<Book:{{name},{author},{price}}>'.format(name=self.name,author=self.author,price=self.price))
还可以修改表名
class Meta:
db_table = '[name]'
#
在django的模型model中都继承django.db.models.Model类
字段必须是models.XXXField类型
Meta类的db_table为映射数据表的名字如果没有就默认应用名_模型名
然后再执行在终端返回的就是
:三国演义,罗贯中,100这样的形式了
- 也可以
books=book.objects.filter(name=’西游记‘)(还可以这样books=book.objects.filter(name=’西游记‘).frist())
return render(request,'book_detail.html',context={'book':books})
filter是一个过滤器把所有西游记的都返回而render的context也是返回传过区内容
删除
首先查找到对应值在delete()
books=book.objects.get(pk=1)
books.delete()
修改
books=book.objects.get(pk=1)
books.price=200
books.save()
8 ORM的外键 ForeignKey
定义模型如下
from django.db import models
class User(models.Model):
name = models.CharField(max_length=100)
password = models.CharField(max_length=100)
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
author= models.ForeignKey('User',on_delete=models.CASCADE
操作如下
article=Article(title='asd',content='asfa')
user=User(name='sfa',password='sada')
article.author=user
article.save()
9 使用exact精确查找
article=Article.objects.get(id__exact=15)
article1=Article.objects.filter(id__exact=1)
终端返回的是filter 为一个QuerySet
10聚合函数
需要放在支持聚合函数的方法中比如:aggregate
from django.db.models import Avg
result=Book.objects.aggregate(Avg('price))
Student.objects.annotate(score_avg=Avg('score__number')).filter(score_avg__gt=60)
annotate 方法在底层调用了数据库的数据聚合函数,annotate可以做一个整合汇总的作用
- a表单
创建一个forms.py
from django import forms
class MesssageBoardForm(forms.Form):
title = forms.CharField(max_length=100,min_length=2,label='标题',error_messages={'min_length':'不得少于一个字符'})
coutent =forms.CharField(widget=forms.Textarea,label='内容')
# 控件
email=forms.EmailField(label='邮箱')
reply=forms.BooleanField(required=False,label='是否回复')
还可以增加一些选项如
kind_chioce=(
('python','python')
('java',java')
('c','c')
)
username=models.CharField(max_length=100)
kind=models.CharField(max_length=100,choices=kend_chioce,default=king_chioce[0])
#这样就可以形成选择填表,default是默认显示
views视图中
from .forms import MesssageBoardForm
class IndexView(View):
def get(self,request):
form = MesssageBoardForm()
return render(request,'liuyan.html',context={'form':form})
urls中
``
path('liuyan/',views.IndexView.as_view(),name='liuyan'),
liuyan.html中
<body>
<form action=""method="post"></form>
<table>
{{ form.as_table }}
<tr>
<td></td>
<td><input type="submit" value="提交"> </td>
</tr>
</table>
</body>
项目介绍和过程
1安装nvm,管理node
下载地址https://github.com/coreybutler/nvm-windows/releases
并添加进入环境变量
2 nvm install node下载最新版本node
nvm install [virsion]下载相应版本
nvm use [virsion]用相应版本
nvm uninstall[virsion]删除相应版本
cmd执行下面就会下载
nvm install 6.4.0
版本后会自动安装相应版本的npm,npm就是用来管理这些包的6.4.0对应10.3
3 安装包
先使用nvm use 6.4.0
本地安装
npm install express
执行后安装包放在node_modules下面即D:\nvm\nvm\v6.4.0\node_modules
可以通过require()引入本地包
express包还带有许多其他包
全局安装
npm install express -g
卸载包就是
npm uninstall [package]
如 npm uninstall express卸载express
npm uninstall express -g
还有更新和搜索包等
npm update [包名字]如 npm update express
npm search [package]
4 在本地中,将安装的包的写的文件放在一个文件夹中方便发送给别人你的项目
并且在你要写项目的文件夹目录cmd 中
nmp init
比如我的就是D:\nvm_demo\demo_1
使它生成一个package.json它记录你使用的包并方便看和管理,毕竟node_modules那么多包不是都要用,安装时参数一路enter最后yes就 ok了
5 安装一个前端自动化过程的包gulp
需要全局和本地都安装
npm install gulp --save.dev
--save。Dev是将安装的包放在package.josn下的devDependencies依赖中
npm install gulp -g 全局
6以后就可以通过npm install直接安装package.json里devDependencies有的包了,也就是项目用的包 ,所以发送项目时只用发这个package.json不用node_modules
7输出hello world过程
总项目文件 demo_1
要有node_modules放包的地方即
npm uninstall express
还需要一个pcakage.json即nmp init
在用gulp时才能调用包
在demo_1总下创建一个js
var gulp = require("gulp")
gulp.task("greet",function(){
console.log("hello world");
});
在终端 Cd到该项目文件再
gulp greet输出hello world