Why does not django delete one to one relationship? - python

I have the following simple relationship:
class User(models.Model):
fields here
class UserProfile(models.Model):
user = models.OneToOneField(User)
I did the following in the shell:
user = User.objects.create(...)
profile = UserProfile.objects.create(user=user)
user.userprofile
...<UserProfile: UserProfile object>
user.userprofile.delete()
...(1, {'accounts.UserProfile': 1})
user.userprofile
...<UserProfile: UserProfile object>
From the above, you can see that I create User and UserProfile instances. Than I try to delete UserProfile instance and it is deleted (at least seems like). Than I do user.userprofile and it's like it never was deleted.
After little digging into the Django delete method, I realized that when I do user.userprofile.delete() Django just deletes userprofile's pk and the rest fields are not touched. What I do not understand is what should I do in order to get the following result:
user.userprofile.delete()
user.userprofile
...RelatedObjectDoesNotExist: User has no userprofile.
Does anyone have some ideas or code snippets?

You can reload the user from the database:
user = User.objects.get(pk=user.pk)
That will refresh all its attributes including the userprofile.

You can use Model.refresh_from_db:
user.refresh_from_db
Relevant docs

Related

Django restframework: How serialize two models queryset?

I have the following situation: A user can have more than one profile. Here is my models class. Something like this example:
models.py:
class Profile:
name=models.Charfield()
class UserProfile:
user=models.ForeignKey(User)
profile = models.ForeignKey(Profile)
serializers.py:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
Here I'm returning all my users by JSON but I would like to add a new field called profiles that returns all ids profiles that the user have.
{ "id": 1,
"name" : "John"
....
profiles = [1, 2]
}
How can I get(query) all profiles that the user have and add them on my final JSON?
on the UserSerializer declare the field profile as PrimaryKeyRelatedField
profiles = serializers.PrimaryKeyRelatedField()
By default this field is read-write, although you can change this behavior using the read_only flag.
see docs
1) Simplify relations - only User and Profile models needed in this case, you don't have to store explicit relation in UserProfile table as the same could be done in Profile model, as long as you don't need Users to share profiles with other Users.
2) Create ProfileSerializer
3) Add profiles field to UserSerializer with many=True property & provide reference in 'source' property
Please reffer to these docs as they are really good
http://www.django-rest-framework.org/api-guide/serializers/
Another thing to mention, creating UserProfile is depricated and in new versions of Django you can extend basic User model using setting property AUTH_USER_MODEL

Django updating values to OneToOneField field

Hi I have User object imported from auth and different model named UserProfile which has bio of user
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User)
bio=models.TextField(null=True,blank=True, max_length=128)
def __unicode__(self):
return self.user
as the user is OneToOneField Im having inserting data into it
q=User.objects.get(id=1)
>>> <User: test>
q.userprofile_set.create(bio='check')
Im getting error 'User' object has no attribute 'userprofile_set'. Im new to django..How should I insert data which has a OneToOneField
Any help is much appreciated...Thnaks in advance
ManyToManyFields and Foreignkey fields create a object.relation_set property on the object you can follow, but OneToOneFields do not. Instead you use object.relation directly (since we know there's only one).
So try q.userprofile.create(bio="check") instead!
(Bonus tip: Whenever you want to see the properties of a python object, use the dir() method, it will show you the full list of properties available!)

Django - all attributes for the User object?

I am reading a book called 'Packt Publishing, Learning Website Development with Django' and I am doing a tutorial on how to create a bookmarking website where users can read articles and bookmark them / save the url to the article. Here is the models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Link(models.Model):
url = models.URLField(unique=True)
class Bookmark(models.Model):
title = models.CharField(max_length=200)
user = models.ForeignKey(User)
link = models.ForeignKey(Link)
Now, this is my user_page view (where the username is passed as a parameter to the view)
def user_page(request, username):
try:
user = User.objects.get(uesrname=username)
except:
raise Http404('Requested user not found.')
bookmarks = user.bookmark_set.all()
variables = {
'username': username,
'bookmarks': bookmarks
}
return render(request, 'user_page.html', variables)
I'm confused about the line
bookmarks = user.bookmark_set.all()
I understand that 'user' is a user object, but we are using the generic User model provided by Django, which only has username, password and email, right? So where is bookmark_set coming from? Because if it is trying to access all bookmarks from the bookmark class, shouldn't the 'b' in bookmark_set at least be upper case? and what does the _set do? In the book, it explains this line by saying
"To obtain the list of bookmarks for a particular user object, we can
conveniently use the bookmark_set attribute available in the user object"
I tried google'ing all the attributes available for the user object but couldn't find anything. Is there a website which has a list of all the attributes available for the user object?
The bookmark_set comes from the Bookmark definition and more specifically, from the line
user = models.ForeignKey(User)
This line creates a user attributes to the Bookmark model but also adds a bookamrk_set attribute to the User model!
This is explained in the django documentation. For completeness, I'm copying from the docs:
Django also creates API accessors for the “other” side of the relationship – the link from the related model to the model that defines the relationship. For example, a Blog object b has access to a list of all related Entry objects via the entry_set attribute: b.entry_set.all().
bookmark_set is the reverse/"other side" of the ForeignKey. You have a FK from Bookmark to User, so Django automatically generates a bookmark_set on the User.
See also the official Django documentation: Following relationsips "backward"
You should have done the Django tutorial, where this is explained.
bookmark_set is the reverse relation for the ForeignKey that's defined in Bookmark and points to User. Every foreign key in Django gets this reverse accessor, which in this case gives you all bookmarks related to the particular User object you have.

Writing user.get_profile() custom function which should create auth profile if there is not any

I am trying to write custom get_profile() function which should create user profile for users who are registered thru admin or any other way where post_save was not called.
How can I start this?
I guess that you have a model to handle user profile like this:
class UserProfile(models.Model):
"""Contains user profile fields not provided by User model"""
user = models.OneToOneField(User)
# Defined User profile fields like picture, phone, etc
So adding following line (maybe in your models.py after UserProfile model):
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
Allows access to the profile of a user (i.e. in templates: {% user.profile.phone %}) by creating it if not exists.
This is the way I solved in my site a problem like you describe.
Hope this helps
I am a bit confused. Are you trying to let users create account and sign in? Then use django-registration which is easy and works out of the box.

Django: given a user object, how do I get a corresponding UserProfile object?

Have a UserProfile object that successfully extends the django default user class:
class UserProfile(models.Model):
user = models.OneToOneField(User)
and have updated the settings.py file accordingly:
AUTH_PROFILE_MODULE = 'authorization.UserProfile'
Everything works fine, just wondering: how do I get to objects associated with UserProfile for a given context within a view?
Assume that I can just get context.user if the user is logged in, but then how do I grab the corresponding UserProfile object?
In view:
request.user.get_profile().field_name
In template:
{{user.userprofile.field_name}}
You can get it like -
context.user.userprofile
Detail here.

Categories