django的model怎么测试(django model 查询)

导读:今天首席CTO笔记来给各位分享关于django的model怎么测试的相关内容,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

Django 中使用model 怎么查询不等于某个值的情况

Model是django项目的基础, 如果一开始没有好好设计好, 那么在接下来的开发过程中就会遇到更多的问题. 然而, 大多数的开发人员都容易在缺少思考 的情况下随意的增加或修改model. 这样做的后果就是, 在接下来的开发过程中, 我们不得不做出更多努力来修正这些错误.

因此, 在修改model时, 一定尽可能的经过充分的考虑再行动! 以下列出的是我们经常用到的一些工具和技巧:

South, 用于数据迁移, 我们会在每个django项目中都用到. 但到django 1.7时, 将会有django.db.migrations代替.

django-model-utils, 用于处理常见的模式, 例如TimeStampedModel.

django-extensions, 主要用到shell_plus命令, 该命令会在shell中自动载入所有的app的model

1. 基本原则

第一, 将model分布于不同的app中. 如果你的django项目中, 有一个app拥有超过20个model, 那么, 你就应当考虑分拆该app了. 我们推荐每个app拥 有不超过5个model.

第二, 尽量使用ORM. 我们需要的大多数数据库索引都能通过Object-Relational-Model实现, 且ORM带给我们许多快捷方式, 例如生成SQL语句, 读取/更新数据库时的安全验证. 因此, 如果能使用简单的ORM语句完成的, 应当尽量使用ORM. 只有当纯SQL语句极大地简化了ORM语句时, 才使用纯SQL语句. 并且, 在写纯SQL语句是, 应当优先考虑使用raw(), 再是extra().

第三, 必要时添加index. 添加db_index=True到model中非常简单, 但难的是理解何时应该添加. 在建立model时, 我们事先不会添加index, 只有当 以下情况时, 才会考虑添加index:

在所有的数据库查询中使用率在10%-25%时

或当有真实的数据, 或能正确估计出使用index后的效果确实满意时

第四, 注意model的继承. model的继承在django中需要十分小心, django提供了三种继承方式, 1.abstract base class继承(不要和Pyhton标准库的abc模块 搞混), 2.多表(multi-table)继承, 3.proxy model继承. 下表罗列了这三种继承的优劣:

django的创造者和其他许多开发人员都认为, 多表继承的方法不是一个良好的方法. 因此我们强烈建议大家不要使用该方法. 下面列举了一些常见的如何 选择model继承的情形:

如果只有少数model拥有重复的field时, 大可不必使用model继承, 只需要在每个model中添加这些相同的field即可.

如果有足够的model拥有重复的field时, 大多是情况下, 可以使用abstract base class继承, 将相同的field提取到abstract base class 中.

Proxy model继承很少被用到, 和其他两种继承也有着许多不一样之处.

请不要使用多表(multi-table)继承, 因为它既消耗资源又复杂, 如果可以, 尽量使用OneToOneFields和ForeignKeys代替.

django项目中, 创建时间和修改时间这两个field是最用到的, 下面给出一个abstract base class继承的例子:

2. Django Model的设计

如何设计出好的django model可能是最难也是最复杂的一个话题了, 在此, 我们看看一些基本的技巧吧:

a. 规范化

我们首先建议了解数据库规范化(database normalization). 如果你还不清楚这是什么, 那么, 我们强烈建议你先阅读一下相关的书籍, 或搜索\"关系 型数据库设计\"或\"数据库规范化\". 在创建django model之前, 应当首先保证设计的数据库是规范化的.

b. cache

正确的使用cache能帮助我们提高数据库的性能. 详细的信息, 我们会在今后的文章中作进一步介绍.

c. 何时使用null和blank

当定义model field时, 我们可以设置null=True和blank=True (默认都是False), 知道何时设置null和blank对于开发人员也是十分重要的, 在下 面的表格中, 我们一一列举了如何使用这两个选项:

d. 什么时候使用BinaryField

在django 1.6中, 新增了BinaryField, 用于储存二进制数据(binary data或 bytes). 对于BinaryField, 我们无法使用ORM的filters, excludes或其他SQL操作. 但在少数情况下, 我们会用到BinaryField, 例如MessagePack格式的内容, 传感器接受的原始数据和压缩数据等. 但需要注意 的是, Binary Data一般都十分庞大, 因此可能会拖慢数据库的速度. 如果发生这一现象, 我们可以将binary data储存在文件中, 然后使用FileField储 存该文件的路径信息.

还有, 不要从BinaryField中直接读取文件并呈献给用户. 因为, 1. 从数据库读写总是比从文件系统读写慢; 2. 数据库备份会变得十分庞大, 花费更多 的时间; 3. 获得文件的过程, 增加了从django到数据库的这一环节.

3. 不要替换默认的Model Manager

从ORM获取model, 实际上是通过django中的Model manager完成的, django为每一个model提供了默认的model manager, 我们不建议将其替换掉, 因为:

当使用model继承时, model会继承 abstract base class model的model manager, 而不会继承非abstract base class的manager.

model的第一个model manager通常作为默认的manager, 当被替换时, 可能会发生不可预测的问题.

4. 数据库事务 (Transaction)

在django 1.6中, ORM默认会autocommit每一个数据库查询, 也就是说, 每次使用m.create()或m.update()时, 在数据库中马上就会做出相应的修 改. 这样做的好处就是简化了初学者对ORM的理解. 但坏处就是, 当一个view中包含两个数据库修改, 可能一个成功, 但另一个失败, 这就可能导致数据库不 完整, 给我们带来很大的危险.

解决这一问题的方法就是使用数据库transaction, 即将一系列数据库操作包含在一个transaction中, 当其中有一个失败时, 其他操作也会自动回退. Django 1.6 为我们带来了一套崭新的既简单又强大的transaction机制, 使我们方便的使用数据库transaction.

a. 将整个http request包裹在transaction中

django给我们提供了一个简单地方法, 将一个http request中的所有数据库操作包裹在transaction中:

只需要在数据库设置中加入\'ATOMIC_REQUESTS\': True选项, 就能将整个http request包裹在transaction中. 这样做的好处显而易见是是安全, 但 坏处则是性能可能会下降, 因此随着流量的增大, 我们必须采取更针对性的transaction. 其次, 需要注意的是, 回退的只是数据库的状态, 而不包括其他费 数据库项, 例如发送email等. 所以当涉及这些非数据库项时, 我们应当使用transaction.con_atomic_request()修饰(decorate)这些view:

b. 更明确地transaction控制

更明确地transaction控制意味着提高真题web app的性能, 但也意味着更多的开发时间. 大多数网站下, 由于有限的流量, 使用ATOMIC_REQUESTS已 经足够. 在使用手动transaction控制时, 应当注意:

不做数据修改的操作, 应当排除在transaction之外

做数据修改的操作, 则应在transaction内

特殊情况下, 可以违反以上两条

需要注意的是, 当view返回的是django.http.StreamingHttpResponse时, 应当设置ATOMIC_REQUESTS为false, 或使用 transaction.non_atomic_requests将该view修饰. 因为对于view本身, 是可以使用transaction的, 但对于之后生成的response stream触发的额 外SQL查询, 会自动变为django默认的autocommit模式.

django的model怎么测试(django model 查询)  第1张

Django Model层的设计一般是怎么进行的

model是数据库的设置,看你需要存储那些数据,就设置那些表,然后加入相应的字段

# Create your models here.

class user(models.Model):

    username = models.CharField(max_length=20, default=\'\') #name属性,字段

    password = models.CharField(max_length=50, default=\'\') #password属性,字段

    #此方法在print对象的时候,可以打印字符串,类似java中的toString()方法

    def __str__(self):

        return self.username + self.password

自己写的python程序怎么使用的django的models

在一个爬虫脚本中将爬取的数据通过django自带的model保存到数据库

修改的文件(其余pycharm新建Django项目生成,未修改):

# testapp/models.pyfrom django.db import models class Problem(models.Model): title = models.CharField(max_length=100, default=\"\") author = models.CharField(max_length=100, default=\"\")

def __str__(self): return self.title pass

# testapp/spider.pyimport osimport sysimport django pathname = os.path.dirname(os.path.abspath(__file__))sys.path.insert(0, pathname)sys.path.insert(0, os.path.abspath(os.path.join(pathname, \'..\')))os.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"testproject.settings\") django.setup() from testapp.models import Problem if __name__ == \"__main__\": p = Problem(title=\"hi\", author=\"hi\") p.save() pass

# testproject/setting.py......INSTALLED_APPS = [ \'django.contrib.admin\', \'django.contrib.auth\', \'django.contrib.contenttypes\', \'django.contrib.sessions\', \'django.contrib.messages\', \'django.contrib.staticfiles\', # 添加应用 \'testapp\',]......

# testapp/admin.py 在后台管理界面注册 Problemfrom django.contrib import admin # Register your models here. from testapp.models import Problemadmin.site.register(Problem)

如何解决Django 1.8在migrate时失败

1. 创建项目

运行下面命令就可以创建一个 django 项目,项目名称叫 mysite :

$ django-admin.py startproject mysite

创建后的项目目录如下:

mysite

├── manage.py

└── mysite

├── __init__.py

├── settings.py

├── urls.py

└── wsgi.py

1 directory, 5 files

说明:

__init__.py :让 Python 把该目录当成一个开发包 (即一组模块)所需的文件。 这是一个空文件,一般你不需要修改它。

manage.py :一种命令行工具,允许你以多种方式与该 Django 项目进行交互。 键入python manage.py help,看一下它能做什么。 你应当不需要编辑这个文件;在这个目录下生成它纯是为了方便。

settings.py :该 Django 项目的设置或配置。

urls.py:Django项目的URL路由设置。目前,它是空的。

wsgi.py:WSGI web 应用服务器的配置文件。更多细节,查看 How to deploy with WSGI

接下来,你可以修改 settings.py 文件,例如:修改 LANGUAGE_CODE、设置时区 TIME_ZONE

SITE_ID = 1

LANGUAGE_CODE = \'zh_CN\'

TIME_ZONE = \'Asia/Shanghai\'

USE_TZ = True

上面开启了 [Time zone]() 特性,需要安装 pytz:

$ sudo pip install pytz

2. 运行项目

在运行项目之前,我们需要创建数据库和表结构,这里我使用的默认数据库:

$ python manage.py migrate

Operations to perform:

Apply all migrations: admin, contenttypes, auth, sessions

Running migrations:

Applying contenttypes.0001_initial... OK

Applying auth.0001_initial... OK

Applying admin.0001_initial... OK

Applying sessions.0001_initial... OK

然后启动服务:

$ python manage.py runserver

你会看到下面的输出:

Performing system checks...

System check identified no issues (0 silenced).

January 28, 2015 - 02:08:33

Django version 1.7.1, using settings \'mysite.settings\'

Starting development server at

Quit the server with CONTROL-C.

这将会在端口8000启动一个本地服务器, 并且只能从你的这台电脑连接和访问。 既然服务器已经运行起来了,现在用网页浏览器访问 。你应该可以看到一个令人赏心悦目的淡蓝色 Django 欢迎页面它开始工作了。

你也可以指定启动端口:

$ python manage.py runserver 8080

以及指定 ip:

$ python manage.py runserver 0.0.0.0:8000

3. 创建 app

前面创建了一个项目并且成功运行,现在来创建一个 app,一个 app 相当于项目的一个子模块。

在项目目录下创建一个 app:

$ python manage.py startapp polls

如果操作成功,你会在 mysite 文件夹下看到已经多了一个叫 polls 的文件夹,目录结构如下:

polls

├── __init__.py

├── admin.py

├── migrations

│ └── __init__.py

├── models.py

├── tests.py

└── views.py

1 directory, 6 files

4. 创建模型

每一个 Django Model 都继承自 django.db.models.Model

在 Model 当中每一个属性 attribute 都代表一个 database field

通过 Django Model API 可以执行数据库的增删改查, 而不需要写一些数据库的查询语句

打开 polls 文件夹下的 models.py 文件。创建两个模型:

import datetime

from django.db import models

from django.utils import timezone

class Question(models.Model):

question_text = models.CharField(max_length=200)

pub_date = models.DateTimeField(\'date published\')

def was_published_recently(self):

return self.pub_date = timezone.now() - datetime.timedelta(days=1)

class Choice(models.Model):

question = models.ForeignKey(Question)

choice_text = models.CharField(max_length=200)

votes = models.IntegerField(default=0)

然后在 mysite/settings.py 中修改 INSTALLED_APPS 添加 polls:

INSTALLED_APPS = (

\'django.contrib.admin\',

\'django.contrib.auth\',

\'django.contrib.contenttypes\',

\'django.contrib.sessions\',

\'django.contrib.messages\',

\'django.contrib.staticfiles\',

\'polls\',

)

在添加了新的 app 之后,我们需要运行下面命令告诉 Django 你的模型做了改变,需要迁移数据库:

$ python manage.py makemigrations polls

你会看到下面的输出日志:

Migrations for \'polls\':

0001_initial.py:

- Create model Choice

- Create model Question

- Add field question to choice

你可以从 polls/migrations/0001_initial.py 查看迁移语句。

运行下面语句,你可以查看迁移的 sql 语句:

$ python manage.py sqlmigrate polls 0001

输出结果:

BEGIN;

CREATE TABLE \"polls_choice\" (\"id\" integer NOT NULL PRIMARY KEY AUTOINCREMENT, \"choice_text\" varchar(200) NOT NULL, \"votes\" integer NOT NULL);

CREATE TABLE \"polls_question\" (\"id\" integer NOT NULL PRIMARY KEY AUTOINCREMENT, \"question_text\" varchar(200) NOT NULL, \"pub_date\" datetime NOT NULL);

CREATE TABLE \"polls_choice__new\" (\"id\" integer NOT NULL PRIMARY KEY AUTOINCREMENT, \"choice_text\" varchar(200) NOT NULL, \"votes\" integer NOT NULL, \"question_id\" integer NOT NULL REFERENCES \"polls_question\" (\"id\"));

INSERT INTO \"polls_choice__new\" (\"choice_text\", \"votes\", \"id\") SELECT \"choice_text\", \"votes\", \"id\" FROM \"polls_choice\";

DROP TABLE \"polls_choice\";

ALTER TABLE \"polls_choice__new\" RENAME TO \"polls_choice\";

CREATE INDEX polls_choice_7aa0f6ee ON \"polls_choice\" (\"question_id\");

COMMIT;

你可以运行下面命令,来检查数据库是否有问题:

$ python manage.py check

再次运行下面的命令,来创建新添加的模型:

$ python manage.py migrate

Operations to perform:

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

Running migrations:

Applying polls.0001_initial... OK

总结一下,当修改一个模型时,需要做以下几个步骤:

修改 models.py 文件

运行 python manage.py makemigrations 创建迁移语句

运行 python manage.py migrate,将模型的改变迁移到数据库中

你可以阅读 django-admin.py documentation,查看更多 manage.py 的用法。

创建了模型之后,我们可以通过 Django 提供的 API 来做测试。运行下面命令可以进入到 python shell 的交互模式:

$ python manage.py shell

下面是一些测试:

from polls.models import Question, Choice # Import the model classes we just wrote.

# No questions are in the system yet.

Question.objects.all()

[]

# Create a new Question.

# Support for time zones is enabled in the default settings file, so

# Django expects a datetime with tzinfo for pub_date. Use timezone.now()

# instead of datetime.datetime.now() and it will do the right thing.

from django.utils import timezone

q = Question(question_text=\"What\'s new?\", pub_date=timezone.now())

# Save the object into the database. You have to call save() explicitly.

q.save()

# Now it has an ID. Note that this might say \"1L\" instead of \"1\", depending

# on which database you\'re using. That\'s no biggie; it just means your

# database backend prefers to return integers as Python long integer

# objects.

q.id

1

# Access model field values via Python attributes.

q.question_text

\"What\'s new?\"

q.pub_date

datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=UTC)

# Change values by changing the attributes, then calling save().

q.question_text = \"What\'s up?\"

q.save()

# objects.all() displays all the questions in the database.

Question.objects.all()

[Question: Question object]

打印所有的 Question 时,输出的结果是 [Question: Question object],我们可以修改模型类,使其输出更为易懂的描述。修改模型类:

from django.db import models

class Question(models.Model):

# ...

def __str__(self): # __unicode__ on Python 2

return self.question_text

class Choice(models.Model):

# ...

def __str__(self): # __unicode__ on Python 2

return self.choice_text

接下来继续测试:

from polls.models import Question, Choice

# Make sure our __str__() addition worked.

Question.objects.all()

[Question: What\'s up?]

# Django provides a rich database lookup API that\'s entirely driven by

# keyword arguments.

Question.objects.filter(id=1)

[Question: What\'s up?]

Question.objects.filter(question_text__startswith=\'What\')

[Question: What\'s up?]

# Get the question that was published this year.

from django.utils import timezone

current_year = timezone.now().year

Question.objects.get(pub_date__year=current_year)

Question: What\'s up?

# Request an ID that doesn\'t exist, this will raise an exception.

Question.objects.get(id=2)

Traceback (most recent call last):

...

DoesNotExist: Question matching query does not exist.

# Lookup by a primary key is the most common case, so Django provides a

# shortcut for primary-key exact lookups.

# The following is identical to Question.objects.get(id=1).

Question.objects.get(pk=1)

Question: What\'s up?

# Make sure our custom method worked.

q = Question.objects.get(pk=1)

# Give the Question a couple of Choices. The create call constructs a new

# Choice object, does the INSERT statement, adds the choice to the set

# of available choices and returns the new Choice object. Django creates

# a set to hold the \"other side\" of a ForeignKey relation

# (e.g. a question\'s choice) which can be accessed via the API.

q = Question.objects.get(pk=1)

# Display any choices from the related object set -- none so far.

q.choice_set.all()

[]

# Create three choices.

q.choice_set.create(choice_text=\'Not much\', votes=0)

Choice: Not much

q.choice_set.create(choice_text=\'The sky\', votes=0)

Choice: The sky

c = q.choice_set.create(choice_text=\'Just hacking again\', votes=0)

# Choice objects have API access to their related Question objects.

c.question

Question: What\'s up?

# And vice versa: Question objects get access to Choice objects.

q.choice_set.all()

[Choice: Not much, Choice: The sky, Choice: Just hacking again]

q.choice_set.count()

3

# The API automatically follows relationships as far as you need.

# Use double underscores to separate relationships.

# This works as many levels deep as you want; there\'s no limit.

# Find all Choices for any question whose pub_date is in this year

# (reusing the \'current_year\' variable we created above).

Choice.objects.filter(question__pub_date__year=current_year)

[Choice: Not much, Choice: The sky, Choice: Just hacking again]

# Let\'s delete one of the choices. Use delete() for that.

c = q.choice_set.filter(choice_text__startswith=\'Just hacking\')

c.delete()

上面这部分测试,涉及到 django orm 相关的知识,详细说明可以参考 Django中的ORM。

5. 管理 admin

Django有一个优秀的特性, 内置了Django admin后台管理界面, 方便管理者进行添加和删除网站的内容.

新建的项目系统已经为我们设置好了后台管理功能,见 mysite/settings.py:

INSTALLED_APPS = (

\'django.contrib.admin\', #默认添加后台管理功能

\'django.contrib.auth\',

\'django.contrib.contenttypes\',

\'django.contrib.sessions\',

\'django.contrib.messages\',

\'django.contrib.staticfiles\',

\'mysite\',

)

同时也已经添加了进入后台管理的 url, 可以在 mysite/urls.py 中查看:

url(r\'^admin/\', include(admin.site.urls)), #可以使用设置好的url进入网站后台

接下来我们需要创建一个管理用户来登录 admin 后台管理界面:

$ python manage.py createsuperuser

Username (leave blank to use \'june\'): admin

Email address:

Password:

Password (again):

Superuser created successfully.

总结

最后,来看项目目录结构:

mysite

├── db.sqlite3

├── manage.py

├── mysite

│ ├── __init__.py

│ ├── settings.py

│ ├── urls.py

│ ├── wsgi.py

├── polls

│ ├── __init__.py

│ ├── admin.py

│ ├── migrations

│ │ ├── 0001_initial.py

│ │ ├── __init__.py

│ ├── models.py

│ ├── templates

│ │ └── polls

│ │ ├── detail.html

│ │ ├── index.html

│ │ └── results.html

│ ├── tests.py

│ ├── urls.py

│ ├── views.py

└── templates

└── admin

└── base_site.htm

通过上面的介绍,对 django 的安装、运行以及如何创建视 图和模型有了一个清晰的认识,接下来就可以深入的学习 django 的自动化测试、持久化、中间件、国 际 化等知识。

在django rest framework的model序列化时,字段有可能是None时的处理办法

一,model字段

从Model定义中可以看到,env,release这些字段都有可能为None

二,过滤器

六,POSTMAN测试

结语:以上就是首席CTO笔记为大家整理的关于django的model怎么测试的全部内容了,感谢您花时间阅读本站内容,希望对您有所帮助,更多关于django的model怎么测试的相关内容别忘了在本站进行查找喔。

以上内容为新媒号(sinv.com.cn)为大家提供!新媒号,坚持更新大家所需的互联网后端知识。希望您喜欢!

版权申明:新媒号所有作品(图文、音视频)均由用户自行上传分享,仅供网友学习交流,不声明或保证其内容的正确性,如发现本站有涉嫌抄袭侵权/违法违规的内容。请发送邮件至 k2#88.com(替换@) 举报,一经查实,本站将立刻删除。

(0)
上一篇 2023-09-23 13:08
下一篇 2023-09-23 13:08

相关推荐

发表回复

登录后才能评论