Django Web应用框架【模型】

设计系统表

Django提供了完善的模型层,来创建和存取数据,它包含你所储存数据的必要字段和行为,每个模型对应数据库中唯一的一张表,模型避免了我们直接对数据库的操作

  • 每个模型是一个Python类,集成django.db.models.Model类
  • 模型的每个属性表示一个数据库表字段
  • Django已经准备了一个自动生成的数据库访问的API

通过模型完成表的创建

修改…/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 "<console>", 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 "<console>", 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

SQLite管理用具

  • SQLite Manager 基于Firefox的浏览器插件,直接在插件里搜索安装即可
    在这里插入图片描述
  • SQLiteStudio跨平台的SQLite数据库管理工具,下载地址https://sqlitestudio.pl/index.rvt
    在这里插入图片描述

配置Mysql

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 "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", 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 "<frozen importlib._bootstrap>", line 1006, in _gcd_import
  File "<frozen importlib._bootstrap>", line 983, in _find_and_load
  File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", 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.

发布了162 篇原创文章 · 获赞 42 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/dawei_yang000000/article/details/102649708
今日推荐