0

我有以下型号

class Peri(models.Model):
    #fields

class Task(models.Model):
    #fields
    peri = models.ForeignKey(Peri)

我正在创建一个 javascript 客户端来创建新的 Peri 和任务。在创建新的 Peri 模型以预先创建必要的任务时,我想对自己轻松一点。每个 Peri 最多有 64 个任务。所以我想预先创建它们,然后让用户从 javascript 客户端/前端编辑它们。创建是使用 ajax 和 django-rest-framework 完成的。我使用 ajax 调用来创建 peri 模型,如果成功,我将创建任务

$.ajax({
    dataType: 'json',
    url: 'api/url',
    data: newPeriInstance,
    success: function (data, textStatus, jqXHR){
        for (var i = 0; i < 64; i++){
            $.ajax({
                dataType:'json',
                data: newTaskInstance,
                url: '/api/url/tasks/',
                success: function (data, textStatus, jqXHR){
                    //code for success
                },
                error: function (jqXHR, textStatus, errorThrown){
                    //code for error
                }
            });
        }
});

问题是我收到锁定数据库的错误。我在开发阶段使用 sqlit,但我不确定这不会在更大的生产规模中发生。我怎样才能通过这个问题?

Internal Server Error: /crm/api/peritasks/
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 114, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/csrf.py", line 57, in wrapped_view
    return view_func(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/rest_framework/viewsets.py", line 79, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/rest_framework/views.py", line 403, in dispatch
    response = self.handle_exception(exc)
  File "/usr/local/lib/python2.7/dist-packages/rest_framework/views.py", line 400, in dispatch
    response = handler(request, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/rest_framework/mixins.py", line 54, increate
    self.object = serializer.save(force_insert=True)
  File "/usr/local/lib/python2.7/dist-packages/rest_framework/serializers.py", line 595, in save
    self.save_object(self.object, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/rest_framework/serializers.py", line 1037, in save_object
    obj.save(**kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 545, in save
    force_update=force_update, update_fields=update_fields)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 573, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 654, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/base.py", line 687, in _do_insert
    using=using, raw=raw)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 232, in _insert
    return insert_query(self.model, objs, fields, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 1511, in insert_query
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 898, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/util.py", line 69, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/util.py", line 53, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/utils.py", line 99, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/util.py", line 53, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/sqlite3/base.py", line 450, in execute
    return Database.Cursor.execute(self, query, params)
OperationalError: database is locked
4

3 回答 3

2

SQLite does not allow row-level locking like many other database systems do, which is one of the many reasons why it's not the greatest development or production database. It only supports database-level locks for write operations, so when you have multiple requests coming in making writes, only one is allowed to do it. Eventually you are guaranteed to hit a timeout or a locking issue, which is what you are seeing here.

So, you have a few options in your situation for preventing the locking.

  1. Don't create the tasks ahead of time. This is the easiest way as far as initial implementation, but it requires the rest of your code base to be able to handle partial or nonexistent task lists.

  2. Create the tasks lists at the time of the parent object creation. This would require modifying the create method for the Peri model's view, but you would avoid the need for clients to do it. You can use the bulk_create method that Django provides to create all of the tasks in a single transaction, and you wouldn't hit many speed issues.

于 2014-12-22T14:41:50.123 回答
0

虽然存在不预先创建任务的论点,但如果有此要求,您可以扩展当前的 API 视图,以便它接受许多要创建的任务(或始终创建 64 个)并构建一个列表并使用Django 的 bulk_create 方法。

这取决于您从 DRF 使用的 APIView,但作为一个想法:

class MyApiView(baseview):
    def create(*args):
        model = super(MyAPIView, self).create(*args)
        tasks = []
        for i in range(0, 64):
            tasks.append(Task(...))

        Task.objects.bulk_create(tasks)
        return model
于 2014-12-22T14:39:16.513 回答
0

在 for 循环中发送这么多 Ajax 调用不是一个好主意。在 Peri 模型中创建任务:

class Peri(models.Model):

    # fields

    def save(self, *args, **kwargs):
        # Create tasks here
        super(Peri, self).save(*args, **kwargs)
于 2014-12-22T13:17:30.033 回答