0 环境
再次重新过一下Django的知识。
开发环境,Linux Mint 19。
IDE, PyCharm, Vim
Python: 3
Django: 2.1.7
1 Start
这里直接使用Pycharm了,创建一个新的Project。
pip install django -i https://pypi.douban.com/simple --trusted-host=pypi.douban.com
1.1 创建Django Project
django-admin startproject HelloWorldPro
~/PycharmProjects/django-study » tree HelloWorldPro alonebo@alonebo-pc
HelloWorldPro
├── HelloWorldPro
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
1 directory, 5 files
可以看到创建了一个同名的子目录,外层目录同级还有一个manage.py
settings.py: 项目的配置文件。
urls.py: 进行url路由的配置。
wsgi.py: web服务器和Django交互的入口。
1.2 创建appilcation
切换cmd工作目录为HelloWorldPro
app相当于django项目对每一个业务逻辑模块的细分。
切换工作目录为HelloWorldPro。
django-admin startapp helloapp
~/PycharmProjects/django-study/HelloWorldPro » tree alonebo@alonebo-pc
.
├── helloapp
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── HelloWorldPro
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-36.pyc
│ │ └── settings.cpython-36.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
4 directories, 14 files
在helloapp目录里面,相关介绍如下
models.py: 写和数据库项目的内容, 设计模型类。
views.py: 接收请求,进行处理,与M和T进行交互,返回应答。定义处理函数,视图函数。
tests.py: 写测试代码的文件。
admin.py: 网站后台管理相关的文件。
1.3 注册创建的app
HelloWorldPro>> vim HelloWorldPro/settings.py
%s/staticfiles',/staticfiles',\r 'helloapp'
在INSTALLED_APPS 列表里面添加。
1.4 Runserver
之前说过,项目顶层目录有一个manage.py,现在,它就派上用处了。
python manager.py runserver
测试是否正常
firefox localhost:8000
1.5 HelloWorld
为了访问能够展示Hello World,我们需要创建视图,修改路由信息
修改HelloWorldPro/helloapp/views.py
from django.shortcuts import HttpResponse
def hello(request):
return HttpResponse("Hello Baloneo")
修改HelloWorldPro/HelloWorldPro/urls.py
from django.contrib import admin
from django.urls import path
from helloapp.views import hello as hello_view
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', hello_view)
]
测试是否成功
curl localhost:8000/hello
PyCharm提示找不到helloapp,右键,让项目目录变为源码目录。
MVC开始是存在于桌面程序中的,M是指业务模型,V是指用户界面,C则是控制器,使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使用不同的表现形式。比如一批统计数据可以分别用柱状图、饼图来表示。C存在的目的则是确保M和V的同步,一旦M改变,V应该同步更新。
2 模型
ORM, Object Relational Mapping, 将你描述的对象映射为sql数据,语句等。
Django提供了强大的ORM。
2.1 模型类
模型类,用于代表数据库中的表结构。
修改HelloWorldPro/helloapp/models.py, 创建一个简单的学生模型类。
from django.db import models
# Create your models here.
class Student(models.Model):
name = models.CharField(max_length=128) # 学生名
age = models.IntegerField() # 学生年龄
birthday = models.DateField() # 出生日期
1 生成迁移文件
python manage.py makemigrations
2 执行迁移生成表
python mange.py migrate
执行完后,应该会有一个db.sqlite3的文件。
sqlite3 db.sqlite3
.tables
.schema helloapp_student
select * from sqlite_master where type="table" and name="helloapp_student";
2.2 manage.py shell基础
使用Django自带的交互环境,
增加一条数据
python manage.py shell
>>> from helloapp.models import Student
>>> stu = Student()
>>> stu.name="张三"
>>> stu.age=23
>>> from datetime import date
>>> stu.birthday = date(1998,10,10)
>>> stu.save()
>>> stu.age=44
>>> res = stu.save()
>>> print(res)
None
如果没保存成功,会出现异常。调用save之后,再次调用就是更新了。
保存成功之后,在sqlite3里面可以找到这条数据。
sqlite> select * from helloapp_student;
id|name|age|birthday
1|张三|44|1998-10-10
sqlite>
2.3 模型类相关基础操作
查询数据
python manage.py shell
all查询所有
>>> Student.objects.all()
<QuerySet [<Student: Student object (1)>]>
>>> from helloapp.models import Student
>>> Student.objects.all()
<QuerySet [<Student: Student object (1)>]>
>>>
get查询指定条件
<QuerySet [<Student: Student object (1)>]>
>>> Student.objects.all()[0]
<Student: Student object (1)>
>>> Student.objects.all()[0].name
'张三'
>>> Student.objects.get(id=1)
<Student: Student object (1)>
>>> Student.objects.get(name="张三")
<Student: Student object (1)>
>>>
删除数据
stu.delete()
2.4 一对多的表结构表示
方便起见,删除旧的数据库文件。然后,
修改HelloWorldPro/helloapp/models.py
from django.db import models
# Create your models here.
class Student(models.Model):
name = models.CharField(max_length=128) # 学生名
age = models.IntegerField() # 学生年龄
birthday = models.DateField() # 出生日期
# 多的一方 建立外键
class School(models.Model):
name = models.CharField(max_length=128) # 学校名
address = models.CharField(max_length=380) # 学校地址
models.ForeignKey(Student, on_delete=models.CASCADE)
更新执行迁移文件:
~/PycharmProjects/django-study/HelloWorldPro » python manage.py makemigrations alonebo@alonebo-pc
Migrations for 'helloapp':
helloapp/migrations/0002_school.py
- Create model School
(venv) ------------------------------------------------------------
~/PycharmProjects/django-study/HelloWorldPro » python manage.py migrate alonebo@alonebo-pc
Operations to perform:
Apply all migrations: admin, auth, contenttypes, helloapp, sessions
Running migrations:
Applying helloapp.0002_school... OK
(venv) ------------------------------------------------------------
~/PycharmProjects/django-study/HelloWorldPro »
创建数据:
~/PycharmProjects/django-study/HelloWorldPro » python manage.py shell alonebo@alonebo-pc
Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from helloapp.models import Student, School
>>> stu = Student()
>>> stu.name = "张三"
>>> stu.age = 20
>>> from datetime import date
>>> stu.birthday = date(1999, 10, 10)
>>> sch = School()
>>> sch.name = "希望小学"
>>> sch.address = "北京朝阳区"
>>> stu.school = sch
>>> stu.save()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/alonebo/PycharmProjects/django-study/venv/lib/python3.6/site-packages/django/db/models/base.py", line 670, in save
"unsaved related object '%s'." % field.name
ValueError: save() prohibited to prevent data loss due to unsaved related object 'school'.
>>> sch.save()
>>> stu.save()
sqlite3.IntegrityError: NOT NULL constraint failed: helloapp_student.school_id
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
django.db.utils.IntegrityError: NOT NULL constraint failed: helloapp_student.school_id
>>> stu.
stu.DoesNotExist( stu.clean( stu.full_clean( stu.name stu.save( stu.unique_error_message(
stu.MultipleObjectsReturned( stu.clean_fields( stu.get_deferred_fields( stu.objects stu.save_base( stu.validate_unique(
stu.age stu.date_error_message( stu.get_next_by_birthday( stu.pk stu.school
stu.birthday stu.delete( stu.get_previous_by_birthday( stu.prepare_database_save( stu.school_id
stu.check( stu.from_db( stu.id stu.refresh_from_db( stu.serializable_value(
>>> stu.school = sch
>>> stu.save()
>>> stu2 = Student()
>>> stu2.name = "张三"
>>> stu2.age = 10
>>> stu2.birthday = date(2000, 10, 1)
>>> stu2.school = sch
>>> stu2.save()
这里如果school对象还没调用save(),那么会报错。
ValueError: save() prohibited to prevent data loss due to unsaved related object 'school'.
然后保存之后,调用stu.save()会报完整性错误。
sqlite3.IntegrityError: NOT NULL constraint failed: helloapp_student.school_id
需要把stu.school再次赋值。
此时,数据库数据如下:
sqlite> select * from helloapp_student;
1|张三|20|1999-10-10|1
2|张三|10|2000-10-01|1
sqlite> select * from helloapp_school;
1|希望小学|北京朝阳区
由一查多(从School查询Student)
使用obj.xxx_set
>>> from helloapp.models import Student,School
>>> sch = School.objects.get(name="希望小学")
>>> sch
<School: School object (1)>
>>> sch.address
'北京朝阳区'
>>> sch.student_set.all()
<QuerySet [<Student: Student object (1)>, <Student: Student object (2)>]>
>>>
由多查一(从Student查询School)
使用obj.外键名
>>> from helloapp.models import Student,School
>>> stu1 = Student.objects.all()[0]
>>> stu1
<Student: Student object (1)>
>>> stu1.name
'张三'
>>> stu1.school
<School: School object (1)>
>>> stu1.school.name
'希望小学'
>>>
网友评论