【Django】【三】模型

 

---------------------------------------【MySQL】--由于之前用的是sqlite,所以现在要重新来过----------start-----------------

1  数据库客户端删除数据库

mysql> drop database 数据库名字;

【备注】如果报错:mysql errro 1010 (HY000)  参考:https://jingyan.baidu.com/article/d71306352af34613fdf475eb.html

2  清理项目中关于数据库的缓存 :删掉migrations和 __pycache__ folder 

3  数据库客户端创建数据库,编码格式选择"utf-8" 

 mysql> CREATE DATABASE guest CHARACTER SET utf8;

4 重新执行:

python3 manage.py makemigrations app名字

python3 manage.py migrate

5. Admin 后台超级管理员账号(admin/admin123) 也需要重新创建 

cmd.exe

D:\pydj\guest>python3 manage.py createsuperuser

Username (leave blank to use 'fnngj'): admin #输入登录用户名 

 

Email address:admin@mail.com

Password:#数据登录密码

Password(again):#再次输入密码

Superuser created successfully.

6. MySQL客户端安装

win7 我用 HeidiSQL_9.4.0.5125

 

---------------------------------------【MySQL】--由于之前用的是sqlite,所以现在要重新来过----------end-----------------

 

 

4.1 设计系统表

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

Django模型基础知识:

  • 每个模型是一个Python类,继承django.db.models.Model 类
  • 该模型的每个属性表示一个数据库表字段
  • 所有这一切,已经给了你一个自动生成的数据库访问的API

打开 .../sign/models.py  

# -*- coding: UTF-8 -*-
from django.db import models

# 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('events 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) # 关联发布会ID
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) # 创建时间(默认获取当前时间)

class Meta:
unique_together = ('event', 'phone')

def __str__(self):
return self.realname
对于产品发布会来说,它是一个事件。那么时间、地点、人物等要素必不可少。数据库表将会围绕这些要素设计。
发布会表 (Event表)和嘉宾表(Guest表)的每一个字段在代码中已经做了注解。有些字段的设计需要做一个简单的说明。

首先,发布会表和嘉宾表中默认都会生成自增ID,但在创建模型类时不需要声明该字段。
其次,发布会表中增加status字段用于表示该发布会的状态是否开启,从而控制发布会是否可用。
再次,嘉宾表中通过字段event(表中字段名event_id)关联发布会ID,一条嘉宾信息一定是属于某一场发布会。ForeignKey()用来创建外键。
最后,对于一场发布会来说,因为手机号具有很强的唯一性,因此一般会选择手机号作为一位嘉宾的唯一验证信息。在嘉宾表中,除了嘉宾ID为主键外,这里通过发布会id+手机号来作为联合主键。Meta是Django模型类的一个内部类,它用于定义
一些Django模型类的行为特性。unique_together用于设置两个字段为联合主键。
__str__()方法告诉Python如何将对象以str的方式显示出来。所以,为每个模型类添加了__str__()
Django模型字段常用类型

官方参考文档 https://docs.djangoproject.com/en/3.1/ref/models/fields

数据库迁移

B0178RQ2019070018:guest wangxue$ python3 manage.py makemigrations sign

Migrations for 'sign':

  sign/migrations/0001_initial.py

    - Create model Event

    - Create model Guest

B0178RQ2019070018:guest wangxue$ python3 manage.py migrate

Operations to perform:

  Apply all migrations: admin, auth, contenttypes, sessions, sign

Running migrations:

  Applying sign.0001_initial... OK

 



4.2 admin后台管理
admin.py

from django.contrib import admin
from sign.models import Event, Guest

# Register your models here.

admin.site.register(Event)
admin.site.register(Guest)

这些代码通知Admin管理工具为这些模块逐一提供界面。
登陆admin后台: http://127.0.0.1:8000/admin/ (admin/admin123456)

单击Events对应的add 添加一条发布会信息

 

 如何才能显示表中更多字段呢? 继续修改../sign/admin.py

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)


Django提供了大量选项让你针对特别的模块自定义管理工具。这些选项都在ModleAdmin类中,创建EventAdmin类 ModelAdmin。 这里只自定义了一项,list_display,
它是一个字段名称的数组,用于定义要在列表中显示哪些字段。当然,这些字段名称必须是模型中的Event() 类所定义的。
修改admin.site.register(),添加 EventAdmin类。你可以这样理解,用EventAdmin选项注册Event模块。
对于Guest模块来说,操作步骤同上。保存修改的代码,重新刷新Events列表,如图

添加一条嘉宾信息,如下图 

 

除此之外,还可以快速生成搜索栏和过滤器。重新打开../sign/admin.py 修改如下

 

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)

访问http://127.0.0.1:8000/admin/sign/event/

 

 

4.3 基本数据访问

当需要操作数据库时,不再需要通过SQL语句。Django自动为这些模型提供了高级的API。接下来联系数据库表的操作,运行manage.py提供的shell命令

cmd.exe

B0178RQ2019070018:~ wangxue$ cd ~/Library/Python/3.7/bin/guest/

B0178RQ2019070018:guest wangxue$ python3 manage.py shell

Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 03:13:28) 

[Clang 6.0 (clang-600.0.57)] on darwin

Type "help", "copyright", "credits" or "license" for more information.

(InteractiveConsole)

>>> from sign.models import Event, Guest

>>> Event.objects.all()

<QuerySet [<Event: 小米5发布会>]>

>>> Guest.objects.all()

<QuerySet [<Guest: snow>]>

>>> 

 

4.3.1 插入数据

>>> from datetime import datetime

>>> e1 = Event(id=2, name='红米Pro发布会', limit=2000, status=True, address='北京水立方', start_time=datetime(2020, 6, 24, 14, 0, 0))

>>> e1.save()

/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/db/models/fields/__init__.py:1368: RuntimeWarning: DateTimeField Event.start_time received a naive datetime (2020-06-24 14:00:00) while time zone support is active.

  RuntimeWarning)

>>>

因为 start_time字段需要设置日期时间,所以先导入datetime.datetime()方法。当通过save()保存插入的数据时,我们收到一行警告信息:

RuntimeWarning: DateTimeField Event.start_time received a naive datetime (2020-06-24 14:00:00) while time zone support is active.

 这跟UTC有关,如果读者感兴趣可以自己搜索UTC是什么? 这里选择忽略这个问题,最简单的方式就是在../settings.py 文件中设置:USE_TZ = False

修改settings.py并保存,需要执行quit()命令退出shell模式,并重启python3 manage.py shell进入,刚才的设置才会生效。再次执行插入数据的步骤,看看警告信息是不是不见了。

 

>>> from sign.models import Event, Guest

>>> e2 = Event(id=3, name='realme发布会', limit=200, status=True, address='shanghai新天地', start_time=datetime(2020,8,8,15,0,0))

>>> e2.save()

>>>

 

如果觉得创建和保存分两步完成太麻烦,也可以通过table.objects.create() 将两步合为一步,方法如下

.....

>>> Event.objects.create(id=4, name='红米Max 发布会', limit=2000, status=True, address='北京会展中心', start_time=datetime(2016,9,22,14,0,0))

<Event: 红米Max 发布会>

>>> Guest.objects.create(realname='snow2', phone=13611001101, email='snow2@mail.com', sign=False, event_id=4)

<Guest: snow2>

需要说明的是,表的ID字段已经设置了自增,所以创建表数据可以不用指定ID,但在创建嘉宾数据时需要指定关联的发布会ID。Event表指定id=4, Guest表指定event_id=4,所以嘉宾‘snow2'对应的是‘红米Max发布会‘

 

4.3.2 查询数据

table.objects.get()用于从数据库表中取得一条匹配的结果,返回一个对象,如果记录不存在的话,那么它会报DoesNotExist 类型错误。

通过name='红米Max 发布会‘ 作为查询条件。

>>> from sign.models import Event, Guest

>>> Event.objects.all()

<QuerySet [<Event: 小米5发布会>, <Event: 红米Pro发布会>, <Event: realme发布会>, <Event: 红米Max 发布会>]>

>>> e1 = Event.objects.get(name='红米Max 发布会')

>>> e1

<Event: 红米Max 发布会>

>>> e1.address

'北京会展中心'

>>> e1.start_time

datetime.datetime(2016, 9, 22, 14, 0)

>>> Event.objects.get(name='红米Max 发布会').status

True

>>> Event.objects.get(name='红米Max 发布会').limit

2000

>>> Event.objects.get(name='红米Max').address

Traceback (most recent call last):

  File "<console>", line 1, in <module>

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/db/models/manager.py", line 82, in manager_method

    return getattr(self.get_queryset(), name)(*args, **kwargs)

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/db/models/query.py", line 417, in get

    self.model._meta.object_name

sign.models.Event.DoesNotExist: Event matching query does not exist.

>>>

因为name='红米Max‘并没有完全匹配到发布会名称,所以跑出DoesNotExist异常。但更多的时候我们会使用模糊查询。

table.objects.filter() 匹配结果,返回一个对象列表,如果记录不存在,返回空列表

 

cmd.exe

...

>>> e2 = Event.objects.filter(name__contains='发布会')

>>> e2

<QuerySet [<Event: 小米5发布会>, <Event: 红米Pro发布会>, <Event: realme发布会>, <Event: 红米Max 发布会>]>

>>>

【备注】name__contains是双下划线

接下来通过嘉宾查询其关联的发布会信息

cmd.exe

...

>>> g = Guest.objects.get(phone=13611001101)

>>> g

<Guest: snow2>

>>> g.event

<Event: 红米Max 发布会>

>>> g.event.name

'红米Max\xa0发布会'

>>> g.event.address

'北京会展中心'

 

4.3.3 删除数据

cmd.exe

>>> g = Guest.objects.get(phone=13611001101)

>>> g.delete()

(1, {'sign.Guest': 1})

 

4.3.4 更新数据

...

>>> g = Guest.objects.get(phone=123000)

>>> g.realname='snow2'

>>> g.save()

 

或者

...

>>> Guest.objects.select_for_update().filter(phone='123000').update(realname='snow3')

1

 

4.5.3 安装PyMySQL驱动

mysql_demo.py

from pymysql import cursors, connect 

 

# 连接数据库

conn = connect(host='127.0.0.1', user='root', password='123', db='guest', charset='utf8mb4', cursorclass=cursors.DictCursor)

try:

  with conn.cursor() as cursor:

      #创建嘉宾数据

      sql = 'insert into sign_guest(realname, phone, email, sign, event_id, create_time) values ('snow3', 678, 'snow3@mail.com, 0, 1, NOW());'

      #提交事务

      conn.commit()

  with conn.cursor() as cursor:

     #查询添加的嘉宾

     sql = 'select realname, phone, email, sign from sign_guest where phone=%s'

     cursor.execute(sql, ('123000',))

     result = cursor.fetchone()

     print(result)

finally:

  conn.close()

 

4.5.4 =Django中配置Mysql

.. guest/settings.py

 

...

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1',
'PORT': '3306',
'NAME': 'guest',
'USER': 'root',
'PASSWORD': '123',
'OPTIONS': {
           'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
},
}
}


cmd.exe

B0178RQ2019070018:guest wangxue$ python3 manage.py migrate

Traceback (most recent call last):

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/db/backends/mysql/base.py", line 16, 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 "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/core/management/__init__.py", line 401, in execute_from_command_line

    utility.execute()

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/core/management/__init__.py", line 377, in execute

    django.setup()

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/__init__.py", line 24, in setup

    apps.populate(settings.INSTALLED_APPS)

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/apps/registry.py", line 114, in populate

    app_config.import_models()

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/apps/config.py", line 211, in import_models

    self.models_module = import_module(models_module_name)

  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/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 "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/contrib/auth/models.py", line 2, in <module>

    from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/contrib/auth/base_user.py", line 47, in <module>

    class AbstractBaseUser(models.Model):

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/db/models/base.py", line 121, in __new__

    new_class.add_to_class('_meta', Options(meta, app_label))

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/db/models/base.py", line 325, in add_to_class

    value.contribute_to_class(cls, name)

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/db/models/options.py", line 208, in contribute_to_class

    self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/db/__init__.py", line 28, in __getattr__

    return getattr(connections[DEFAULT_DB_ALIAS], item)

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/db/utils.py", line 207, in __getitem__

    backend = load_backend(db['ENGINE'])

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/db/utils.py", line 111, in load_backend

    return import_module('%s.base' % backend_name)

  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/importlib/__init__.py", line 127, in import_module

    return _bootstrap._gcd_import(name[level:], package, level)

  File "/Users/wangxue/Library/Python/3.7/lib/python/site-packages/django/db/backends/mysql/base.py", line 21, in <module>

    ) from err

django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.

Did you install mysqlclient?

B0178RQ2019070018:guest wangxue$

 

出错啦 这是因为Django在连接Mysql时默认MySLdb 驱动 然而我们并没有安装这个驱动,前面已经说明它不支持python3 而现在使用的是PyMySQL 如何让当前的Django通过PyMySQL 来连接mysql呢

../guest/__init__.py

import pymysql
pymysql.install_as_MySQLdb()

重新执行数据库同步

 

---------------------------------------【MySQL】--由于之前用的是sqlite,所以现在要重新来过----------start-----------------

1  数据库客户端删除数据库

mysql> drop database 数据库名字;

【备注】如果报错:mysql errro 1010 (HY000)  参考:https://jingyan.baidu.com/article/d71306352af34613fdf475eb.html

2  清理项目中关于数据库的缓存 :删掉migrations和 __pycache__ folder 

3  数据库客户端创建数据库,编码格式选择"utf-8" 

 mysql> CREATE DATABASE guest CHARACTER SET utf8;

4 重新执行:

python3 manage.py makemigrations app名字

python3 manage.py migrate

5. Admin 后台超级管理员账号(admin/admin123) 也需要重新创建 

cmd.exe

D:\pydj\guest>python3 manage.py createsuperuser

Username (leave blank to use 'fnngj'): admin #输入登录用户名 

 

Email address:admin@mail.com

Password:#数据登录密码

Password(again):#再次输入密码

Superuser created successfully.

6. MySQL客户端安装

mac pro bn  -> navicat

---------------------------------------【MySQL】--由于之前用的是sqlite,所以现在要重新来过----------end-----------------

 

 










 

posted @ 2017-09-27 16:42  素人渔芙2017  阅读(278)  评论(0编辑  收藏  举报