拥有删除权限获取django admin内联中的父实例

拥有删除权限获取django admin内联中的父实例,django,python-2.7,django-admin,Django,Python 2.7,Django Admin,我有一个带有用户外键的预订模型。在管理员界面中,预订被内联在用户更改页面中 我想防止在预订前不到24小时且登录用户不在SuperStaff组中时删除某些预订(从内联) 所以我对BookingLine的定义如下: class BookingInline(admin.TabularInline): model = Booking extra = 0 fk_name = 'bookedFor' def has_delete_permission(self, reque

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

我想防止在预订前不到24小时且登录用户不在SuperStaff组中时删除某些预订(从内联)

所以我对BookingLine的定义如下:

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
这段代码已经到达,但我得到的是一个用户实例,而不是一个预订实例(当然还有一个错误),因此无法决定是否可以删除每个内联预订。 在这种情况下,has_delete_permission()方法不应该获取内联对象实例吗?django文档中没有任何内容

我知道代码已经到达,因为我只使用了user上的条件进行了检查,它实际上隐藏了相应用户的delete框

我还尝试用另一种方法,通过Formset和clean()方法,但它没有request参数,所以我得到了所需的实例,但没有登录的用户

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


如果你能想出一个好办法,我将不胜感激。

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

只有在特定字段具有特定值时,我才必须使内联线可删除。具体地说,由于我处理的是一般性任务和分配,只有不可接受的任务才可以删除。就范本而言:

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])
由于我不能在我的
admin.tablerinline
类中使用
has\u delete\u permission
,因为它引用整个字段集(即所有内联线),而不是单行,所以我通过了模板覆盖的路径:

tabular.html:44-62(原件)

[…]
{inline_admin_form%}中的字段集为%
{字段集%中的行的%s}
{第%行中的字段为%1}
{%if not field.field.is_hidden%}
{%if field.is_readonly%}
{{field.contents}

{%else%} {{field.field.errors.as_ul}} {{field.field} {%endif%} {%endif%} {%endfor%} {%endfor%} {%endfor%} {%if inline_admin_formset.formset.can_delete%} {%if inline_admin_form.original%}{{inline_admin_form.deletation_field.field}{%endif%} {%endif%} [...]
tabular.html(被覆盖)

[…]
{inline_admin_form%}中的字段集为%
{字段集%中的行的%s}
{第%行中的字段为%1}
{%if not field.field.is_hidden%}
{%if field.is_readonly%}
{{field.contents}

{%else%} {%include“admin/includes/field.html”和is_tabular=True%} {%endif%} {%endif%} {%endfor%} {%endfor%} {字段集%中的行的%s} {第%行中的字段为%1} {%if-field.field.name==“状态”%} {%if-field.field.value==“PND”%} {%if inline_admin_form.original%}{{inline_admin_form.deletation_field.field}{%endif%} {%else%} {%endif%} {%endif%} {%endfor%} {%endfor%} {%endfor%} [...]
因此(我使用的是非标准图形):

严格地说“优雅”,我必须两次通过行的字段才能使其工作,但我没有找到比直接读取该字段的值更好的方法。我不能让像
{{line.fields.0.status}}
{{line.fields.status}}
这样的工作。如果有人能指出直接语法,我很乐意更新我的解决方案


无论如何,因为它仍然有效,而且还没有那么糟糕,所以我会一直使用这个方法,直到有更好的结果出现。

您可以在formset的clean()方法中检查条件


请注意,此处没有请求对象,因此无法检查isSuperStaff()

显然,这确实是访问内联对象的唯一可能方法。内联管理类和表单集只操作基本模型实例。
[...]
{% 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 %}
[...]
[...]
{% 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 %}
-->
[...]
class BookingFormSet(forms.BaseInlineFormSet):
    def clean(self):
        super().clean()
        has_errors = False
        for form in self.deleted_forms:
            if form.instance.is24hoursFromNow():
                form._errors[NON_FIELD_ERRORS] = self.error_class(['Not allowed to delete'])
                has_errors = True

        if has_errors:
            raise forms.ValidationError('Please correct the errors below')

class BookingInline(admin.TabularInline):
    model = Booking
    formset = BookingFormSet