Django提供了完善的模型层,来创建和存取数据,它包含你所储存数据的必要字段和行为,每个模型对应数据库中唯一的一张表,模型避免了我们直接对数据库的操作
修改…/sign/models.y文件,通过模型完成表的创建
"""
Django的模型文件,创建应用程序数据表模型(对应数据库的相关操作)
"""
from django.db import models
"""
Event表和Guest表都会生成自增ID,但在创建模型类时无需声明该字段
"""
# Create your models here.
class Event(models.Model):
name = models.CharField(max_length=100)
limit = models.IntegerField()
status = models.BooleanField()
address = models.CharField(max_length=200)
start_time = models.DateTimeField('event time')
create_time = models.DateTimeField('auto_now=True')
def __str__(self):
return self.name
class Guest(models.Model):
event = models.ForeignKey(Event, on_delete=models.CASCADE)
realname = models.CharField(max_length=64)
phone = models.CharField(max_length=16)
email = models.EmailField()
sign = models.BooleanField()
create_time = models.DateTimeField(auto_now=True)
"""
Django模型类的一个内部类,它用于定义一些Django模型类的行为特性,unique_together用于设置两个字段为联合主键
"""
class Meta:
unique_together = ('event', 'phone')
"""
__str__()方法告诉Python如何将对象以str的方式显示出来(python2的话使用__unicode__())
"""
def __str__(self):
return self.realname
类型 | 说明 |
---|---|
AutoField | 一个IntegerField类型的自动增量 |
BooleanField | 用于存放布尔类型的数据 |
CharField | 用于存放字符型数据,需要指定长度max_length |
DateField | 日期类型,必须是"YYYY-MM-DD"格式 |
DateTimeField | 日期时间类型,必须是"YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]"格式 |
DecimalField | 小数型,用于存放小数的数字 |
EmailField | 电子邮件类型 |
FilePathField | 文件路径类型 |
FloatField | 用于存放浮点型数据 |
IntegerField | integer类型,数值范围从-2147483648到2147483647 |
BigIntegerField | 用于存放大的integer类型,最大数支持9223372036854775807 |
GenericIPAddressField | 存放IP地址的类型,IPv4和IPv6地址,字符串格式 |
NullBooleanField | 类似BooleanField类型,但允许NULL作为选项之一 |
PositiveIntegerField | 类似IntegerField类型,但必须是正数或者零,范围从0到2147483647 |
PositiveSmallIntegerField | 类似PositiveIntegerField类型,范围从0到32767 |
SlugField | Slug是短标签,只包含字母、数字、下划线或字符,它通常在网址中使用,像CharField类型一样,需要定义max_length值 |
SmallIntegerField | 类似IntegerField类型,范围从-32768到32767 |
TextField | 用于存放文本类型的数据 |
TimeField | 时间类型“HH:MM[:ss[.uuuuuu]]”格式 |
URLField | 用于存放URL地址 |
BinaryField | 存储原始二进制数据的字段 |
更多细节参考官方文档
模型类建好后,执行如下命令进行数据库迁移
E:\Programs\Python\Python_Django_Interface>python manage.py makemigrations sign
Migrations for 'sign':
sign\migrations\0001_initial.py
- Create model Event
- Create model Guest
E:\Programs\Python\Python_Django_Interface>python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, sign
Running migrations:
Applying sign.0001_initial... OK
修改…/sign/admin.py文件,用于在页面上添加(注册)模块
"""
映射models中的数据到django自带的admin后台
"""
from django.contrib import admin
from sign.models import Event, Guest
# Register your models here.
admin.site.register(Event)
admin.site.register(Guest)
访问页面http://127.0.0.1:8000/admin/ 如图所示,已经添加了Event和Guest模块
成功添加一个Event
如图所示显示了一条发布会信息,默认只会有发布会名称,这与创建model时设置的__str__()方法有关,默认返回self.name,即发布会名称,要显示更多字段,需修改…/sign/admin.py文件
"""
映射models中的数据到django自带的admin后台
"""
from django.contrib import admin
from sign.models import Event, Guest
# Register your models here.
class EventAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'status', 'address', 'start_time']
class GuestAdmin(admin.ModelAdmin):
list_display = ['realname', 'phone', 'email', 'sign', 'create_time', 'event']
admin.site.register(Event, EventAdmin)
admin.site.register(Guest, GuestAdmin)
刷新Event页面,如下所示
通过Admin页面添加一个guest,http://127.0.0.1:8000/admin/
修改…/sign/admin.py文件
"""
映射models中的数据到django自带的admin后台
"""
from django.contrib import admin
from sign.models import Event, Guest
# Register your models here.
class EventAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'status', 'address', 'start_time']
search_fields = ['name']
list_filter = ['status']
class GuestAdmin(admin.ModelAdmin):
list_display = ['realname', 'phone', 'email', 'sign', 'create_time', 'event']
search_fields = ['realname', 'phone']
list_filter = ['sign']
admin.site.register(Event, EventAdmin)
admin.site.register(Guest, GuestAdmin)
当需要操作数据库时,不需要SQL语句,Django自动为这些模型提供了高级的Python API
启动命令行,输入如下命令,进入Django特别定制的Shell命令行,该命令行便可以操作Django模型
E:\Programs\Python\Python_Django_Interface>python manage.py shell
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from sign.models import Event, Guest
>>> Event.objects.all()
<QuerySet [<Event: 迅盘云发布会A>]>
>>> Guest.objects.all()
<QuerySet [<Guest: davieyang>]>
>>>
objects.all()获取table中所有对象
>>> from datetime import datetime
>>> event1 = Event(id=2,name='迅盘云发布会B', litmit=200, status=True, address='上海', start_time=datetime(2019,10,21,20,0,0))
>>>event1.save()
执行该组命令会报错
C:\Python37\lib\site-packages\django\db\models\fields\__init__.py:1423: RuntimeWarning: DateTimeField Event.start_time received a naive datetime (2019-10-21 20:00:00) while time zone support is active.
RuntimeWarning)
Traceback (most recent call last):
File "" , line 1, in <module>
File "C:\Python37\lib\site-packages\django\db\models\base.py", line 501, in __init__
raise TypeError("%s() got an unexpected keyword argument '%s'" % (cls.__name__, kwarg))
TypeError: Event() got an unexpected keyword argument 'litmit'
>>> event1 = Event(id=2,name='迅盘云发布会B', limit=200, status=True, address='上海', start_time=datetime(2019,10,21,20,0,0))
>>> event1.save()
C:\Python37\lib\site-packages\django\db\models\fields\__init__.py:1423: RuntimeWarning: DateTimeField Event.start_time received a naive datetime (2019-10-21 20:00:00) while time zone support is active.
RuntimeWarning)
Traceback (most recent call last):
File "C:\Python37\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "C:\Python37\lib\site-packages\django\db\backends\sqlite3\base.py", line 383, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: NOT NULL constraint failed: sign_event.create_time
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "" , line 1, in <module>
File "C:\Python37\lib\site-packages\django\db\models\base.py", line 741, in save
force_update=force_update, update_fields=update_fields)
File "C:\Python37\lib\site-packages\django\db\models\base.py", line 779, in save_base
force_update, using, update_fields,
File "C:\Python37\lib\site-packages\django\db\models\base.py", line 870, in _save_table
result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "C:\Python37\lib\site-packages\django\db\models\base.py", line 908, in _do_insert
using=using, raw=raw)
File "C:\Python37\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Python37\lib\site-packages\django\db\models\query.py", line 1186, in _insert
return query.get_compiler(using=using).execute_sql(return_id)
File "C:\Python37\lib\site-packages\django\db\models\sql\compiler.py", line 1335, in execute_sql
cursor.execute(sql, params)
File "C:\Python37\lib\site-packages\django\db\backends\utils.py", line 99, in execute
return super().execute(sql, params)
File "C:\Python37\lib\site-packages\django\db\backends\utils.py", line 67, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "C:\Python37\lib\site-packages\django\db\backends\utils.py", line 76, in _execute_with_wrappers
return executor(sql, params, many, context)
File "C:\Python37\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "C:\Python37\lib\site-packages\django\db\utils.py", line 89, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "C:\Python37\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "C:\Python37\lib\site-packages\django\db\backends\sqlite3\base.py", line 383, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: NOT NULL constraint failed: sign_event.create_time
核心内容是
C:\Python37\lib\site-packages\django\db\models\fields\__init__.py:1423: RuntimeWarning: DateTimeField Event.start_time received a naive datetime (2019-10-21 20:00:00) while time zone support is active.
RuntimeWarning)
修改…/sign/settings.py文件,设置USE_TZ=False
然后命令行执行quit(),先退出,再进入Django Shell,刚才对于settings.py的设置才能生效,再次执行这组命令
>>> from datetime import datetime
>>> from sign.models import Event, Guest
>>> event1 = Event(id=2,name='迅盘云发布会B', limit=200, status=True, address='上海', start_time=datetime(2019,10,21,20,0,0), create_time=datetime(2019,10,21,20,0,0))
>>> event1.save()
>>>
命令行中我们先创建了一个Event,然后使用Save()函数进行数据插入
也可以直接使用create()函数,两步并作一步
即Event.objects.create()
>>> Event.objects.create(id=3, name='迅盘云发布会C', limit=3000, status=True, address='广州', start_time=datetime(2019,10,22,00,00,00), create_time=datetime(2019,10,22,00,00,00))
<Event: 迅盘云发布会C>
>>> Guest.objects.create(realname='alexyang', phone=18001156155, email='[email protected]', sign=False, event_id=3)
<Guest: alexyang>
table.objects.get() 精确查询
table.objects.filter() 模糊查询
>>> event1 = Event.objects.get(name='迅盘云发布会A')
>>> event1.address
'北京'
>>>
>>> event2 = Event.objects.filter(name__contains='发布会')
>>> event2
<QuerySet [<Event: 迅盘云发布会A>, <Event: 迅盘云发布会B>, <Event: 迅盘云发布会C>]>
两种写法均可
>>> guest1 = Guest.objects.get(phone='18001156155')
>>> guest1.delete()
(1, {'sign.Guest': 1})
>>> Guest.objects.get(phone='18001156155').delete()
两种写法均可
>>> guest1 = Guest.objects.get(phone='15901281916')
>>> guest1.realname='yangdawei'
>>> guest1.save()
>>> Guest.objects.select_for_update().filter(phone='15901281916').update(realname='davieyang')
1
Django默认是使用python自带的SQLite3,但它不适合大型系统,Django还支持Mysql/PostgreSQL/Oracle
修改…/guest/settings.py文件,将项目的数据库又SQLite3改成Mysql
# https://docs.djangoproject.com/en/2.2/ref/databases/#mysql-sql-mode
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1',
'PORT': 3306,
'NAME': 'guest', # 数据库实例名
'USER': 'root',
'PASSWORD': 'root',
'OPTIONS': {
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"
}
}
}
关于sql_mode的设置可参考官方地址
切换了数据库后,原来的SQLite3的数据并不会迁移到Mysql中,需要重新走一遍之前数据创建的过程
执行命令
python manage.py migrate
会抛出如下异常:
(venv) D:\Python_Django_Interface>python manage.py migrate
Traceback (most recent call last):
File "C:\Python37\lib\site-packages\django\db\backends\mysql\base.py", line 15, in <module>
import MySQLdb as Database
ModuleNotFoundError: No module named 'MySQLdb'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "manage.py", line 21, in <module>
main()
File "manage.py", line 17, in main
execute_from_command_line(sys.argv)
File "C:\Python37\lib\site-packages\django\core\management\__init__.py", line 381, in execute_from_command_line
utility.execute()
File "C:\Python37\lib\site-packages\django\core\management\__init__.py", line 357, in execute
django.setup()
File "C:\Python37\lib\site-packages\django\__init__.py", line 24, in setup
apps.populate(settings.INSTALLED_APPS)
File "C:\Python37\lib\site-packages\django\apps\registry.py", line 114, in populate
app_config.import_models()
File "C:\Python37\lib\site-packages\django\apps\config.py", line 211, in import_models
self.models_module = import_module(models_module_name)
File "C:\Python37\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "" , line 1006, in _gcd_import
File "" , line 983, in _find_and_load
File "" , line 967, in _find_and_load_unlocked
File "" , line 677, in _load_unlocked
File "" , line 728, in exec_module
File "" , line 219, in _call_with_frames_removed
File "C:\Python37\lib\site-packages\django\contrib\auth\models.py", line 2, in <module>
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
File "C:\Python37\lib\site-packages\django\contrib\auth\base_user.py", line 47, in <module>
class AbstractBaseUser(models.Model):
File "C:\Python37\lib\site-packages\django\db\models\base.py", line 117, in __new__
new_class.add_to_class('_meta', Options(meta, app_label))
File "C:\Python37\lib\site-packages\django\db\models\base.py", line 321, in add_to_class
value.contribute_to_class(cls, name)
File "C:\Python37\lib\site-packages\django\db\models\options.py", line 204, in contribute_to_class
self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
File "C:\Python37\lib\site-packages\django\db\__init__.py", line 28, in __getattr__
return getattr(connections[DEFAULT_DB_ALIAS], item)
File "C:\Python37\lib\site-packages\django\db\utils.py", line 201, in __getitem__
backend = load_backend(db['ENGINE'])
File "C:\Python37\lib\site-packages\django\db\utils.py", line 110, in load_backend
return import_module('%s.base' % backend_name)
File "C:\Python37\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "C:\Python37\lib\site-packages\django\db\backends\mysql\base.py", line 20, in <module>
) from err
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
Did you install mysqlclient?
安装mysqlclient即可pip install mysqlclient
可能还会报如下异常
(venv) D:\Python_Django_Interface>python manage.py migrate
Traceback (most recent call last):
File "manage.py", line 21, in <module>
main()
File "manage.py", line 17, in main
execute_from_command_line(sys.argv)
File "C:\Python37\lib\site-packages\django\core\management\__init__.py", line 381, in execute_from_command_line
utility.execute()
File "C:\Python37\lib\site-packages\django\core\management\__init__.py", line 357, in execute
django.setup()
File "C:\Python37\lib\site-packages\django\__init__.py", line 24, in setup
apps.populate(settings.INSTALLED_APPS)
File "C:\Python37\lib\site-packages\django\apps\registry.py", line 114, in populate
app_config.import_models()
File "C:\Python37\lib\site-packages\django\apps\config.py", line 211, in import_models
self.models_module = import_module(models_module_name)
File "C:\Python37\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "" , line 1006, in _gcd_import
File "" , line 983, in _find_and_load
File "" , line 967, in _find_and_load_unlocked
File "" , line 677, in _load_unlocked
File "" , line 728, in exec_module
File "" , line 219, in _call_with_frames_removed
File "C:\Python37\lib\site-packages\django\contrib\auth\models.py", line 2, in <module>
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
File "C:\Python37\lib\site-packages\django\contrib\auth\base_user.py", line 47, in <module>
class AbstractBaseUser(models.Model):
File "C:\Python37\lib\site-packages\django\db\models\base.py", line 117, in __new__
new_class.add_to_class('_meta', Options(meta, app_label))
File "C:\Python37\lib\site-packages\django\db\models\base.py", line 321, in add_to_class
value.contribute_to_class(cls, name)
File "C:\Python37\lib\site-packages\django\db\models\options.py", line 204, in contribute_to_class
self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
File "C:\Python37\lib\site-packages\django\db\__init__.py", line 28, in __getattr__
return getattr(connections[DEFAULT_DB_ALIAS], item)
File "C:\Python37\lib\site-packages\django\db\utils.py", line 201, in __getitem__
backend = load_backend(db['ENGINE'])
File "C:\Python37\lib\site-packages\django\db\utils.py", line 110, in load_backend
return import_module('%s.base' % backend_name)
File "C:\Python37\lib\importlib\__init__.py", line 127, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "C:\Python37\lib\site-packages\django\db\backends\mysql\base.py", line 36, in <module>
raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.__version__)
django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3.
异常信息很清楚, mysqlclient版本太低了,与Django版本不匹配,需要1.3.13以上版本
django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3.
命令行更新mysqlclient
(venv) D:\Python_Django_Interface>pip install --upgrade mysqlclient
Collecting mysqlclient
Downloading https://files.pythonhosted.org/packages/64/46/3811fe37b1e1a39d6c47f44957cdae9c207bc23bf6c22ebb1d7a6892a55f/mysqlclient-1.4.4-cp37-cp37m-win
_amd64.whl (178kB)
|████████████████████████████████| 184kB 344kB/s
Installing collected packages: mysqlclient
Successfully installed mysqlclient-1.4.4
也可以直接下载安装文件,然后安装
https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient
根据…/settings.py的数据库配置,我们是要往名为guest的数据库实例中创建内容,因此首先要保证mysql中已经见了guest库,然后再执行命令
python manage.py migrate
(venv) D:\Python_Django_Interface>python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions, sign
Running 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 admin.0003_logentry_add_action_flag_choices... 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 auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying sessions.0001_initial... OK
Applying sign.0001_initial... OK
更换了数据,Django的Admin后台管理员账号也要重新创建,再温习一遍吧
(venv) D:\Python_Django_Interface>python manage.py createsuperuser
Username (leave blank to use 'administrator'): admin
Email address: [email protected]
Password:
Password (again):
Superuser created successfully.