Input widget anstatt select für ForeignKey field

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
lunas
User
Beiträge: 87
Registriert: Samstag 2. Dezember 2006, 10:56

Hi,

ich möchte gerne in einem Django Form (ModelForm) anstatt einer Combobox ein Input Field erhalten für ein ForeignKey Feld erhalten.
Folgendes Scenario:

Code: Alles auswählen

# form
class AddPersonForm(forms.ModelForm):
  user = forms.CharField()
  class Meta:
    model = models.Person

form = AddPersonForm()

# model
class Person(models.Model):
  user = models.ForeignKey(User)
  blah = models.CharField()
Unter http://docs.djangoproject.com/en/dev/to ... ield-types wird beschrieben wie es geht, aber wenn ich, wie in meinem Beispiel, ein eigenes widget wähle, dann kann ich lediglich den Primary Key editieren. Ich möchte jedoch 'user.username' editieren und ggf. neu anlegen (was ein ganz anderes Problem ist, form.save() wird hier wohl nicht funktionieren).

Hat jemand einen Rat?

Danke,
lunas
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Dachte, so schwer kann das doch nicht sein und habe mir jetzt ganz schön die Ohren abgebrochen, um folgende Lösung zusammenzuschreiben:

Code: Alles auswählen

class UserField(forms.CharField):
    class widget(forms.widgets.TextInput):
        def render(self, name, value, attrs=None):
            if isinstance(value, int):
                value = unicode(User.objects.get(pk=value))
            return super(UserField.widget, self).render(name, value, attrs)
        
    def clean(self, value):
        value = super(UserField, self).clean(value)
        if not value:
            return None
        try:
            return User.objects.get(username=value)
        except User.DoesNotExist:
            raise forms.ValidationError('invalid user name')
Der Teil mit `clean` war einfach, doch wie ich die ID dann auch als Name im Eingabefeld anzeige hat mich verzweifeln und dann eine spezielle `TextInput`-Unterklasse schreiben lassen.

Stefan
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Eventuell ist raw_id_fields was du suchst. Ich habe es selbst bisher noch nicht ausprobiert, sollte ich irgendwann wohl machen.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Leonidas hat geschrieben:Eventuell ist raw_id_fields was du suchst.
Nein, ich glaube, lunas sucht, was ich beschrieben habe :) Das Raw-ID-Feld zeigt ja nur eine Nummer an und genau das will er/sie nicht.

Das neu Anlegen ist übrigen sehr einfach. Dort wo ich `get(usernam=...)` benutzt habe, kann man prinzipiell `get_or_create` benutzen. Allerdings fehlen einem u.U. dann Informationen wie der echte Name, email oder Kennwort. Daher muss man hier wohl so vorgehen wie es Django auch sonst macht und einen Extradialog benutzen.

Stefan
lunas
User
Beiträge: 87
Registriert: Samstag 2. Dezember 2006, 10:56

Vielen Dank. Das Anzeigen klappt schon mal prima (der type des PK musste in long geändert werden). Nur das Speichern wirft noch eine Exception, aber das kriege ich auch noch hin (habe im Moment keine Zeit...).

Code: Alles auswählen

Cannot assign "u'12345'": "Person.user" must be a "User" instance.
Dankeschön,
lunas
lunas
User
Beiträge: 87
Registriert: Samstag 2. Dezember 2006, 10:56

Die vorgeschlagene Lösung funktioniert wunderbar für ModelForms, aber nun wollte ich sie für Formsets benutzen und da scheitert sie leider. Dummerweise ist der Parameter "value" nicht nur zur Anzeige notwendig, sondern wird bei Formsets auch zur Identifizierung der zurückgelieferten Daten benutzt.

Der Post request liefert folgende Daten, wenn die UserField class die Daten einfach nur durchleitet. Beim verändern von "value" wird dies dann weitergeleitet und es kommt zu Validierungsproblemen wenn das Formset gespeichert werden soll.

Gibt es eine Möglichkeit das modifizierte Field trotzdem bei Formsets einzusetzen?

Code: Alles auswählen

form-3-user : 1312
form-2-user : 1311
form-3-id : 47
form-4-additionaldata : 67
form-3-additionaldata : 67
form-1-additionaldata : 67
form-1-id : 49
form-2-additionaldata : 67
form-TOTAL_FORMS : 5
form-4-id : 46
form-4-user : 1313
form-2-id : 48
form-1-user: 1310
form-INITIAL_FORMS : 5
course_id : 44
form-0-id : 50
form-0-additionaldata : 67
form-0-user : 1309
Antworten