David J. David J. - 11 months ago 55
Python Question

Django models's attributes correctly saved by forms, but returns None type when queried

I have a model called UserProfile defined like so:

class UserProfile(models.Model):

user = models.OneToOneField(User)

website = models.URLField(blank=True, null=True)
location = models.CharField(max_length=200, null=True)
longitude = models.FloatField(null=True)
latitude = models.FloatField(null=True)
credit = models.FloatField(default=0, null=True)

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

The 'register' page includes the following form:

When it is submitted it goes to:

def register(request):
registered = False
if request.method == "POST":
user_form = UserForm(request.POST)
profile_form = UserProfileForm(request.POST)

if user_form.is_valid() and profile_form.is_valid():
lat = request.POST.get('lat')
print("lat is: " + lat)
lng = request.POST.get('lng')
user = user_form.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.latitude = lat
profile.longitude = lng
print user_form.errors, profile_form.errors

profile_form = UserProfileForm()
user_form = UserForm()

return render(request, "register.html", {'user_form' : user_form, 'profile_form' : profile_form})

That all seems to work fine, but when I try to query this data in another view, the location, lat, and lng properties come up as 'None' types.

def link(request):
print("trying to authenticate...")
if request.user.is_authenticated():
user_profile = UserProfile(user=request.user)
return render(request, 'login.html')

if request.method == "POST":
print("request was a post.")
if request.is_ajax():
print("request is ajax.")
print("User profile is: " + str(user_profile))
# returns billy, so we're looking at the right object
print("user location is: " + str(user_profile.location))
user_longitude = user_profile.longitude
user_latitude = user_profile.latitude
distance = request.POST.get('distance')
value = request.POST.get('value')

As you can see, the data coming up here is different than what is returned by the shell queries:

User profile is billy
user location is: None
user longitude is: None

I'm very confused as to how location, etc are float types in the shell and register view, but None types in the 'link' view. Any ideas?

Answer Source

In your link view, you're not querying for the userprofile, you're just instantiating a new (blank) one with the user set to the current user.

You probably meant to do:

user_profile = UserProfile.objects.get(user=request.user)

but it would be even easier to do:

user_profile = request.user.userprofile

Another minor point: you don't show the form, but I assume that the UserProfileForm has latitude and longitude fields on it, in which case there is no need to set them manually. If they're not on the form, why not? By getting them directly from request.POST you're bypassing all the validation the form would do, such as checking that they are valid float values.