开发者

Editing related models in profile form using django-profiles

I'm using django-profiles in my app, as it gives me a few simple views that helps me get where I want to go, faster.

However, I have one problem. Given the models below, how can I create a form for editing a profile that includes all the fields on UserProfile, the first_name, last_name and email fields from User, and one or more PhoneNumbers?

from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    height = models.IntegerField(_('Height'), max_length=3, blank=True, null=True, help_text=_('Users height in centimeters'))

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

    def __unicode__(self):
        return self.user.username

class PhoneNumber(models.Model):
    description = models.CharField(_("Description"), max_length=32, blank=True)
    number = models.CharField(_("Phone number"), max_length=15)
    owner = models.ForeignKey(UserProfile, related_name="phone_numbers")

    def __unicode__(self):
        return u"%s (%s)" % (self.number, self.description)

The closest I've managed so far, is a form that includes all fields on UserProfile, and the wanted fields from User, using tricks explained here and here:

from django import forms
from main.models import UserProfile开发者_如何学Go
from django.contrib.auth.models import User

class UserForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ('first_name', 'last_name', 'email')

class ProfileForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        # magic
        self.user = kwargs['instance'].user
        user_kwargs = kwargs.copy()
        user_kwargs['instance'] = self.user
        self.uf = UserForm(*args, **user_kwargs)
        # magic end

        super(ProfileForm, self).__init__(*args, **kwargs)

        self.fields.update(self.uf.fields)
        self.initial.update(self.uf.initial)

    def save(self, *args, **kwargs):
        # save both forms
        self.uf.save(*args, **kwargs)
        return super(ProfileForm, self).save(*args, **kwargs)

    class Meta:
        model = UserProfile
        exclude = ("user",)

In the admin, using Inlines on a custom ModelAdmin, I get the behaviour I want for the PhoneNumbers, but I've not been able to recreate it in a single form for use with django-profiles.

Is it at all possible, or should I just ditch django-profiles and write my own profile-app that can use a formset to pull in the PhoneNumbers?


that's quite a contortion to cram two modelforms into the same form. Choices:

  • Make your own view. You could utilize the short-circuit, first-come-first-serve nature of django urls to pirate that one.

  • Bring django-profiles into your own version control and hack it to your heart's content without the constraints of reusability.

  • You can just create the one big form with your own save method and use django-profiles in place. This would be more tedious than just being able to declare fields = ('first_name', 'last_name', 'email') and exclude = ("user",). See the docstrings

Depends on the project. I would definitely be tempted to write my own. There's not much to a profiles app and you may run into other places where you wish you had more control.


As far as I can tell, django-profiles is absolutely nothing but a glorified set of views. I added to my app but ran into the same issue. An examination of the source code reveals that it is essentially featureless. Basically, it saves you the trouble of writing up your own edit_profile and create_profile views. Really, that's it. Unless you have a severe terror of writing your own view, don't even bother using django-profiles, just roll your own code.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜