2009-11-13 11 views
20

Wenn denke, meine Frage ist ziemlich offensichtlich, und fast jeder Entwickler, der mit UserProfile arbeitet, sollte in der Lage sein, es zu beantworten.Wie erstellt man ein UserProfile-Formular in Django mit first_name, last_name Modifikationen?

Ich konnte jedoch keine Hilfe zur Django-Dokumentation oder im Django-Buch finden.

Wenn Sie ein Formular mit Django Forms UserProfile machen möchten, möchten Sie die Profilfelder sowie einige User Feld ändern.

Aber es gibt keine forms.UserProfileForm (noch?)!

Wie machst du das?

Antwort

32

Hier ist, wie ich schließlich tat

class UserProfileForm(forms.ModelForm): 
    first_name = forms.CharField(label=_(u'Prénom'), max_length=30) 
    last_name = forms.CharField(label=_(u'Nom'), max_length=30) 

    def __init__(self, *args, **kw): 
     super(UserProfileForm, self).__init__(*args, **kw) 
     self.fields['first_name'].initial = self.instance.user.first_name 
     self.fields['last_name'].initial = self.instance.user.last_name 

     self.fields.keyOrder = [ 
      'first_name', 
      'last_name', 
      ...some_other... 
      ] 

    def save(self, *args, **kw): 
     super(UserProfileForm, self).save(*args, **kw) 
     self.instance.user.first_name = self.cleaned_data.get('first_name') 
     self.instance.user.last_name = self.cleaned_data.get('last_name') 
     self.instance.user.save() 

    class Meta: 
     model = UserProfile 
+0

Wo es heißt "Media" sollte es "Meta" sagen. – Daishiman

+0

Diese Lösung funktioniert nicht, wenn das Profil noch nicht erstellt wurde. Ich habe keine Lösung dafür, aber wenn ich es tue, werde ich es posten. –

+5

Dies passiert nicht, wenn Sie das Signal 'post_save' im' User'-Modell verwenden, wie hier beschrieben: http://docs.djangoproject.com/de/dev/topics/auth/#storing-additional-information-about- Benutzer – Natim

0

Ich nehme es normal, dass Sie nicht finden, keine Informationen in der Dokumentation, wie Sie zwei Modelle in einer einzigen Form verschmelzen.

Alternativ und vielleicht ganz offensichtlich können Sie: Erstellen Sie zwei Modellformen, eine für den Benutzer und die andere für das Benutzerprofil. Legen Sie das Benutzerprofilmodell so fest, dass nur Vorname und Nachname angezeigt werden. Legen Sie beide Formulare in die gleiche Vorlage innerhalb eines einzigen Tags <form>. Rufen Sie nach dem Senden die Speichermethoden für jedes Formular auf.

+0

Ja, aber es ist nicht wirklich einfach, zwei Formulare für tatsächlich eins zu verwenden ... Mit dieser Lösung können Sie die Felder nicht wie gewünscht bestellen und weiter verwenden die '{{form}}'. Mit der von mir bereitgestellten Lösung können Sie tun, was Sie wollen, indem Sie das Formular-Framework weiterhin verwenden. – Natim

+0

Ich mag einfach nicht die Idee, zwei Modelle in einer Modellform zusammenzuführen. Abgesehen von meiner subjektiven Meinung habe ich keine konkreten Einwände gegen Ihre Lösung, und es scheint, dass beide Lösungen ihre Vor- und Nachteile haben. Verwenden Sie nach Belieben;) – shanyu

+0

Ich stimme Ihnen zu, aber es ist in Bezug auf die Sicht, dass Sie für dieses spezifische Problem suchen. UserProfile und User-Modell sind eng miteinander verbunden. Für mich ist das UserProfile-Modell nur eine Möglichkeit, dem Benutzermodell einige fehlende Felder hinzuzufügen. Wenn Sie Ihr Profil aktualisieren möchten, müssen Sie alle diese Felder aktualisieren, unabhängig davon, ob sie sich im Benutzerprofil oder im Benutzermodell befinden, da sie kombiniert werden, um Eigenschaften für den Benutzer zu speichern. – Natim

5

So habe ich es im aktuellen Koffer (Revision: 11804) gemacht. Die Lösung von Natim funktionierte nicht für mich.

In admin.py:

class ProfileAdmin(admin.ModelAdmin): 
    form = ProfileForm 

    def save_model(self, request, obj, form, change): 
     obj.user.first_name = form.cleaned_data['first_name'] 
     obj.user.last_name = form.cleaned_data['last_name'] 
     obj.user.save() 
     obj.save() 

In forms.py:

class ProfileForm(forms.ModelForm): 
    first_name = forms.CharField(max_length=256) 
    last_name = forms.CharField(max_length=256) 

    def __init__(self, *args, **kwargs): 
     super(ProfileForm, self).__init__(*args, **kwargs) 
     try: 
      self.fields['first_name'].initial = self.instance.user.first_name 
      self.fields['last_name'].initial = self.instance.user.last_name 
     except User.DoesNotExist: 
      pass 

    class Meta: 
     fields = ['first_name', 'last_name', ...etc.] 
+0

Aber mit Ihrem ProfileForm können Sie das Profil nicht speichern. Mine ändert nicht den Admin. Aber deins, aber kann nicht ohne den Admin verwendet werden. – Natim

+0

Es speichert das Profil mit '' obj.save() ''. Dein korrekter, dass es nur im Admin funktioniert. Ich musste es einbauen. Damit es in Ihrer App funktioniert. Sichten sollten Sie die Logik vom Admin in das Formular verschieben. Wie du es mit deiner '' save'' Methode getan hast. – wunki

0

Warum nicht zwei Modellformen auf dem Back-End hat und sie nur als eine einzige Form in Ihrer Vorlage präsentieren? Löschen Sie die Namensfelder aus Ihrem UserProfileForm und erstellen Sie ein zweites Modellformular für das Benutzerobjekt?

+0

Es ist keine schlechte Idee. Aber es ist bequemer, nur eine Form zu haben. – Natim

+0

Verschiedene Ansätze schätze ich. Ich ging mit dem, was ich oben beschrieben, gerade weil es bequemer war, die mehreren Django-Formularobjekte zu verwenden, so dass sie unabhängig voneinander wiederverwendet werden konnten (und die Verarbeitung ist sauberer als das, was Sie oben haben (IMHO)). Um klar zu sein, ich spreche nicht über mehrere HTML-Formulare auf einer Seite; Es sieht für den Benutzer wie ein Formular aus. – Tom

1

Sie können auch versuchen, die django-basic-Anwendungen Projekt zu verwenden, die eine Profile App hat:

https://github.com/nathanborror/django-basic-apps

+0

Dies ist nicht sinnvoll, weil Sie nicht erstellen kombinieren Formularsatz von UserProfile und Django Benutzermodell/ – Denis

35

ich auf diese heute gestolpert und nach einigen googeln ich eine Lösung gefunden, die etwas sauberer ist meiner Meinung nach:

#in forms.py 
class UserForm(forms.ModelForm): 
    class Meta: 
     model = User 
     fields = ["username", "email"] 

class UserProfileForm(forms.ModelForm): 
    class Meta: 
     model = UserProfile 

#in views.py 
def add_user(request): 
    ... 
    if request.method == "POST": 
     uform = UserForm(data = request.POST) 
     pform = UserProfileForm(data = request.POST) 
     if uform.is_valid() and pform.is_valid(): 
      user = uform.save() 
      profile = pform.save(commit = False) 
      profile.user = user 
      profile.save() 
      .... 
    ... 

#in template 
<form method="post"> 
    {{ uform.as_p }} 
    {{ pform.as_p }} 
    <input type="submit" ...> 
</form> 

Source

+0

Es ist eine andere Lösung, aber Sie können Ihre Felder nicht bestellen, wie Sie möchten. Zum Beispiel habe ich ein 'title' Feld, das vor dem first_name und last_name aber immer noch Teil von pform sein sollte. – Natim

+0

Natim, das kannst du - aber es muss es mit deinen Händen machen :) –

+0

Du kannst die Reihenfolge der Felder angeben ... wie ns-keip erwähnt ... solange du das Rendern selbst machst .. https: //docs.djangoproject.com/en/1.8/topics/forms/#rendering-fields-manuell –

1

Dies ist ich etwas in einem meiner Projekte verwendet es hoffentlich lange zurück sollte den anderen helfen, dieses Problem zu googeln.

class SignUpForm(forms.ModelForm): 
    first_name = forms.CharField(max_length = 30) 
    last_name = forms.CharField(max_length = 30) 
    username = forms.CharField(max_length = 30) 
    password = forms.CharField(widget = forms.PasswordInput) 
    password1 = forms.CharField(widget = forms.PasswordInput) 
    class Meta: 
     model = UserProfile 
     exclude = ['user'] 

    def clean_username(self): # check if username does not exist before 
     try: 
      User.objects.get(username=self.cleaned_data['username']) #get user from user model 
     except User.DoesNotExist : 
      return self.cleaned_data['username'] 

     raise forms.ValidationError("This user exist already choose an0ther username") 



    def clean(self, *args , **kwargs): 
     super(SignUpForm).clean(*args ,**kwargs) # check if password 1 and password2 match each other 
     if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data:#check if both pass first validation 
      if self.cleaned_data['password1'] != self.cleaned_data['password2']: # check if they match each other 
       raise forms.ValidationError("Passwords don't match each other") 

     return self.cleaned_data 
    def save(self): # create new user 
     new_user = User.objects.create_user(username=self.cleaned_data['username'],password=self.cleaned_data['password1'],email=self.cleaned_data['email']) 
     new_user.first_name = self.cleaned_data['first_name'] 
     new_user.last_name = self.cleaned_data['last_name'] 
     new_user.save() 
     UserProf = super(SignUpForm,self).save(commit = False) 
     UserProf.user = new_user 
     UserProf.save() 
     return UserProf 
Verwandte Themen