Pulling data associated with user account in Django - django

I'm creating a model in Django with the following syntax. The model has a foreign key of registered users. However, I want to serialize this model that will return a Json file only associated with the logged in user. Can you give your recommendations? Or is there an alternative way to extract the information from the model using different approach?
class Education(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
school = models.CharField(max_length=50)
year = models.CharField(max_length=10)
Sample photo
For instance, it will only show the first field associated with the account

To filter objects related to a user, simply get hold of the user and apply filter based on the user.
user_education_queryset = Education.objects.filter(user=user)
if you are doing this in the view where user objects is available in request context, you could simply do user=request.user Note: the user has to be logged in, else this will return anonymouse user object which will fail to query the database.
Summary:
Get the user object and filter by the user field in education model using the user object obtained.
mike = User.objects.get(id=1) # or mike = User.objects.get(username='mike')
then
mike_education_query = Education.objects.filter(user=mike)

Because of the suggestions, I was able to query the results per user with this code:
class EducationViewSet(viewsets.ModelViewSet):
serializer_class = EducationSerializer
def get_queryset(self):
user = self.request.user
account = User.objects.get(id=user.id)
return Education.objects.filter(user=account)

Related

Django - Update field values in extended user model after a request is performed

My project is a social networking site that can send requests to friends and make friends.
I have extended django's existing user model using oneToone field .
So far i've been able to do the above said thing but when ever a user accepts the request , Both the user who sent request and also the user accepted it must increment a value in their extended user model which stores the value of their friends count .
I'm facing difficulties trying to solve this .
I've also used signals but it doesn't work .
Here is my code:
models.py:
class Friends(models.Model):
"""Model for saving relationship of user and friends"""
request_id = models.ForeignKey(User,on_delete=models.CASCADE,related_name='current_user')
friend_id = models.ForeignKey(User,on_delete=models.CASCADE,related_name='user_friend')
created_on = models.DateTimeField(auto_now_add=True,auto_now=False)
class Meta:
verbose_name_plural = "Friends"
def __str__(self):
return str(self.friend_id)
class Profile(models.Model):
user = models.OneToOneField(User,related_name='profile',on_delete=models.CASCADE)
location = models.CharField(max_length=30,blank=True)
friends_count = models.PositiveIntegerField(default=0)
profile_pic = models.ImageField(upload_to='profile_pics/',blank=True,null=True)
def natural_key(self):
return (self.user.username,)
signals.py:
#receiver(post_save,sender=Friends)
def update_friends_count(sender,instance,created,**kwargs):
if created:
user_profile = Profile(user = instance.request_id)
user_profile.friends_count=F('friends_count')+1
user_profile.save()
Any help would be greatly appreciated!!!!! Thank you in advance!!!
You were initializing a new instance of Profile every time a friend is made. Instead you can use get_or_create to generate a profile or retrieve the one associated with that id. Next, you want to update both users so fetch the other update the counts and save.
#receiver(post_save,sender=Friends)
def update_friends_count(sender,instance,created,**kwargs):
if created:
user_profile, profile_created = Profile.objects.get_or_create(user = instance.request_id)
user_profile.friends_count=F('friends_count')+1
user_profile.save()
friend_profile, profile_created = Profile.objects.get_or_create(user = instance.friend_id)
friend_profile.friends_count=F('friends_count')+1
friend_profile.save()
With Q filter and update
Profile.objects.filter(
Q(user=instance.request_id) |
Q(user=instance.friend_id)
).update(
friends_count=F('friends_count')+1
)
This last query uses the django.db.models Q object to make an SQL OR statement to retrieve the two profile instances; that of the requested and the requester: the update call acts on the query and updates all instances in the list

How do I link these two models such that one will update that same instance?

I really want to build this app with Django that lets people register and create User instances that can be edited. Each User instance is already linked to a UserProfile with OneToOne because I didn't want to mess with the original User model. The UserProfile will have a field where he/she can register a game if that person is logged in.
ie. Billy wants to register for Monday Smash Melee. He logs in, clicks an option on a form, the UserProfile linked to User, Billy, will update the registered game choice and user tag to the user profile.
The part with the user profile linking to the user works fine, but I don't know how to update the UserProfile with the new tournament registration form so that it can change the UserProfile fields that's linked to the user that is logged in.
Django Models:
class UserProfile(models.Model):
#User profile for registered users. SEPARATE USERBASE TO PLAYER_RANKING
#To Do: add more customizeability and more access for registered.
#weekly e-mails, ability to register for weeklies...
user = models.OneToOneField(User)
picture = models.ImageField(upload_to='profile_images', blank=True)
MON = 'ME'
TUE = 'S4'
THR = 'PM'
reg_game_choices = (
(MON, "Melee"),
(TUE, "Smash 4"),
(THR, "PM"),
)
reg_game_choice = models.CharField(max_length=2,
choices=reg_game_choices,
default="")
user_tag = models.CharField(max_length=60, default = "")
def __str__(self):
return self.user.username
Forms:
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'password')
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('picture',)
class TournyRegForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('reg_game_choice', 'user_tag',)
View:
#login_required
def tourny_reg(request):
#Registering for tournaments
context_dict = {}
weekday = datetime.datetime.today().weekday()
day_names = ['MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY', 'SUNDAY']
game_days = ['SMASH MELEE', 'SMASH 4', 'CLOSED', 'PROJECT M & FIGHTING GAMES',
'FRIENDLIES', 'CLOSED', 'CLOSED']
day_title = day_names[weekday]
game_day = game_days[weekday]
context_dict['day'] = day_title
context_dict['game_of_the_day'] = game_day
if request.method == 'POST':
tourny_form = TournyRegForm(data=request.POST)
if tourny_form.is_valid():
tourny_form.save()
else:
print (tourny_form.errors)
else:
tourny_form = TournyRegForm()
context_dict['tourny_form'] = tourny_form
return render(request, 'Kappa/tourny_reg.html', context_dict)
It shows up perfectly fine in html and on the local server, but when I try, it gives me an integrity error.
IntegrityError at /Kappa/tourny_reg/
NOT NULL constraint failed: Kappa_userprofile.user_id
Exception Value:
NOT NULL constraint failed: Kappa_userprofile.user_id
▶ Local vars
C:\Users\Kyle\Documents\GitHub\Kappa_Ranks\Kappa\views.py in tourny_reg
So basically, you want to know how to save an instance of something which is related to the logged-in user. That's easy.
To explain why you are getting a NOT NULL error: Your TournyRegForm class has not been told to display an input field for 'user', so it isn't. So when you go to save the form, None is being filled in for the user field. The database is complaining because a 'NOT NULL' field has a NULL value, which is a problem.. so this error is legitimate.
But it's ok that this field is not on the form.. because you don't want the user telling us who they are via the form, you want to get the information about who they are by the fact that they are logged in. The Django auth module puts this information in the Request object where you can easily get at it. All you need to do is to fill in the correct user before the model is saved, like this:
if tourny_form.is_valid():
# commit= False tells the modelform to just create the model instance
# but don't save it yet.
user_profile = tourny_form.save(commit=False)
# associate this user_profile with the logged in user.. it is always
# present in the request object if you are using django's auth module.
user_profile.user = request.user
# now save it
user_profile.save()
So that takes care of saving a model that is related to the currently logged in user. But you have other problems. For example, do you want to save a new UserProfile each time? I don't think you do.. So on your GET you need to do something like this:
user_profile = UserProfile.objects.filter(user=request.user).first()
tourny_form = TournyRegForm(instance=user_profile)
This will fetch the UserProfile of the currently logged=in user from the database, then initialize the form with that instance, so when the user comes back they will be able to edit their profile.
Now, if you actually want the user to be able to register for multiple games.. you will need a Game model for storing the game information, with one-to-many relationship with your UserProfile. This works by having a ForeignKey field in the Game model which relates it to UserProfile.. so each user will have only one UserProfile but could have multiple Games.

Django Filter ForeignKey relationships in get_queryset

I wonder what to do here.
So I have an EmailAddress class which has a ForeignKey relationship to my User class
class EmailAddress(models.Model):
user = models.ForeignKey(allauth_app_settings.USER_MODEL, verbose_name=_('user'))
email = models.EmailField(unique=app_settings.UNIQUE_EMAIL,
verbose_name=_('e-mail address'))
I also have a UserProfile class which has a OneToOneField relationship with the mentioned User like so:
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile')
attribute= models.CharField("attr", max_length=150, blank=False)
Now in admin.py I want to filter the Users so that the current user who is logged in to admintool can only see emails from users who share some attribute. The catch is that the attribute is saved in UserProfile and I need to get there through the email.
Basically I don't know how to access the 'attribute' which is in the UserProfile. I understand that I want to filter users by taking the email finding the user that this email belongs to and then compare his 'attribute' to the user who send the request to decide whether to show it to him or not.
def get_queryset(self, request):
user = [User whos email is in the list]
qs = [the queryset]
[and then]
return qs.filter([filter so the user attribute = the request.user attribute])
Im using allauth btw. in case you wonder what
allauth_app_settings.USER_Model
stands for.
Have a nice day!
You need to use the double-underscore syntax to follow the relationships.
qs.filter(user__userprofile__attribute=request.user.attribute)

using session to store data from anonymous user

in my django app, I have a user wishlist feature. I want that an anonymous user can add a product to his wishlist.
models.py
class User_Wishlist(models.Model):
created_by = models.ForeignKey(User, default=None, null =True, blank=True)
products = models.ManyToManyField(Products, null=True)
# some Products model
views.py
# to add an item from the user wishlist
def add_userwl(request, id):
products = Products.objects.filter(id__iexact=id)
product = products[0]
if request.user.is_authenticated():
userwlt = get_sl(request, request.user) #gets the auth user wishlist
userwlt.products.add(product)
sl_products = userwlt.products.all()
else:
if "wl_user" in request.session:
wl_user = request.session["wl_user"]
else:
wl_user = User_Wishlist(created_by = request.user) #here lies the problem!
request.session["wl_user"] = wl_user
wl_user.products.add(product)
wl_products = wl_user.products.all()
return render_to_response('getsl.html', {
'wl_products':wl_products
}, context_instance=RequestContext(request))
Error: Cannot assign "": "User_Wishlist.created_by" must be a "User" instance.
So, it can't create a wishlist for an anon user. Also if I just do wl_user = User_Wishlist(), it can't access the manytomany field 'products' without assigning a user id.
Any help on this would be great. Thanks!
p.s: I also want to save this user wishlist once the anon user signs up, but thats a later problem
Your concept of an anonymous user seems wrong. If you wish to bound data to a certain 'user' you will have to create an 'user' for them. Otherwise whenever the session expires or the 'user' resets his or her browser's cache the data is gone.
Now how an 'user' is defined is entirely up to you. It could be a 'cart' or a 'customer' or anything else. There's no reason you can't use a different abstraction then the one provided by Django's auth module.
Most sites that implement this properly allow your not-so-much 'anonymous' session to be bound to an optional account at some point (which might as well be an oauth or openid solution).
The much simpler solution is to require that a wishlis is tied to either a user object or a session object. So allow for those fields to be null and implement logic that favours the user object.

Django Foreign Key Relationship And Creation

I have the following:
models.py
class User(models.Model):
email = models.EmailField(unique=True)
passwd = models.CharField()
sessionID = models.CharField()
class StudentProfile(models.Model):
school = models.CharField()
name = models.CharField()
user = models.ForeignKey(User, unique=True)
I don't understand how to create Users and StudentProfiles in django and have them linked. Could somebody please provide some sample code for creating a User, then creating a StudentProfile that refers to the User. Could they also post sample access code, ie let's say I have an email, please show how I would lookup the User, and then access the accompanying Profile information. Could I write a method as part of the User model to do this?
inb4 Why aren't you using the Django User model?
This is as much of a thought exercise as anything, I also want to roll my own because the Django stuff was much more than I needed. I prefer it sweet and simple.
Thanks!
As addition to zhyfer's answer – You can approach things even a bit more basic:
user = User()
user.email = 'anon#anon.com'
user.save()
profile = StudentProfile()
profile.school = 'MIT'
profile.user = user
profile.save()
To get the related items you can also use the related manager:
user.profile_set.all()[0] should return the related StudentProfile for the created user.
And therefore user.profile_set.all()[0].school should return MIT while
profile.user.email returns anon#anon.com
This all is a bit more elaborated in this blog post: Doing things with Django models
And finally you could write the get_profile method of the user-model like this:
def get_profile(self):
return self.profile_set.all()[0]
If you have the above models,you can access a profile given an email via:
profile = StudentProfile.objects.get(user__email = 'test#test.com')
school = profile.school
I think that if you want a method in the user model to do this you can basically do the same thing:
def get_profile(email):
return StudentProfile.objects.get(user__email = 'test#test.com')
To Link:
u = User.objects.create(email="test#test.com", passwd="test", sessionId=1)
StudentProfile.objects.create(school="test", name="student", user=u)