2 Stimmen

Django Admin: Wie man ein inline Fremdschlüsselfeld basierend auf dem übergeordneten Modell 'vorabfüllt'

Einige Kommentare zu dieser Frage deuten darauf hin, dass es eine einfachere und aktuellere Lösung gibt. (Ich habe keine gefunden)

(Kommentare wie: "Ja, es ist gelöst. Übergeben Sie einfach die zugehörige Instanz als Parameter, und sie wird vorab ausgefüllt..." lassen mich glauben, dass es jetzt einfach ist, aber ich kann es immer noch nicht zum Laufen bringen)

Die Sache ist die, dass ich Benachrichtigungen an einige Benutzer senden möchte, die an einem bestimmten Ereignis beteiligt sind und vom Administrationspersonal ausgewählt wurden. Das Personalmitglied befindet sich auf der Seite des Ereignisses, wählt das Ereignis aus und speichert es, dann sollten die Fremdschlüsselfelder im Inline mit den beteiligten Benutzernamen vorab ausgefüllt werden. (Und warten darauf, dass das Personalmitglied sie überprüft oder abwählt, um eine E-Mail-Benachrichtigung zu erhalten)

Aus Gründen der Benutzerfreundlichkeit ist es entscheidend, dass dies in Form eines Inline erfolgt, da bereits viele Seiten durchgegangen werden müssen, um alle erforderlichen Informationen vom Personal zu sammeln.

Ideen?

class When(models.Model):
    ...
    Datum = models.DateTimeField(unique=True)
    Nameofevent = models.ForeignKey(Event, to_field='Name') #das Event-Modell ruft dann den Benutzernamen von models.ManyToManyField(User, through='Role') ab
    ...
    def getteam(self):
        teamliste = self.Nameofevent.Roleinevent.all() # Benutzer sammeln, die beteiligt sind
        return teamliste
    getteamresult = property(getteam)

class Notice(models.Model): #dies wird in den Inline gehen
    ...
    Wer = models.ForeignKey(User, blank=True)
    Zu_beachten_oder_nicht_zu_beachten = models.BooleanField(default=False)
    ...

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

class WhenAdmin(admin.ModelAdmin):
    list_display = ('Datum', ...)
    readonly_fields = ('getteamresult', ) #dies dient dazu, deutlich zu machen, dass ich Zugriff auf das habe, was ich will und es anzeigen kann. wird ausgegeben als [, ]
    inlines = [NoticeInline] #aber ich möchte, dass die Benutzerobjekte das Fremdfeld hier im Inline-Modell vorab ausfüllen
admin.site.register(When,WhenAdmin)

1voto

Chris Pratt Punkte 219403

Ich glaube nicht, dass Inlines für so etwas der richtige Weg sind. Wenn das Personalmitglied aufgefordert werden soll, Benutzer, die an der Veranstaltung beteiligt sind, per E-Mail zu benachrichtigen und die Kontrolle darüber haben muss, welche tatsächlich benachrichtigt werden, sollten Sie eine Zwischenansicht verwenden.

Zuerst benötigen Sie ein Formular, mit dem Sie Benutzer auswählen können, die zur Veranstaltung gehören. Zunächst setzen wir das users-Feld einfach auf alle Benutzer, aber in der __init__-Methode des Formulars nehmen wir den "event" kwarg und filtern das Feld basierend darauf.

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()

Zweitens erstellen Sie eine Ansicht auf Ihrem ModelAdmin, die sich genauso verhält wie eine normale Formularansicht:

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')
            # E-Mail senden
            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))

Sie müssen natürlich ein Template dafür erstellen, aber das ist einfach genug. Das Formular ist bereits so eingerichtet, dass es eine Liste von Kontrollkästchen anzeigt, eins für jeden Benutzer, sodass Sie dort alle Informationen haben, die Sie benötigen.

Drittens, binden Sie diese Ansicht in die URLs Ihres ModelAdmin ein:

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\d+)/notify/$', self.notify_users_view, name='%s_%s_notify' % info)
    )
    return my_urls + urls

Viertens überschreiben Sie die change_view-Methode, um nach dem Speichern zu dieser Ansicht umzuleiten:

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,))
    # Hinweis: Dadurch werden die Schaltflächen "Speichern und Weiter" sowie "Speichern und Hinzufügen eines weiteren" effektiv aufgehoben.
    # Sie können bedingt überprüfen, ob diese basierend auf den Schlüsseln, die sie zu request.POST hinzufügen, und dementsprechend zu einem anderen gewünschten Verhalten verzweigen.
    return response

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X