Django - Linking my models to profiles (UserProfile) model
I'm trying to create a small app for users to have contacts. I'm using django-profiles as a base for my profiles. Now everything works well until I try to submit the edit contact form and I receive this error.
Cannot assign "<Contact: Contact object>": "Contact.user" must be a "UserProfile" instance.
Being pretty new to Django, I'm not even sure if I'm taking the right approach here. My end goal is for the user to be able to add as many contacts as neccessary. Any advice is appreciated.
My UserProfile model which extends User looks like:
class UserProfile(models.Model):
#User's Info
user = models.ForeignKey(User, unique=True)
first_name = models.CharField("first name", max_length=30)
last_name = models.CharField("last name", max_length=30)
home_address = models.CharField(max_length=50)
primary_phone = PhoneNumberField()
city = models.CharField(max_length=50)
state = USStateField()
zipcode = models.CharField(max_length=5)
birth_date = models.DateField()
gender = models.CharField(max_length=1, choices=GENDER_CHOICES, blank=True)
and my contact model looks like this:
class Contact(models.Model):
user = models.ForeignKey(UserProfile)
contact_description开发者_如何学C = models.CharField("Relation or Description of Contact", max_length=50, blank=True)
contact_first_name = models.CharField("contact first name", max_length=30)
contact_last_name = models.CharField("contact last name", max_length=30)
contact_primary_phone = PhoneNumberField("contact primary phone number")
contact_secondary_phone = PhoneNumberField("contact secondary phone number",blank=True)
and my view:
def editContact(request, username, object_id=False, template_name='contacts/edit.html'):
user = UserProfile.user
AddContactFormset = inlineformset_factory(UserProfile,Contact, extra=1)
if object_id:
contact=Contact.objects.get(pk=object_id)
else:
contact=Contact()
if request.method == 'POST':
f= ContactForm(request.POST, request.FILES, instance=contact)
fs = AddContactFormset(request.POST, instance=contact)
if fs.is_valid() and f.is_valid():
f.save()
fs.save()
return HttpResponse('success')
else:
f = ContactForm(instance=contact)
fs = AddContactFormset(instance=contact)
return render_to_response(template_name ,{'fs':fs,'f':f,'contact': contact}, context_instance=RequestContext(request))
Basically, django-profiles is for something else - it's just helping to create and manage user profiles across an application.
First of all - you should link Contact
models directly to the django.contrib.auth.models.User
via ForeignKey. This way you can access given User's contacts by a simple query ie. User.contact_set.all()
- it will return to you a list of User's contacts. This will also get rid off your error.
Second - fields like first_name
, last_name
are already definied in django.contrib.auth.models.User
, so there is no need to define them again in UserProfile
. Read the source of User model here
Third - if your user can only have one Profile and you're not intend to use very old versions of django then you should be using OneToOneField
instead of ForeignKey
.
Fourth thing - you could probably omit usage of RequestContext()
by using one of the generic views bundled with django - read about that here
Last thing - remember that main model for handling the Users is the User
model itself. Any custom Profile is just an extension, so link everything which is related to the User to the User model itself.
Happy coding!
To elaborate on bx2's answer, your Contact model should look more like this:
class Contact(models.Model):
user = models.ForeignKey(User, related_name='contacts')
contact_description = models.CharField("Relation or Description of Contact", max_length=50, blank=True)
contact_first_name = models.CharField("contact first name", max_length=30)
contact_last_name = models.CharField("contact last name", max_length=30)
contact_primary_phone = PhoneNumberField("contact primary phone number")
contact_secondary_phone = PhoneNumberField("contact secondary phone number",blank=True)
Your view, frankly, does not make much sense. In general an inline formset is meant to represent records related to some parent record. In your case, it would be the user record, with the contacts being the "children" records. But having both a Contact form and an AddContactFormset doesn't make a lot of sense.
Also, I'd recommend against using variable names like f
and fs
in Django. Apart from variables like indexes, counters, etc. it doesn't serve any purpose to use short 1-2 character variable names. Go ahead and use longer variable names like form
and formset
, or even contact_form
and contact_formset
. It makes it much, much easier to debug the code in the future.
精彩评论