在代码库中实现软删除的最佳方法是什么(特别是Django项目)?
我认为最简单的方法是简单地添加:
is_deleted = models.BooleanField(default=False)
Run Code Online (Sandbox Code Playgroud)
到一个实现a的超类softDeleteObject,然后重写delete()以在相关对象上设置适当的标志.相关对象还需要从同一个超类继承.
另一种方法是删除原始文件,并将其等于存档对象,该对象是已删除对象的表示.
第一个似乎具有更大程度的简单性,但确实需要一些广泛的覆盖 - 例如,User必须重写以确保所有已删除对象的外键关系仍然保持,并且删除用户然后没有' t hard删除所有软删除的对象.
第二个可以用pre_delete信号实现,该信号触发代理对象的创建.这又有一些优点(不需要覆盖所有delete()方法),但确实需要实现项目中使用的模型的存档版本.
哪个更好,还有其他选择吗?
MySQL 5.6.4及更高版本扩展了对TIME,DATETIME和TIMESTAMP值的小数秒支持,精度高达微秒(6位):http://dev.mysql.com/doc/refman/5.6/en/fractional-seconds html的
Django 1.5及以上支持小数秒作为imputformat:https://docs.djangoproject.com/en/1.5/ref/settings/#datetime-input-formats
但DATETIME(6)字段尚未在Django中实现. https://code.djangoproject.com/ticket/19716
我决定编写一个自定义的DateTimeFractionField.它是具有DATETIME([1-6])db_type的标准DateTimeField.'precicion'用于设置毫秒,微秒或任何其他分数精度.
class DateTimeFractionField(models.DateTimeField):
description = "Datetimefield with fraction second."
def __init__(self, precision, *args, **kwargs):
self.precision = precision
super(DateTimeFractionField, self).__init__(*args, **kwargs)
def db_type(self, connection):
return 'DATETIME(%s)' % self.precision
class MyModel(models.Model):
dt_micros = DateTimeFractionField(6)
dt_millis = DateTimeFractionField(3)
dt = models.DateTimeField()
def __unicode__(self):
return "%s - %s" %(self.dt_micros, self.dt_millis)
Run Code Online (Sandbox Code Playgroud)
mysql后端负责用0替换毫秒.Django文档建议编写我自己的后端.https://docs.djangoproject.com/en/1.5/ref/settings/#engine
我砍了:
$ cd /path/to/site-packages/django/db/backends/
$ cp -r mysql mysql564
Run Code Online (Sandbox Code Playgroud)
并修改了mysql564/base.py:
42:45行
from django.db.backends.mysql564.client import DatabaseClient
from django.db.backends.mysql564.creation import DatabaseCreation
from …Run Code Online (Sandbox Code Playgroud) 尝试unique_together在两个外键约束上使用时,出现以下错误:
CommandError: System check identified some issues:
ERRORS:
main.AuthorTag: (models.E012) 'unique_together' refers to the non-existent field 'author'.
main.AuthorTag: (models.E012) 'unique_together' refers to the non-existent field 'tag'.
Run Code Online (Sandbox Code Playgroud)
在下表中
class AuthorTag(models.Model):
class Meta:
unique_together = (('tag', 'author',),)
tag = models.ForeignKey(TagIndex, on_delete=models.CASCADE),
author = models.ForeignKey(Author, on_delete=models.CASCADE),
Run Code Online (Sandbox Code Playgroud)
同样的例子似乎在这里工作:Unique外键对与 Django 但我不明白为什么我会收到这个错误
编辑:改变unique_together = (('tag', 'author',),)来unique_together = (('tag', 'author'))给我同样的错误。以及将元类移动到字段声明下方。
我有一个复杂的代码块来处理 ORM 对象关系的创建/更新。
假设模型是 A 和 B,关联是 OneToOne A - B(A.b_line指向 B)。
1)在创建/更新关联之前,需要更新一些A对象并将其保存到数据库中。在此操作期间,将计算并保存 A 对象的一些内部字段。
2)更新的A对象从db重新加载(因为我们需要派生的计算字段)并且可以继续与B对象的关联。
例子:
def update_and_associate(a_items):
with transaction.atomic():
for item in a_items:
item.field_alpha = 1
# updates item.field_beta depending on
# item.field_alpha
item.update_beta()
item.save() # Save to db
with transaction.atomic:
for item in a_items:
item.refresh_from_db()
b = item.b_line
b.total = a.field_beta
b.save()
# later...
try:
update_and_associate(items)
except Exception as e:
handle_exception(e)
Run Code Online (Sandbox Code Playgroud)
我将代码封装在嵌套原子事务块中,以便如果发生任何异常,则应回滚更改(带有 InnoDB 的 MySql)。
问题是,在第二个原子块中,当我重新加载项目时,refresh_from_db它们不同步,这意味着它们具有旧值,就好像第一个事务块根本没有运行一样。
我认为任何更改都会尽快提交,但如果出现异常,我们仍然有可能回滚。
所以我的问题是:通过将代码括起来transaction.atomic意味着要对数据库执行的所有写入修改都会推迟到我们退出该块为止?这可以解释为什么数据库中刷新的项目具有旧值。
我每 5 秒收到大约 5000 个工具的财务数据,需要更新数据库中的相应条目。该模型如下所示:
class Market(models.Model):
market = models.CharField(max_length=200)
exchange = models.ForeignKey(Exchange,on_delete=models.CASCADE)
ask = models.FloatField()
bid = models.FloatField()
lastUpdate = models.DateTimeField(default = timezone.now)
Run Code Online (Sandbox Code Playgroud)
需要发生的事情如下:
我的代码如下所示:
bi_markets = []
for item in dbMarkets:
eItem = Market.objects.filter(exchange=item.exchange,market=item.market)
if len(eItem) > 0:
eItem.update(ask=item.ask,bid=item.bid)
else:
bi_markets.append(item)
#Bulk insert items that does not exist
Market.objects.bulk_create(bi_markets)
Run Code Online (Sandbox Code Playgroud)
但是,执行此操作需要的时间太长。大约 30 秒。我需要将时间减少到 1 秒。我知道这可以在 100 毫秒内完成,因为我在 .NET 中执行相同的自定义 SQL 代码。知道如何提高 Django 的性能吗?
让\xe2\x80\x99s 说我有一个类Child通过FK 链接到另一个类Parent。现在让\xe2\x80\x99s 说我有一个代码块在模板中执行类似的操作
<td>{{ child.parent.name }}</td>\n<td>{{ child.parent.age}}</td>\n<td>{{ child.parent.address }}</td>\nRun Code Online (Sandbox Code Playgroud)\n\n我的第一个问题是,Django会去数据库读取Parent实体三遍吗?我的第二个问题是:如果是,最好不要多次阅读它是什么?我的意思是我知道我可以在这个块之前声明一个对象并将其设置为等于,child.parent但是还有其他方法可以做到这一点吗?
我认为这会是之前提出的问题,所以也许我的措辞不正确。
我试过:
manage.py python3.6 dbshell
Run Code Online (Sandbox Code Playgroud)
进而:
obj= Person.objects.create('Justin')
Run Code Online (Sandbox Code Playgroud)
但这不起作用。谢谢你的帮助。
首先,我是在这里提问的新手,所以如果我做得不完美,请耐心等待:) 这是...
我正在设置一个处理统计信息的 Django2.0 API。它显然有自己的“默认”数据库来写东西,但我将需要其他几个只读的数据库。这就是现在的设置。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'dev_gpws',
'USER': 'dev_gpws_user',
'PASSWORD': 'gpws_pwd',
'HOST': 'localhost',
'PORT': '5432',
},
'other_db': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'other_db_name',
'USER': 'other_db_user',
'PASSWORD': 'other_db_pwd',
'HOST': 'other_db_host',
'PORT': '5432',
},
}
Run Code Online (Sandbox Code Playgroud)
fabric 将项目部署到 staging 时,部分例程为./manage.py test,导致如下错误:
(gpws) dev_gpws@af968cdb7653:~/gpws/project$ ./manage.py test
Creating test database for alias 'default'...
Creating test database for alias 'other_db'...
Got an error creating the test database: ERREUR: permission denied to create database
Run Code Online (Sandbox Code Playgroud)
考虑到other_db_user是只读用户,这是完全有意义的,所以我想禁用 django 对此数据库的测试。有没有干净的方法来做到这一点?此外,此统计应用程序稍后将与相当多的数据库链接,因此我宁愿使用易于扩展的解决方案。 …
我正在遵循关于如何在一个 Django 项目中处理多个数据库的说明,来自这里的topics/db/multi-db
我已经创建了所需的两个路由器。它们被保存为 ./database_routers/discourse.py 和 ./database_routers/wordpress.py
./database_routers/discourse.py 的内容是
class DiscourseRouter:
"""
A router to control all database operations on models in the
discourse application.
"""
def db_for_read(self, model, **hints):
"""
Attempts to read discourse models go to discourse.
"""
if model._meta.app_label == 'discourse':
return 'discourse'
return None
def db_for_write(self, model, **hints):
"""
Attempts to write discourse models go to discourse.
"""
if model._meta.app_label == 'discourse':
return 'discourse'
return None
def allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if …Run Code Online (Sandbox Code Playgroud) 我正在开发具有多个数据库的 Django 项目。在应用程序中,我需要根据用户的请求将数据库连接从 Development-Database 切换到 Test-DB 或 Production-DB。(数据库架构已设置且不可更改!)
我也在这里用这个旧指南试了运气 不起作用。在数据库路由器中,我无法访问 threading.locals。
我也尝试过设置自定义数据库路由器。通过会话变量,我尝试设置连接字符串。要读取 dbRouter 中的用户会话,我需要确切的会话密钥,否则我必须循环抛出所有会话。
object.using('DB_CONNECTION) 的方式是不可接受的解决方案......对于许多依赖项。我想为登录用户全局设置连接,而不为每个模型功能提供数据库连接......
请给我一些如何解决这个问题的意见。
我应该能够根据会话值在数据库路由器中返回 dbConnection...
def db_for_read|write|*():
from django.contrib.sessions.backends.db import SessionStore
session = SessionStore(session_key='WhyINeedHereAKey_SessionKeyCouldBeUserId')
return session['app.dbConnection']
Run Code Online (Sandbox Code Playgroud)
更新 1: 感谢 @victorT 的贡献。我只是用给定的例子尝试过。还是没有达到目标……
这是我尝试过的。可能你会看到一个配置错误。
Django Version: 2.1.4
Python Version: 3.6.3
Exception Value: (1146, "Table 'app.myModel' doesn't exist")
Run Code Online (Sandbox Code Playgroud)
.app/views/myView.py
from ..models import myModel
from ..thread_local import thread_local
class myView:
@thread_local(DB_FOR_READ_OVERRIDE='MY_DATABASE')
def get_queryset(self, *args, **kwargs):
return myModel.objects.get_queryset()
Run Code Online (Sandbox Code Playgroud)
.app/myRouter.py
from .thread_local import get_thread_local
class myRouter:
def db_for_read(self, model, **hints): …Run Code Online (Sandbox Code Playgroud) django django-middleware django-models django-database django-sessions
django ×10
django-database ×10
python ×2
architecture ×1
atomic ×1
django-admin ×1
django-forms ×1
django-orm ×1
django-tests ×1
module ×1
python-3.x ×1