【问题标题】:Django Admin: How to 'prepopulate' inline foreign key field based on parent modelDjango Admin:如何基于父模型“预填充”内联外键字段
【发布时间】:2012-02-23 08:28:03
【问题描述】:

this question 上的一些 cmets 表示有更直接和最新的解决方案。 (没找到)

(cmets 喜欢:“是的,它已经解决了。只需在参数中传递相关实例,它就会预先填充它......”让我觉得现在很容易,但我仍然无法让它工作)

问题是我想向一些参与给定事件并由管理员选择的用户发送通知。 工作人员在事件页面上,选择事件并保存它,然后 inline 中的 fk 字段应预先填充相关的用户名。 (并等待工作人员检查它们或取消选中它们以接收电子邮件通知)

出于可用性原因,这应该采取内联形式至关重要,因为已经有很多页面要通过来从员工那里收集所有必要的信息。

有什么想法吗?

class When(models.Model):
    ...
    Date = models.DateTimeField(unique=True)
    Nameofevent = models.ForeignKey(Event, to_field='Name') #the Event model gets then username from models.ManyToManyField(User, through='Role')
    ...
    def getteam(self):
        teamlist = self.Nameofevent.Roleinevent.all() # gathering users which are involved
        return teamlist
    getteamresult = property(getteam)

class Notice(models.Model): #this will go to the inline
    ...
    Who = models.ForeignKey(User, blank=True)
    To_notice_or_not_to_notice = models.BooleanField(default=False)
    ...

class NoticeInline(admin.TabularInline):
    model = Notice
    extra = 9

class WhenAdmin(admin.ModelAdmin):
    list_display = ('Date', ...)
    readonly_fields = ('getteamresult', ) #this is to make clear i have access to what i want and i can display it. prints out as [<User: someone>, <User: someoneelse>]
    inlines = [NoticeInline] #but i want the User objects to prepopulate foreign field here in inline model
admin.site.register(When,WhenAdmin)

【问题讨论】:

  • 为什么不通过在用户模型上创建一个过滤器来过滤所有收到(或未收到)通知的用户来解决这个问题?然后您可以创建一个发送通知的管理操作。
  • 步骤是:过滤与给定戏剧有关系的用户。而不是让工作人员指出他们中的哪些人将收到给定重演(事件)的通知 - 并非所有这些都是必要的(例如,导演没有参加所有重演)。此操作是在工作人员提交有关此特定事件的所有其他信息时完成的。
  • 这样就清楚多了。那么为什么不通过将多对多事件链接到用户来解决它呢?它可以是像filter_horizontalinline 这样的小部件。然后,您可以向这些用户发送通知。
  • 我试图减少问题以使问题清晰,但这并不是那么简单。用户不是直接 M-M 到事件。有很多中间模型,如“角色”、“角色名称”等,它们在关系中生效。剧院环境相当复杂,有时甚至是混乱的。我想让非技术人员尽可能轻松地填写我需要的所有信息:电子邮件通知、网页生成、为所有相关人员定制的时间表……现在我离我的圣杯;-)
  • 除非您明确说明您想要什么,否则我们无法真正帮助您。

标签: django django-admin inline


【解决方案1】:

我不相信内联是解决此类问题的方法。如果应提示员工向事件中涉及的用户发送电子邮件,并且需要控制实际通知哪些用户,那么您应该使用中间视图。

首先,您需要一个可以让您选择属于​​该事件的用户的表单。最初,我们将 users 字段设置为所有用户,但在表单的 __init__ 方法中,我们将采用“event” kwarg 并根据该字段过滤字段。

class UserNotifyForm(forms.Form):
    users = forms.ModelMultipleChoiceField(queryset=User.objects.all(), widget=forms.CheckboxSelectMultiple())

    def __init__(self, *args, **kwargs):
        event = kwargs.pop('event')
        super(UserNotifyForm, self).__init__(*args, **kwargs)
        if event:
            self.fields['users'].queryset = event.users.all()

其次,您在 ModelAdmin 上创建一个视图,其行为与普通表单视图一样:

def notify_users_view(self, request, object_id):
    event = get_object_or_404(Event, id=object_id)
    if len(request.POST):
        form = UserNotifyForm(request.POST, event=event)
        if form.is_valid():
            users = form.cleaned_data.get('users')
            # send email
            return HttpResponseRedirect(reverse('admin:yourapp_event_changelist'))
    else:
        form = UserNotifyForm(event=event)

    return render_to_response('path/to/form/template.html', {
        'event': event,
        'form': form,
    }, context_instance=RequestContext(request))

您当然需要为此创建模板,但这很简单。该表单已设置为显示一个复选框列表,每个用户一个,因此您可以在那里获得所需的所有信息。

第三,将此视图绑定到您的ModelAdmin 的网址中:

def get_urls(self):
    urls = super(MyModelAdmin, self).get_urls()

    info = (self.model._meta.app_label, self.model._meta.module_name)

    my_urls = patterns('',
        (r'^(?P<object_id>\d+)/notify/$', self.notify_users_view, name='%s_%s_notify' % info)
    )
    return my_urls + urls

第四,覆盖change_view保存后重定向到这个视图:

def change_view(self, request, object_id, extra_context=None):
    response = super(MyModelAdmin, self).change_view(request, object_id, extra_context=extra_context)
    if len(request.POST):
        info = (self.model._meta.app_label, self.model._meta.module_name)
        response['Location'] = reverse('admin:%s_%s_notify', args=(object_id,))
    # Note: this will effectively negate the 'Save and Continue' and
    # 'Save and Add Another' buttons. You can conditionally check
    # for these based on the keys they add to request.POST and branch
    # accordingly to some other behavior you desire.
    return response

【讨论】:

  • 谢谢,我正在努力获得您的大部分答案,但我绝对必须将它与“何时”模型一起放在一页上。否则它将变得一团糟,并导致可用性灾难。最后,他们不会使用它。而且我相信这是可能的,我有我需要的所有信息,只是为了将它们连接在一起......如果 Django 方式失败,我必须用 js 实现它(即使我的 js 技能很烂)
猜你喜欢
  • 2010-12-25
  • 2017-03-17
  • 1970-01-01
  • 2016-03-25
  • 2017-10-26
  • 2010-11-26
  • 2011-08-09
  • 2017-03-27
  • 2013-06-25
相关资源
最近更新 更多