Seems it was easier than I thought.
Replace this:
form = AccountSettingsForm(request.POST, obj=request.user)
with:
form = AccountSettingsForm(request.POST, obj=request.user, country=request.user.account.country)
题
I have a Django model which extends the auth User class, but I can't find a way to render data from both models in a single form.
For example, let's extend the User class with a country field using a One2OneField:
from django.contrib.auth.models import User
import pycountry
class Account(models.Model):
user = models.OneToOneField(User, primary_key=True)
COUNTRY_CHOICES = [(country.alpha2, country.name) for country in pycountry.countries]
country = models.CharField(max_length=2, choices=COUNTRY_CHOICES, default='US')
Now let's create a form which contains elements from both models:
class AccountSettingsForm(Form):
first_name = TextField(u'First name:', [validators.Length(min=2, max=35,message=u'First name should be between 2 and 35 characters.')])
last_name = TextField(u'Last name:', [validators.Length(min=2, max=35,message=u'Last name should be between 2 and 35 characters.')])
email = EmailField(u'E-mail address:', [validators.Email(message=u'Invalid e-mail address.')])
COUNTRY_CHOICES = [(country.alpha2, country.name) for country in pycountry.countries]
country = SelectField(u'Country', [valid_country,],choices=COUNTRY_CHOICES)
Now, on my "account settings" page, I have this:
@login_required
def update_settings(request):
form = AccountSettingsForm(request.POST, obj=request.user)
if request.method=='POST' and form.validate():
#processing goes here
context = {'form': form}
return render(request, 'account/settings.html', context)
When opening the page, only the info from "User" (like first name, last name, mail address,...) is displayed. However, the "country" part is not retrieved from the model.
What do I need to do to get both displayed on the same form? I don't see how I can explicitly bind the "country" field of the form to the user.account.country field on the model.
解决方案 2
Seems it was easier than I thought.
Replace this:
form = AccountSettingsForm(request.POST, obj=request.user)
with:
form = AccountSettingsForm(request.POST, obj=request.user, country=request.user.account.country)
其他提示
You can override the __init__()
method like this to populate the data from obj.account
(is that even the default name? I always use the related_name
option).
class AccountSettingsForm(Form):
def __init__(self, formdata=None, obj=None, prefix='', data={}, meta=None, **kwargs):
data['country'] = obj.account.country
# etc
super(AccountSettingsForm, self).__init__(formdata, obj, prefix,
data, meta, **kwargs)