python中的细节


# 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;

非常秀的博客:

https://www.cnblogs.com/yuanchenqi/articles/6083427.html

原文地址:https://www.cnblogs.com/yangxiaoling/p/6997709.html