Django之 Models组件
本节内容
- 路由系统
- models模型
- admin
- views视图
- template模板
引子
讲django的models之前, 先来想一想, 让你通过django操作数据库,你怎么做? 做苦思冥想,可能会这样写。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import pymysqldef index(request): # 创建连接 conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='alex123', db='luffy_dev') # 创建游标 cursor = conn.cursor() cursor.execute("select username,email,mobile from web_account") data_set = cursor.fetchall() cursor.close() conn.close() return HttpResponse(data_set) |
很方便就实现了从数据库里取数据,事实上,很多人确实就是这么做的。但这样做会带来2个问题
- SQL注入危险,因为有的时候你操作数据库的语句不是写死在代码里的,而是通过前端传参数拼接的,这就给黑客有了可趁之机,通过拼接参数实现sql注入。
- 语句跟代码揉在一起了,增加后续维护成本
那怎么办呢?ORM提供了新思路。
什么是ORM呢?
对象关系映射(Object Relational Mapping),它的实质就是将关系数据(库)中的业务数据用对象的形式表示出来,并通过面向对象(Object-Oriented)的方式将这些对象组织起来,实现系统业务逻辑的过程。
在ORM过程中最重要的概念是映射(Mapping),通过这种映射可以使业务对象与数据库分离。从面向对象来说,数据库不应该和业务逻辑绑定到一起,ORM则起到这样的分离作用,使数据库层透明,开发人员真正的面向对象。
上面的解释有点蒙蔽对不?其实你只需要抓住2个关键词, “映射” 和 “对象”,就能知道orm是什么干什么的了。
- 映射(Mapping) —— 把表结构映射成类
- 对象 —— 像操作类对象一样,操作数据库里的数据
映射
看下面的图,就是直观的例子,把右边的表结构映射成了左边的类

Sql语句到对象
ORM可以使你不用再写原生SQL, 而是像操作对象一样就可以实现对表里数据的增删改查

好棒棒,妈妈再也不用逼你写原生sql啦!
但是不要开心太早,ORM确实提高了开发效率,并且降低了数据操作与代码之间的耦合,不过有利就有弊,我们总结一下orm的优缺点。
优点:
- 实现了代码与数据操作的解耦合
- 不需自己写原生sql, 提高开发效率
- 防止SQL注入, 通过对象操作的方式,默认就是防止sql注入的。
缺点:
- 牺牲性能, 对象到原生SQL势必会有转换消耗,对性能有一定的影响
- 复杂语句力不从心, 一些复杂的sql语句,用orm对象操作的方式很难实现,就还得用原生sql
讲Django为什么说ORM? 哈, 好啦,是时候该引出主角啦,因为Django的models基于架构ORM实现的。
Models模型
Django 的models把数据库表结构映射成了一个个的类, 表里的每个字段就是类的属性。我们都知道数据库有很多字段类型,int,float,char等, Django的models类针对不同的字段也设置了不同的类属性。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
AutoField #An IntegerField that automatically increments according to available IDsBigAutoField #A 64-bit integer, guaranteed to fit numbers from 1 to 9223372036854775807.BigIntegerField #-9223372036854775808 to 9223372036854775807BinaryField #A field to store raw binary data. It only supports bytes assignmentBooleanField CharFieldDateField #e.g 2019-04-27DateTimeField #e.g 2019-04-27 17:53:21DecimalField DurationField #storing periods of time ,e.g [DD] [HH:[MM:]]ss[.uuuuuu]"EmailFieldFileField #存储文件FloatFieldImageField #Inherits all attributes and methods from FileField, but also validates that the uploaded object is a valid image.IntegerFieldGenericIPAddressField #IP地址,支持ipv4NullBooleanField #Like a BooleanField, but allows NULL as one of the optionsPositiveIntegerField #Like an IntegerField, but must be either positive or zero (0). Values from 0 to 2147483647PositiveSmallIntegerField #only allows positive values from 0 to 32767SlugField # A slug is a short label for something, containing only letters, numbers, underscores or hyphens.SmallIntegerFieldTextField #A large text field.TimeField #A time, represented in Python by a datetime.time instance.URLFieldUUIDField #A field for storing universally unique identifiers. Uses Python’s UUID class. |
除了普通的表字段,针对外键也有映射
|
1
2
3
4
|
ForeignKey # 外键关联ManyToManyField #多对多OneToOneField # 1对1 |
好啦,接下来就用django的orm来设计一个博客表。
需求
- 每个用户有自己的账户信息
- 用户可以发文章
- 文章可以打多个标签
根据需求,我们设计3张表

注意Article表和Tag表是属于多对多关系,什么是多对多?即一个文章有多个标签,一个标签又可以属于多个文章。
比如上图的Article表中id为3的文章 ,它的标签是4,26, 即投资、大文娱、社交, 你看“投资”这个标签同时还属于文章2。 这就是多对多关系 , 即many to many .
那这种多对多的关系如何在表中存储呢?难道真的像上图中一样,在Article表中加个tags字段,关联Tag表里的多条数据,通过逗号区分?
这倒确实是个解决办法。但是也有问题,一个字段里存多条纪录的id,就没办法做查询优化了。比如不能做索引等。
所以若想实现多对多关系的高效存储+查询优化,可以在Article and Tag表之间再搞出一张表。

这样是不是就实现了多对多关联?
yes, 没错, django也是这么做的, django 有个专门的字段,叫ManyToManyField, 就是用来实现多对多关联的,它会自动生成一个如上图一样的第3张表来存储多对多关系。
正式的表结构
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
from django.db import models# Create your models here.class Account(models.Model): username = models.CharField(max_length=64,unique=True) email = models.EmailField() password = models.CharField(max_length=128) register_date = models.DateTimeField("注册日期",auto_now_add=True) signature = models.CharField(verbose_name="签名",max_length=128,blank=True,null=True)class Article(models.Model): """文章表""" title = models.CharField(max_length=255,unique=True) content = models.TextField("文章内容") account = models.ForeignKey("Account",verbose_name="作者",on_delete=models.CASCADE) tags = models.ManyToManyField("Tag",blank=True) pub_date = models.DateTimeField() read_count = models.IntegerField(default=0)class Tag(models.Model): """文章标签表""" name = models.CharField(max_length=64,unique=True) date = models.DateTimeField(auto_now_add=True) |
我们发现,每个字段其实都是一个独立的对象,一张表其实是很多类的组合。
上面好多字段里还跟了些参数,我们来看以下常用的:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
null #If True, Django will store empty values as NULL in the database. Default is False.blank #If True, the field is allowed to be blank. Default is False.db_column #The name of the database column to use for this field. If this isn’t given, Django will use the field’s name.db_index #If True, a database index will be created for this field.default #The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.editable # django admin中用,后面讲help_text # django admin中用,后面讲primary_key # If True, this field is the primary key for the model.unique #If True, this field must be unique throughout the tableunique_for_date #Set this to the name of a DateField or DateTimeField to require that this field be unique for the value of the date field. For example, if you have a field title that has unique_for_date="pub_date", then Django wouldn’t allow the entry of two records with the same title and pub_date.unique_for_month #Like unique_for_date, but requires the field to be unique with respect to the month.unique_for_year verbose_name #A human-readable name for the field. If the verbose name isn’t given, Django will automatically create it using the field’s attribute name |
还有几个特殊的字段属性需要单独介绍下
choices
An iterable (e.g., a list or tuple) consisting itself of iterables of exactly two items (e.g. [(A, B), (A, B) ...]) to use as choices for this field.
The first element in each tuple is the actual value to be set on the model, and the second element is the human-readable name.
|
1
2
3
4
5
6
7
8
9
10
11
12
|
class Student(models.Model): YEAR_IN_SCHOOL_CHOICES = ( ('FR', 'Freshman'), ('SO', 'Sophomore'), ('JR', 'Junior'), ('SR', 'Senior'), ) year_in_school = models.CharField( max_length=2, choices=YEAR_IN_SCHOOL_CHOICES, default=FRESHMAN, ) |
ForeignKey.on_delete
当一条记录关联的外键纪录被删除时,django 也会根据外键关联限制的配置来决定如何处理当前这条纪录。举例,如果你有个可以为null的外键关联,并且你想在本纪录关联的数据被删除时,把当前纪录的关联字段设为null,那就配置如下
|
1
2
3
4
5
6
|
user = models.ForeignKey( User, on_delete=models.SET_NULL, blank=True, null=True,) |
这个on_delete就是决定在关联对象被删除时,如何处理当前纪录的,常用的参数如下:
- CASCADE——Cascade deletes. Django emulates the behavior of the SQL constraint ON DELETE CASCADE and also deletes the object containing the ForeignKey.
- PROTECT——Prevent deletion of the referenced object by raising ProtectedError, a subclass of django.db.IntegrityError.
- SET_NULL——Set the ForeignKey null; this is only possible if null is True.
- SET_DEFAULT——Set the ForeignKey to its default value; a default for the ForeignKey must be set.
配置Django数据库连接信息
Django支持多种数据库,Sqlite、Mysql、Oracle、PostgreSQL,默认的是小型文件数据库Sqlite
|
1
2
3
4
5
6
|
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), }} |
咱们是干大事的人,怎么也得用个Mysql呀, 改成mysql 也so easy.
|
1
2
3
4
5
6
7
8
9
10
|
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'my_db', 'USER': 'mydatabaseuser', 'PASSWORD': 'mypassword', 'HOST': '127.0.0.1', 'PORT': '3306', }} |
不过注意,python3 连接mysql的得使用pymysql,MysqlDB模块300年没更新了,但django默认调用的还是MySQLdb, so pymysql有个功能可以让django以为是用了MySQLdb. 即在项目目录下的__init__.py中加上句代码就好
|
1
2
3
|
import pymysqlpymysql.install_as_MySQLdb() |
不加的话,一会连接数据时会报错噢 。
同步数据库
你在ORM定义的表结构如何同步到真实的数据库里呢? 只需2条命令。但django只能帮你自动创建表,数据库本身还是得你自己来。
|
1
|
create database my_db charset utf8; |
好了,可以同步了,说好只需2步。
1. 生成同步文件, django自带一个专门的工具叫migrations, 负责把你的orm表转成实际的表结构,它不旦可以帮自动创建表,对表结构的修改,比如增删改字段、改字段属性等也都能自动同步。只需通过下面神奇的命令。
|
1
|
python manage.py makemigrations |
不出意外的话,会显示类似以下信息
|
1
2
3
4
5
6
7
|
$ python manage.py makemigrationsMigrations for 'app01': app01/migrations/0001_initial.py - Create model Account - Create model Article - Create model Tag - Add field tags to article |
此时你会发现,你的app下的migrations目录里多了一个0001_initial.py的文件 ,这个文件就是因为你这条命令而创建的,migrations工具就会根据这个文件来创建数据库里的表。
2. 同步到数据
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
$ python manage.py migrateOperations to perform: Apply all migrations: admin, app01, auth, contenttypes, sessionsRunning migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying app01.0001_initial... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying sessions.0001_initial... OK(venv_django2) Alexs-MacBook-Pro:mysite alex$ |
此时登录你的数据库,会发现创建了好多张表
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
mysql> show tables;+----------------------------+| Tables_in_luffy_dev2 |+----------------------------+| app01_account | #对应Account表| app01_article | #对应Article表| app01_article_tags | #自动创建的Article to Tag的多对多关联表| app01_tag | #对应Tag表| auth_group | #下面这些,都是django 自带的表,这个是自动用户系统的组| auth_group_permissions | #自带的组与权限的多对多关联表| auth_permission | #自带权限表| auth_user | #用户表| auth_user_groups || auth_user_user_permissions || django_admin_log | #现在你的无法理解 | django_content_type | #现在你的无法理解| django_migrations | #纪录migartions工具同步纪录的表| django_session | #现在你的无法理解+----------------------------+14 rows in set (0.00 sec) |
好啦,表结构也有了,我们可以往里面插数据啦。
之前说好的是可以不用SQL语句的,一点不骗你。
用orm对表数据进行增删改查
先进入已经连接好数据库的django python环境
|
1
2
3
4
5
6
7
|
(venv_django2) Alexs-MacBook-Pro:mysite alex$ python manage.py shell Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 26 2016, 10:47:25)[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwinType "help", "copyright", "credits" or "license" for more information.(InteractiveConsole)>>>>>> from app01 import models |
创建
创建数据简单的令人发指

查

filter 支持很多的过滤条件,我们来看下:
contains
包含,相当于sql的like条件
|
1
|
Entry.objects.get(headline__contains='Lennon') |
SQL equivalent:
|
1
|
SELECT ... WHERE headline LIKE '%Lennon%'; |
Note this will match the headline 'Lennon honored today' but not 'lennon honored today'.
icontains 大小写不敏感
in
In a given iterable; often a list, tuple, or queryset.
|
1
|
Entry.objects.filter(id__in=[1, 3, 4]) |
SQL equivalent:
|
1
|
SELECT ... WHERE id IN (1, 3, 4); |
You can also use a queryset to dynamically evaluate the list of values instead of providing a list of literal values:
|
1
2
|
inner_qs = Blog.objects.filter(name__contains='Cheddar')entries = Entry.objects.filter(blog__in=inner_qs) |
This queryset will be evaluated as subselect statement:
|
1
|
SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%') |
gt
|
1
|
Entry.objects.filter(id__gt=4) |
SQL equivalent:
|
1
|
SELECT ... WHERE id > 4; |
gte
Greater than or equal to.
lt
Less than.
lte
Less than or equal to.
startswith
Case-sensitive starts-with.
|
1
|
Entry.objects.filter(headline__startswith='Lennon') |
SQL equivalent:
|
1
|
SELECT ... WHERE headline LIKE 'Lennon%'; |
SQLite doesn’t support case-sensitive LIKE statements; startswith acts like istartswith for SQLite
istartswith
Case-insensitive starts-with.
endswith
Case-sensitive ends-with.
iendswith
Case-insensitive ends-with
range
区间过渡,可对数字、日期进行过滤
|
1
2
3
4
|
import datetimestart_date = datetime.date(2005, 1, 1)end_date = datetime.date(2005, 3, 31)Entry.objects.filter(pub_date__range=(start_date, end_date)) |
SQL equivalent:
|
1
|
SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31'; |
Warning!
Filtering a DateTimeField with dates won’t include items on the last day, because the bounds are interpreted as “0am on the given date”. If pub_date was a DateTimeField, the above expression would be turned into this SQL:
SELECT ... WHERE pub_date BETWEEN '2005-01-01 00:00:00' and '2005-03-31 00:00:00';
Generally speaking, you can’t mix dates and datetimes.
date
For datetime fields, casts the value as date. Allows chaining additional field lookups. Takes a date value.
|
1
2
|
Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) |
year
For date and datetime fields, an exact year match. Allows chaining additional field lookups. Takes an integer year.
|
1
2
|
Entry.objects.filter(pub_date__year=2005)Entry.objects.filter(pub_date__year__gte=2005) |
SQL equivalent:
|
1
2
|
SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31';SELECT ... WHERE pub_date >= '2005-01-01'; |
When USE_TZ is True, datetime fields are converted to the current time zone before filtering. 简单解决办法是把USE_TZ=False
month
For date and datetime fields, an exact month match. Allows chaining additional field lookups. Takes an integer 1 (January) through 12 (December).
|
1
2
|
Entry.objects.filter(pub_date__month=12)Entry.objects.filter(pub_date__month__gte=6) |
When USE_TZ is True, datetime fields are converted to the current time zone before filtering. This requires time zone definitions in the database.
SQL equivalent:
|
1
2
|
SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12';SELECT ... WHERE EXTRACT('month' FROM pub_date) >= '6'; |
day
For date and datetime fields, an exact day match. Allows chaining additional field lookups. Takes an integer day.
|
1
2
|
Entry.objects.filter(pub_date__day=3)Entry.objects.filter(pub_date__day__gte=3) |
SQL equivalent:
|
1
2
|
SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3';SELECT ... WHERE EXTRACT('day' FROM pub_date) >= '3'; |
week
For date and datetime fields, return the week number (1-52 or 53) according to ISO-8601, i.e., weeks start on a Monday and the first week contains the year’s first Thursday.
Example:
|
1
2
|
Entry.objects.filter(pub_date__week=52)Entry.objects.filter(pub_date__week__gte=32, pub_date__week__lte=38) |
week_day
For date and datetime fields, a ‘day of the week’ match. Allows chaining additional field lookups.
Takes an integer value representing the day of week from 1 (Sunday) to 7 (Saturday).
Example:
|
1
2
|
Entry.objects.filter(pub_date__week_day=2)Entry.objects.filter(pub_date__week_day__gte=2) |
hour
For datetime and time fields, an exact hour match. Allows chaining additional field lookups. Takes an integer between 0 and 23.
Example:
|
1
2
3
|
Event.objects.filter(timestamp__hour=23)Event.objects.filter(time__hour=5)Event.objects.filter(timestamp__hour__gte=12) |
SQL equivalent:
|
1
2
3
|
SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23';SELECT ... WHERE EXTRACT('hour' FROM time) = '5';SELECT ... WHERE EXTRACT('hour' FROM timestamp) >= '12';同 |
同时,还支持mintue,second
|
1
2
3
4
|
Event.objects.filter(time__minute=46)Event.objects.filter(timestamp__second=31) |
isnull
Takes either True or False, which correspond to SQL queries of IS NULL and IS NOT NULL, respectively.
Example:
|
1
|
Entry.objects.filter(pub_date__isnull=True) |
SQL equivalent:
|
1
|
SELECT ... WHERE pub_date IS NULL; |
regex
Case-sensitive regular expression match.
Example:
|
1
|
Entry.objects.get(title__regex=r'^(An?|The) +') |
SQL equivalents:
|
1
2
3
4
5
6
7
|
SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQLSELECT ... WHERE REGEXP_LIKE(title, '^(An?|The) +', 'c'); -- OracleSELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQLSELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite |
iregex 大小写不敏感
改删
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
# 批量修改models.Account.objects.filter(username='elina').update(password="Luffy#21")# 单条修改obj = models.Account.objects.get(username='linux')obj.username = 'python'obj.save()# 批量删除models.User.objects.get(password='oldboy').delete()# 单条删除obj = models.User.objects.get(id=3)obj.delete() |
数据返回后的展示
values()
values(*fields, **expressions)
Returns a QuerySet that returns dictionaries, rather than model instances, when used as an iterable.
|
1
2
3
4
|
>>> Blog.objects.values()<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>>>> Blog.objects.values('id', 'name')<QuerySet [{'id': 1, 'name': 'Beatles Blog'}]> |
order_by()
order_by(*fields)
By default, results returned by a QuerySet are ordered by the ordering tuple given by the ordering option in the model’s Meta. You can override this on a per-QuerySet basis by using the order_by method.
|
1
|
Entry.objects.filter(pub_date__year=2005).order_by('-pub_date', 'headline') |
The result above will be ordered by pub_date descending, then by headline ascending. The negative sign in front of "-pub_date"indicates descending order. Ascending order is implied.
reverse()
Use the reverse() method to reverse the order in which a queryset’s elements are returned. Calling reverse() a second time restores the ordering back to the normal direction.
To retrieve the “last” five items in a queryset, you could do this:
|
1
|
my_queryset.reverse()[:5] |
ORM对象操作
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
单表对象操作o = models.Article.objects.all()[0]o.tilte外键关联>>> o.account.username'jack'>>> o.account.username = rain外键反向关联操作>>> a = models.Account.objects.get(username='alex')>>> a.article_set.all()<QuerySet [<Article: 你好,2018>]>>>> a.article_set.select_related()<QuerySet [<Article: 你好,2018>]>多对多操作>>> o = models.Article.objects.all()[1]>>> o.tags.all()<QuerySet [<Tag: 投资>, <Tag: 科技>]>多对多反向操作>>> t = models.Tag.objects.get(name="投资")>>> t.article_set.all()<QuerySet [<Article: 你好,2018>, <Article: 粉丝超过10万后,我经历了抖音盗号风波>]> |
好啦,orm的操作先点到为止,后面学项目时再带你搞复杂的。
练习题
- 基于前面课程设计的表结构,完成以下练习:
- 创建5条account和5条新tag纪录
- 创建5条article信息,关联上面的不同的用户和tag
- 在account表里找到用户名包含al的纪录,然后把密码改掉
- 在article表找到文章内容包含“电影”2个字的,把这些文章加上”大文娱”tag
- 把用户elina发表的文章找出来,并且把作者都改成alex
- 找到用户表里注册日期在2018-04月,并且signature为空的纪录
- 打到文章中标签为“投资”的所有文章
- 找到每个月8号注册的用户
- 找到每年5月发表的文章
- 找到2015-2017年5月发表的文章
- 找到文章作者以’a’或’k’开头的文章
Django之 Models组件的更多相关文章
- Django之Form组件
Django之Form组件 本节内容 基本使用 form中字段和插件 自定义验证规则 动态加载数据到form中 1. 基本使用 django中的Form组件有以下几个功能: 生成HTML标签 验证用户 ...
- Python之路【第二十一篇】:Django之Form组件
Django之Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试牛刀 1. ...
- 第十一篇:web之Django之Form组件
Django之Form组件 Django之Form组件 本节内容 基本使用 form中字段和插件 自定义验证规则 动态加载数据到form中 1. 基本使用 django中的Form组件有以下几个功 ...
- Django之Model组件
Model组件在django基础篇就已经提到过了,本章介绍更多高级部分. 一.回顾 1.定义表(类) ##单表 from django.db import models class user(mode ...
- 【django之stark组件】
一.需求 仿照django的admin,开发自己的stark组件.实现类似数据库客户端的功能,对数据进行增删改查. 二.实现 1.在settings配置中分别注册这三个app # Applicatio ...
- python Django之Form组件
python Django之Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试 ...
- django 之 stark组件
----------------------------------------------------------------烦恼没完没了,内心动荡不安,呜呼哀哉. 一.有个特殊的需求,需要用sta ...
- Django之ContentType组件
一.理想表结构设计 1.初始构建 1. 场景刚过去的双12,很多电商平台都会对他们的商品进行打折促销活动的,那么我们如果要实现这样的一个场景,改如何设计我们的表? 2. 初始表设计 注释很重要,看看吧 ...
- Python学习(三十九)—— Django之Form组件
一.构建一个表单 假设你想在你的网站上创建一个简单的表单,以获得用户的名字.你需要类似这样的模板: <form action="/your-name/" method=&qu ...
随机推荐
- @atcoder - AGC034F@ RNG and XOR
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个值域在 [0, 2^N) 的随机数生成器,给定参数 A[ ...
- Pants On Fire(链式前向星存图、dfs)
Pants On Fire 传送门:链接 来源:upc9653 题目描述 Donald and Mike are the leaders of the free world and haven't ...
- sorted排序
sorted(['bob', 'about', 'Zoo', 'Credit']) # ['Credit', 'Zoo', 'about', 'bob'] ''' 默认情况下,对字符串排序,是按照AS ...
- pip未找到
命令终端运行 sudo easy_install pip 安装成功后最后会显示 Installed /Library/Python/2.7/site-packages/pip-9.0.1-py2.7. ...
- matplotlib浅析
首先放出matplotlib的中英文文档: 中文:https://www.matplotlib.org.cn/ 英文:https://matplotlib.org/3.1.1/index.html M ...
- java中Proxy类初探
在java中提供了一个动态代理类,这个类位于java.lang.reflect包中的Proxy类中.什么是动态代理类呢?就是可以在运行时创建一个实现了一组给定接口的新类.听上去有点高深的样子,其实是提 ...
- 项目实战:Qt手机模拟器拉伸旋转框架
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- Appium 概括与环境安装
Appium 是什么, 有什么用 Appium 用途和特点 appium 是一个移动 app 自动化工具 手机APP自动化有什么用? 自动化完成一些重要性的任务 比如微信客服机器人 爬虫 就是通过自动 ...
- skywalking的核心概念
在 SkyWalking 中,TraceSegment 是一个介于 Trace 与 Span 之间的概念,它是一条 Trace 的一段,可以包含多个 Span.在微服务架构中,一个请求基本都会涉及跨进 ...
- 001_动力节点_SpringMVC4_SpringMVC简介
1.视频的下载地址是 下载地址:百度云盘 链接:http://pan.baidu.com/s/1ge58XW3 密码:yd5jhttp://www.java1234.com/a/javaziliao/ ...