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 PhoneNumber
s?
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 PhoneNumber
s, 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 PhoneNumber
s?
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')
andexclude = ("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.
精彩评论