has_delete_permission在django admin inline中获取父实例

ole*_*sse 6 django django-admin python-2.7

我有一个带有用户外键的预订模型.在管理员中,预订在用户更改页面中内联.

我想在预订前不到24小时阻止某些预订被删除(来自内联)并且记录的用户不在SuperStaff组中.

所以我定义了类似的BookingInline:

class BookingInline(admin.TabularInline):
    model = Booking
    extra = 0
    fk_name = 'bookedFor'

    def has_delete_permission(self, request, obj=None):
        if not request.user.profile.isSuperStaff() and obj.is24hoursFromNow():
            return True
        return False
Run Code Online (Sandbox Code Playgroud)

这个代码已经到达,但是我得到了一个User实例,而不是Booking实例(当然还有一个错误),因此无法决定每个内联预订是否可以删除.在这种情况下,has_delete_permission()方法是不是应该获取内联对象实例?django文档中没有任何内容......

我知道代码已到达,因为我只使用用户的条件检查它,它实际上隐藏了适当用户的删除框.

我还尝试通过Formset和clean()方法以其他方式执行此操作,但它没有请求参数,因此我获得了所需的实例,但没有登录的用户.

我已经搜索了几个小时的解决方案,但似乎唯一的方法是从内联链接到Booking对象的完整更改页面,并在用户尝试定期删除预订时检查权限.

任何想法如何以优雅的方式完成将不胜感激.

See*_*her 4

我今天面临着完全相同的问题,我想我已经找到了一个可以接受的方法来解决它。这就是我所做的:

仅当特定字段具有特定值时,我才必须使内联可删除。具体来说,当我处理通用任务和分配时,只有未接受的任务才必须删除。在模型方面:

class Task(models.Model):
    STATUS_CHOICES = (
        ('PND', 'Pending'),
        ('ACC', 'Accepted'),
    )
    status = models.CharField(       ----> If this != 'PND', inline instance 
        max_length=3,                      should not be deletable
        choices=STATUS_CHOICES,
        default=STATUS_CHOICES[0][0])
Run Code Online (Sandbox Code Playgroud)

由于我也无法has_delete_permission在我的admin.TabularInline类中使用,因为它引用整个字段集(即所有内联)而不是单行,所以我经历了模板覆盖的路径:

tabular.html:44-62(原始)

[...]
{% for fieldset in inline_admin_form %}
  {% for line in fieldset %}
    {% for field in line %}
      {% if not field.field.is_hidden %}
      <td{% if field.field.name %} class="field-{{ field.field.name }}"{% endif %}>
      {% if field.is_readonly %}
          <p>{{ field.contents }}</p>
      {% else %}
          {{ field.field.errors.as_ul }}
          {{ field.field }}
      {% endif %}
      </td>
      {% endif %}
    {% endfor %}
  {% endfor %}
{% endfor %}
{% if inline_admin_formset.formset.can_delete %}
  <td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td>
{% endif %}
[...]
Run Code Online (Sandbox Code Playgroud)

tabular.html(已覆盖)

[...]
{% for fieldset in inline_admin_form %}
  {% for line in fieldset %}
    {% for field in line %}
      {% if not field.field.is_hidden %}
      <td{% if field.field.name %} class="field-{{ field.field.name }}"{% endif %}>
      {% if field.is_readonly %}
        <p>{{ field.contents }}</p>
      {% else %}
        {% include "admin/includes/field.html" with is_tabular=True %}
      {% endif %}
      </td>
      {% endif %}
    {% endfor %}
  {% endfor %}

  <!-- Custom deletion logic, only available for non-accepted objects -->
  {% for line in fieldset %}
    {% for field in line %}
      {% if field.field.name == "status" %}
        {% if field.field.value == "PND" %}
          <td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td>
        {% else %}
          <td class="delete"><input type="checkbox" disabled="disabled">
          <img src="/static/admin/img/icon_alert.gif" data-toggle="tooltip" class="title-starter"
          data-original-title="Can't remove accepted tasks" />
          </td>
        {% endif %}
      {% endif %}
    {% endfor %}
  {% endfor %}

{% endfor %}

<!-- Classic deletion, removed
{% if inline_admin_formset.formset.can_delete %}
  <td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td>
{% endif %}
-->
[...]
Run Code Online (Sandbox Code Playgroud)

结果(非标准图形,因为我正在使用django-admin-bootstrap):

在此输入图像描述

严格来说“优雅”,我必须两次遍历行的字段才能使其工作,但我还没有找到任何更好的方法,例如直接读取该字段的值。我无法拥有任何类似的东西{{ line.fields.0.status }}{{ line.fields.status }}工作。如果有人可以指出直接语法,我很乐意更新我的解决方案。

不管怎样,因为它仍然有效,而且并没有那么糟糕,所以我会很好地使用这种方法,直到有明显更好的结果出现。