# 1 # li = ['a', 'b', 'c', 'd','e'] # print(li[10:]) #[] 不报错 # 2 # 这不是True或False,而是值 # 另外,优先级 not > and > or # print(1 and 2 or 3) # 2 # print(2 and 0 or 1) # 1 # print(1 or 2 and 0) # 1 # print(2 or 0 and 1) # 2 # print(not 1 and 0) # 3 # x1 = 'a' # x2 = 'b' # list1 = [1,2] # list2 = [3,4] # list3 = [5,6] # list4 = [x1, x2, list1, list2, list3] # ['a', 'b', [1,2], [3,4], [5,6]] # # ### 考察对"引用"的理解 # # x1 = 'c' # x1 = 'c' # list1[0] = 7 # list1 = [7,2] # print(list4) # ['a', 'b', [7,2], [3,4], [5,6]] # # list4[1] = 'd' # ['a', 'd', [7,2], [3,4], [5,6]] # print(x2) # 'b' # # list4[3] = [8,9] # ['a', 'd', [7,2], [8,9], [5,6]] # print(list2) # [3,4], # # 也就是修改list4的引用,原来指向list2,现在指向[8,9],所以对list2没影响。 # # list4[4][1] = 10 # ['a', 'd', [7,2], [8,9], [5,10]] # print(list3) # [5,6], # # 这个做错了,list4[4]还是指向list3,修改list4[4][1]已经影响到了list3。 # print(list4) # 4 # 下面是否有错: # def calc(a, b, c, d=1, e=2): # return (a + b) * (c - d) + e # # print(calc(1, 2, 3, d=5, 4)) #关键字参数一定要放到位置参数后面 # 5 # 互换 # x = [0,1] # i = 0 # i,x[i] = 1,2 # print(x) # [0,2] # a = 1 # b = 2 # a, b = b, a # print(a,b)
Django:
MVC:model、view、controller
MTV:model、template、view
django-admin startproject mysite
python manage.py startapp myapp (mysite目录下执行)
python manage.py runserver 8080 (默认8000)
添加模板:
根目录下创建文件夹templates(名字任意,只是需要与settings.py中对应)
settings.py中设置'DIRS': [os.path.join(BASE_DIR, 'templates')],
给html文件传参:
1 def retok(req): 2 date = datetime.datetime.now() 3 return render(req, 'ret.html', {'date': date}) # django没有'**'
post方法403 Forbidden:
中间件,'django.middleware.csrf.CsrfViewMiddleware',
请求方法大写:
1 def info(req): 2 if req.method == 'POST': # 必须大写 3 print(req.POST.get('name')) # 接收请求信息 4 return HttpResponse('ok') 5 return render(req, 'info.html')
模板jinjia2取值:
无论列表还是字典都可用 '.'
1 {{info_list.0}} 2 <table border="1"> 3 {% for info in info_list %} 4 <td>{{ info.name }}</td> 5 <td>{{ info.age }}</td> 6 {% endfor %} 7 </table>
model模块:
创建model之后,初始化之前需要在settings.py中配置app,
1 INSTALLED_APPS = [ 2 ... 3 'myapp' 4 ]
python manage.py makemigrations
python manage.py migrate
一个pycharm社区版引起的血案:
执行数据库初始化之后,怎么也找不到database插件,原因是pycharm社区版只支持纯python开发,专业版才支持HTML、JS、SQL。
sqlite3表中插入数据:
1 # model.py 2 3 class Info(models.Model): 4 name = models.CharField(max_length=10) 5 age = models.CharField(max_length=10) 6 pwd = models.CharField(max_length=10) 9 10 # views.py 11 12 Info.objects.create( 13 name=n, 14 age=a, 15 pwd=p, 16 )
配置静态文件,以jQuery为例:
1 # settings.py 2 3 STATIC_URL = '/yangxl/' # html中寻找静态文件用的是该路径 4 5 STATICFILES_DIRS = [ 6 (os.path.join(BASE_DIR, 'static')), # 文件名任意, 但逗号不能丢 7 ] 8 9 10 # .html 11 12 <h1>旺财</h1> 13 <script src="/yangxl/jquery-3.4.1.min.js"></script> 14 <script> 15 $('h1').css('color', 'red') 16 </script>
路由匹配:path、re_path,
通过正则分组给视图函数传参
1 # urls.py 2 3 from django.urls import path, re_path 4 from myapp import views 5 6 urlpatterns = [ 7 path('admin/', admin.site.urls), 8 re_path(r'info/([0-9]{3})', views.info), 9 ] 10 11 12 # views.py 13 14 def info(req, n): 15 return HttpResponse(n)
关键字参数,
1 # urls.py 2 3 re_path(r'info/(?P<num1>[0-9]{3})/(?P<num2>[0-9])', views.info), 4 5 6 # views.py 7 8 def info(req, num1, num2): 9 return HttpResponse(num1+num2) # 字符串拼接
传入一个与路径无关的参数,
1 re_path(r'info/(?P<num1>[0-9]{3})/(?P<num2>[0-9])', views.info, {'environ': 'yangxl'}),
别名name,当访问url发生变化时,不需修改form、a等二次访问的url,
1 # urls.py 2 3 re_path(r'info', views.info, name='genesis'), 4 5 6 # .html 7 8 <form action="{% url 'genesis' %}" method="post"> 9 <input type="text" name="user"> 10 <input type="password" name="pwd"> 11 <input type="submit" value="提交"> 12 </form>
include,路由分发,
1 # urls.py 2 3 from django.urls import path, include 4 5 urlpatterns = [ 6 ... 7 path('backend', include('backend.urls')), 8 ] 9 10 # app.urls.py 11 12 from django.urls import path, re_path 13 from backend import views 14 15 urlpatterns = [ 16 re_path('info', views.info, name='genesis'), 17 ] 18 19 访问:http://127.0.0.1:8080/backend/info
req为WSGIRequest对象,
from django.core.handlers.wsgi import WSGIRequest
from django.http import HttpRequest
返回一个HttpResponse对象,
from django.http import HttpResponse
render、render_to_response、redirect、HttpResponse
django命令行模式:
1 python manage.py shell 2 3 In [1]: from django.template import Template, Context 4 5 In [2]: t = Template('hello{{name}}') 6 7 In [3]: c = Context({'name': 'wangcai'}) 8 9 In [4]: t.render(c) 10 Out[4]: 'hellowangcai'
关于import,无论是在mysite.urls.py还是backend.urls.py都能导入views (from backend import views),因为环境变量sys.path[0]为项目根目录。
模板语法提示功能:
Settings -- Editor -- Inspections -- Django、python都选上。
forloop.counter、forloop.counter0:
1 {% for i in l%} 2 <p>{{ forloop.counter0 }}: {{ i }}</p> 3 {% endfor %}
filter:'|'
1 {{ s }} 2 {{ s|upper }} 3 {{ s|capfirst }}
autoescape:
效果等同于{{ s|safe }}
1 def info(req): 2 s = '<a href="#">中南海</a>' 3 return render(req, 'index.html', {'s': s}) 4 5 {% autoescape off %} # 结果渲染,意会!! 6 {{ s }} 7 {% endautoescape %}
{% csrf_token %}:
解决post方法遇到的403 Forbidden问题,
1 # .html 2 <form action="info" method="post"> 3 <input type="text" name="user"> 4 <input type="pwd" name="pwd"> 5 <input type="submit" value="submit"> 6 {% csrf_token %} 7 </form> 8 9 10 提交表单时多加一个input标签, 11 <input name="csrfmiddlewaretoken" type="hidden" value="5i5jCtZj8PRpxha7U6Tct2lxEvXyTUQ0iIaswDqRhXNI2SGXjNoWyMYiMDlNm3B4">
不渲染,{{ s }}
1 {% verbatim %} 2 {{ s }} 3 {% endverbatim %} 4 5 结果:{{ s }}
自定制模板函数:
必须在已注册app中创建名为templatetags的文件夹,文件夹下的文件名任意,(已注册是指在settings.INSTALLED_APPS中)。
1 # views.py 2 3 def info(req): 4 s = 'wangcai' 5 return render(req, 'index.html', {'s': s}) 6 7 # templatetags.customs.py 8 9 from django import template 10 11 register = template.Library() # register 12 13 @register.simple_tag # simple_tag 14 def use_salt(s): 15 return 'hello, ' + s 16 17 # .html 18 19 {% load customs %} # 在使用之前导入模块 20 21 {% use_salt s %} # 去导入的模块customs.py中获取函数并执行
自定制过滤器:只有装饰器和调用方式不同,
1 # customs.py 2 3 @register.filter 4 def ... 5 6 # .html 7 8 {{ s|use_salt }}
二者加参数,
1 {% use_salt s 'come here' %} 2 {{ s|use_salt:', come here' }}
extends:在母版中定义共同的部分和一个盒子,在子模版中导入母版并用各自的内容填充盒子
1 # base.html 2 3 <!DOCTYPE html> 4 <html lang="en"> 5 <head> 6 <meta charset="UTF-8"> 7 <title>Title</title> 8 <style> 9 .page-header{ 10 height: 50px; 11 background-color: rebeccapurple; 12 } 13 .page-body .menu{ 14 height: 500px; 15 background-color: antiquewhite; 16 float: left; 17 20%; 18 } 19 .page-body .content{ 20 height: 500px; 21 background-color: cornflowerblue; 22 float: left; 23 80%; 24 } 25 .page-footer{ 26 height: 50px; 27 background-color: darkcyan; 28 clear: both; 29 } 30 </style> 31 </head> 32 <body> 33 <div> 34 <div class="page-header"></div> 35 <div class="page-body"> 36 <div class="menu"> 37 <a href="/order">订单</a> 38 <a href="/shop">购物</a> 39 </div> 40 {% block aigo %} # 盒子 41 42 {% endblock %} 43 </div> 44 <div class="page-footer"></div> 45 </div> 46 </body> 47 </html> 48 49 # order.html 50 51 {% extends 'base.html' %} # 导入母版 52 53 {% block aigo %} # 填充盒子 54 <div class="content"> 55 订单啊 56 </div> 57 {% endblock %}
model、ORM:
单表操作:
1 # 增 2 user = {'name': 'grute', 'age': 3, 'pwd': 123} 3 models.Info.objects.create(**user) 4 5 # 查 6 users = models.Info.objects.all() 7 users = models.Info.objects.filter(id__gte=1) # <QuerySet []>, 双下划线, 可切片操作 8 users = models.Info.objects.get(id=1) # 找不到数据会报错 9 users = models.Info.objects.all().values('id', 'name') # 特定字段 10 users = models.Info.objects.exclude(id=3) # 反向查找 11 users = models.Info.objects.exclude(id=3).count() # 计数 12 users = models.Info.objects.filter(id=2).last() 13 users = models.Info.objects.filter(id=2).first() 14 users = models.Info.objects.filter(id=1).exists() # 是否存在该条数据, bool, 惰性机制(比如, 还有迭代器) 15 print('uu', users) 16 17 # 改 18 models.Info.objects.filter(id=2).update(name='wangcai', age=16) # update是QuerySet的方法 19 20 # 删 21 models.Info.objects.filter(id=1).delete() 22 23 # 排序 24 users = models.Info.objects.order_by('-id') # 倒序 25 print('uu', users)
联表操作:一对一、多对一、多对多
1 # models.py 2 3 class Book(models.Model): 4 title = models.CharField(max_length=64) 5 price = models.IntegerField() 6 color = models.CharField(max_length=64) 7 page_num = models.IntegerField(null=True) 8 publisher = models.ForeignKey('Publisher', models.CASCADE) 9 # 接受对象 10 author = models.ManyToManyField('Author') # 多对多, 放到Author中也可 11 12 def __str__(self): 13 return self.title 14 15 16 class Publisher(models.Model): 17 name = models.CharField(max_length=64) 18 city = models.CharField(max_length=63) 19 20 def __str__(self): 21 return self.name 22 23 24 class Author(models.Model): 25 name = models.CharField(max_length=30) 26 27 def __str__(self): 28 return self.name 29 35 # views.py 36 37 def info(req): 38 # models.Publisher.objects.create( 39 # name='新东方技工学校', 40 # city='济南', 41 # ) 42 43 # models.Author.objects.create( 44 # name='紫英' 45 # ) 46 47 # pubs = models.Publisher.objects.filter(city='济南') 48 # author1 = models.Author.objects.get(id=2) 49 # author2 = models.Author.objects.get(id=3) 50 # print('aa', author2) 51 52 # book = models.Book.objects.create( 53 # title='挖掘机切磋技法', 54 # price=32, 55 # color='blue3', 56 # # 多对一, 二选一 57 # # publisher_id=2, # id 58 # publisher=pubs[0] # 对象, 推荐 59 # ) 60 # 多对多 61 # 正向查询 62 # book = models.Book.objects.filter(id=3)[0] 63 # authors = models.Author.objects.filter(id=3) 64 # book.author.remove(*authors) # 类似集合操作,删除为remove 65 # 反向查询 66 author = models.Author.objects.filter(id=3)[0] 67 books = models.Book.objects.filter(id__gte=2) 68 author.book_set.add(*books) 69 70 return HttpResponse('ok')
多对一查找:
1 # 多对一 2 # 正查 3 book = models.Book.objects.filter(title='挖掘机切磋技法')[0] 4 print(book.publisher.name) 5 # 反查 6 pubs = models.Publisher.objects.filter(name='新东方技工学校')[0] 7 print(pubs.book_set.values('title')) # QuerySet 8 print(pubs.book_set.values('title').distinct()) # 根据title去重
手动创建第三张表,这样就不需创建多对多字段了
1 # models.py 2 3 class Book2Author(models.Model): 4 book = models.ForeignKey('Book', models.CASCADE) 5 author = models.ForeignKey('Author', models.CASCADE) 6 7 class Meta: 8 unique_together = ['book', 'author'] 9 10 # views.py 11 # 直接插入数据 12 author = models.Author.objects.filter(id=3)[0] 13 book = models.Book.objects.filter(id__gte=2)[0] 14 models.Book2Author.objects.create( 15 book=book, 16 author=author 17 )
一对一:
1 # models.py 2 3 # publisher = models.ForeignKey('Publisher', models.CASCADE, unique=True) 4 publisher = models.OneToOneField('Publisher', on_delete=models.CASCADE) # 推荐
双下划线,条件查询:
1 # 单表查询 2 # book = models.Book.objects.filter(id__range=[4, 7]) 3 # book = models.Book.objects.filter(id__in=[3, 5]) 4 # book = models.Book.objects.filter(title__contains='技法') 5 # book = models.Book.objects.filter(title__icontains='技法') # 不区分大小写 6 # book = models.Book.objects.filter(title__startswith='酸菜') 7 8 # 正向多对一 9 # books = models.Book.objects.filter(title='挖掘机切磋技法').values('id') 10 # books = models.Book.objects.filter(title='挖掘机切磋技法').values('publisher__city') 11 12 # 正向多对多 13 # books = models.Book.objects.filter(author__name='菱纱').values('title') 14 15 # 反向一对多 16 # pubs = models.Publisher.objects.filter(book__title='挖掘机切磋技法').values('name') 17 # pubs = models.Publisher.objects.filter(book__title='酸菜鱼攻略').values('book__author__name') 18 19 # 反向多对多 20 authr = models.Author.objects.filter(book__title='挖掘机切磋技法').values('name') 21 print(authr)
django日志配置,
可用于验证filter等的惰性机制(只有使用filter的返回结果时真正执行sql语句)
1 LOGGING = { 2 'version': 1, 3 'disable_existing_loggers': False, 4 'handlers': { 5 'console': { 6 'level': 'DEBUG', 7 'class': 'logging.StreamHandler', 8 }, 9 }, 10 'loggers': { 11 'django.db.backends': { 12 'handlers': ['console'], 13 'propagate': True, 14 'level': 'DEBUG', 15 }, 16 } 17 }
缓存机制:
1 pubs = models.Publisher.objects.filter(city='成都') 2 for p in pubs: 3 print(p) 4 5 # pubs.update(city='重庆') 6 7 for p in pubs: # 当再次执行遍历操作且遍历数据未改变时, 数据是从缓存中获取的, 不会重复执行sql查询 8 print(p)
以下两条不会把数据加载到缓存,
1 pubs = models.Publisher.objects.filter(city='重庆').exists() 2 pubs = models.Publisher.objects.filter(city='成都').iterator()
聚合查询、分组查询,
aggregate和annotate:
1 from django.db.models import Avg, Min, Max, Sum 2 3 # 查询菱纱出的书的均价 4 # books = models.Book.objects.filter(author__name='菱纱').aggregate(Avg('price')) # 聚合查询 5 6 # 查询各个作者出的书的总价格 7 # books = models.Book.objects.values('author__name') 8 # books = models.Book.objects.values('author__name').annotate(Sum('price')) # annotate对作者分组(可重复), 然后按价格聚合 9 10 # 查询各个出版社最便宜的书的价格 11 # books = models.Book.objects.values('publisher').annotate(Min('price'))
F和Q查询:
1 from django.db.models import F, Q 2 3 # 把菱纱出的书的价格提高100 4 books = models.Book.objects.filter(author__name='菱纱').update(price=F('price')+100) # 返回更新数据的个数 5 6 # &、|、~ 7 books = models.Book.objects.filter(Q(id=3) | Q(price__lt=100)) # 或关系 8 books = models.Book.objects.filter(Q(id__gte=5) & Q(price__lt=150), color='green') # 关键字参数放在Q后面 9
Admin:
python manage.py createsuperuser
汉化:
1 # LANGUAGE_CODE = 'en-us' 2 LANGUAGE_CODE = 'zh-Hans'
指定表字段,verbose_name,后加的不需数据库初始化
1 title = models.CharField(max_length=64, verbose_name='书名')
设置某字段只读,editable
1 title = models.CharField(max_length=64, verbose_name='书名', editable=False)
django连接mysql:
1 ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 2 0.9.3. 3 # django.db.backends.mysql.base.py 4 5 py3中编码也有问题 6 # django.db.backends.mysql.operations.py
1 # settings.py 2 3 DATABASES = { 4 'default': { 5 # 'ENGINE': 'django.db.backends.sqlite3', 6 # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 7 8 'ENGINE': 'django.db.backends.mysql', 9 'HOST': '127.0.0.1', 10 'PORT': '', 11 'USER': 'root', 12 'PASSWORD': '', 13 'NAME': 'wangcai', 14 } 15 } 16 17 # app下的__init__.py 18 19 import pymysql 20 pymysql.install_as_MySQLdb() 21 22 23 # 初始化 24 python manage.py makemigrations 25 python manage.py migrate 26 27 # django-database插件显示mysql,这个因为时区问题无法连接,懒得配置了。。
django-database插件显示mysql,这个因为时区不匹配而无法连接,需要做以下配置,
1 # 修改mysql时区为东八区 2 3 show variables like '%time_zone%'; 4 set global time_zone='+8:00'; 5 flush privileges;
非常秀的博客: