2010-07-21 35 views
1

Résumé:Django-profils personnalisés créer/modifier ModelForm n'épargnent pas correctement

u = self.instance.user 

dans

def save(self, *args, **kwargs): 
    u = self.instance.user 
    u.first_name = self.cleaned_data['first_name'] 
    u.last_name = self.cleaned_data['last_name'] 
    u.save() 
    return super(ProfileForm, self).save(*args, **kwargs) 

pose un problème parce que self.instance n'existe pas. Mais pourtant, c'est ainsi que cela se fait dans d'autres exemples, où cela semble fonctionner. Qu'est-ce que je rate?

Lire la suite pour plus d'informations ->

J'utilise les deux django-enregistrement et django-profils. Dans le but de simplement le faire fonctionner, je n'ai ajouté aucun champ supplémentaire au modèle de profil (celui qui étend l'utilisateur). Jusqu'à présent, il ressemble à ceci:

class sumaConnectUser(models.Model): 

    user = models.ForeignKey(User) 

    def __unicode__(self): 
     return self.user.first_name + " " + self.user.last_name 

    def get_absolute_url(self): 
     return ('profiles_profile_detail',(), { 'username': self.user.username }) 
    get_absolute_url = models.permalink(get_absolute_url) 

Ma compréhension est que maintenant, mon utilisateur « profil » devrait simplement inclure les champs qui viennent avec le modèle contrib.auth utilisateur. (Prénom, nom, etc.)

Dans mon urls.py, je passe dans mon formulaire personnalisé pour la création et l'édition de Profils-

(r'^profiles/edit', 'profiles.views.edit_profile', {'form_class': ProfileForm, }), 
(r'^profiles/create', 'profiles.views.create_profile', {'form_class': ProfileForm, }),     
(r'^profiles/', include('profiles.urls')), 

Enfin, voici mon profil form-

from suma.sumaconnect.models import sumaConnectUser 
from django import forms 
from django.contrib.auth.models import User 

class ProfileForm(forms.ModelForm): 
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 

first_name = forms.CharField(label="First Name") 
last_name = forms.CharField(label="Last Name") 

class Meta: 
    exclude = ('user',) 
    model = sumaConnectUser 

def save(self, *args, **kwargs): 
    u = self.instance.user 
    u.first_name = self.cleaned_data['first_name'] 
    u.last_name = self.cleaned_data['last_name'] 
    u.save() 
    return super(ProfileForm, self).save(*args, **kwargs) 

Mon but est de permettre à l'utilisateur de modifier son prénom et son nom dans le cadre de la modification du profil, mais pas son nom d'utilisateur et son mot de passe.

Je pensais à remplacer

u = self.instance.user 

avec

u = User.objects.get(user = self.cleaned_data['username']) 

mais cela me obligerait à inclure un nom d'utilisateur = forms.CharField sur la page que je ne veux pas afficher. Pour autant que je comprenne, quand je viens à la page de profil de profil ou d'édition de profil, je devrais éditer automatiquement le profil associé à l'utilisateur que je suis identifié en tant que.

Lorsque j'arrive à cette page utilisateur de création ou de modification, le modèle utilisateur existe déjà, mais pas le profil. Est-ce la cause du problème? Je pense que je me méprends sur quelque chose de majeur, et j'apprécierais grandement les indications sur l'endroit où je me trompe. Merci!

Répondre

0

Vous pouvez copier des champs si vous le souhaitez, et les mettre à jour deux fois comme indiqué ci-dessus, mais ce n'est pas le but du profil. Il est supposé gérer des champs qui ne sont pas dans le auth.User d'origine, puisque vous ne devriez pas avoir besoin de modifier ce modèle directement. Vous avez mentionné "extension d'utilisateur" ci-dessus - vous n'êtes pas en train d'hériter de auth.User, êtes-vous? Je ne recommande pas cela.

Mise à jour:

Voir this reference material. Il utilise la même syntaxe que vous pour faire la mise à jour de l'utilisateur dans le profil.

Mise à jour 2:

L'exemple est pour modifier le profil, pas créer le profil. En regardant le code dans profile.views.create_profile:

if request.method == 'POST': 
    form = form_class(data=request.POST, files=request.FILES) 
    if form.is_valid(): 
     profile_obj = form.save(commit=False) 
     profile_obj.user = request.user 
     profile_obj.save() 

Il enregistre la forme premier, définit ensuite utilisateur, enregistre le profil.

Cela signifie que vous ne pouvez pas définir les valeurs de l'utilisateur dans le form.save, vous devez le faire dans le model.save du profil:

# in sumaConnectUser: 

from django.db.models.base import ObjectDoesNotExist 
class sumaConnectUser(models.Model): 
    ... 
    def save(self, *args, **kwargs): 
    s = super(sumaConnectUser,self).save(*args, **kwargs) 
    try: 
     u = s.user 
     u.first_name = self.first_name 
     u.last_name = self.last_name 
     u.save() 
    except ObjectDoesNotExist: 
     pass 
    return s 

En fait, en regardant le code profile.views .create_profile, nous sommes positif qu'il éventuellement appels enregistrer sur le profil après il a défini user. Ce n'est peut-être pas la première fois, nous devons donc piéger cette affaire et l'oublier. Parce que finalement, il sera appelé et déclenchera notre code de sauvegarde à l'utilisateur. Le résultat est que, peu importe les formulaires que vous utiliserez dans le futur pour ce profil utilisateur, il sera toujours sauvegardé dans l'utilisateur sous-jacent.

+0

Je n'hérite pas de auth.User, mais l'étend à travers le champ ForeignKey dans le modèle de profil. Je sais que vous avez dit que je ne devrais pas mettre à jour quoi que ce soit, mais cela ne me semble pas être le cas. Je veux dire, tout ce que je veux, c'est que l'utilisateur puisse modifier les attributs first_name et last_name du modèle auth.User. Par conséquent, j'inclus les deux champs dans le formulaire. Ensuite, je les assigne aux champs appropriés dans l'utilisateur et l'enregistre avant d'enregistrer le profil entier. Quand vous dites essayer d'utiliser super.save, voulez-vous littéralement mettre "super.save()" comme première ligne dans la fonction de sauvegarde? – dpetters

+0

désolé, écrivait sténographie. Je voulais dire votre super appel comme écrit. rien de mal à dupliquer les champs dans ce cas particulier, à mon humble avis, sinon vous devez avoir deux formes et/ou éditer auth.User. – eruciform

+0

J'ai donc essayé de mettre "profile = super (ProfileForm, self) .save (* args, ** kwargs)" tout en haut puis "return profile" tout en bas de la fonction, mais j'ai quand même un "DoesNotExist" at/profiles/create "sur la ligne" u = self.instance.user ". Même pas d'auto-instance existe. Est-ce que cela signifie que j'ai besoin d'instancier le profil la première fois? – dpetters