Accessing UserProfile data from foreign key related Post - python

I am currently working on a little django app, the app is like a social media app.
User can post, like and comment.
I recently created the User Profiles. Which I can now see the user for that user profile in my view, but I cant seem to dig into the Posts that may be related to the UserProfile.
what I am trying to do is in my view of HTML, I want to be able to get the post from the userprofile and the comment, and likes.
But I have tried everything and nothing works.
Currently in my HTML view I have rendered {{ profile.user }} and it displays the users name, but If I try profile.user.post or profile.user.comments I get nothing.
Here is some code to show where I am at.
Any help would be much appreciated.
Profile View.
def profile(request):
profile = get_object_or_404(UserProfile, user=request.user)
template = 'profiles/profile.html'
context = {
'profile': profile,
# 'posts': posts
}
return render(request, template, context)
Profile Model
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class UserProfile(models.Model):
"""
A user profile model to link posts and likes
"""
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="profile")
def __str__(self):
return self.user.username
Post Model
from django.db import models
from django.contrib.auth.models import User
from cloudinary.models import CloudinaryField
from profiles.models import UserProfile
class Post(models.Model):
user_profile = models.ForeignKey(UserProfile, on_delete=models.CASCADE, null=True, blank=True, related_name='user_posts')
title = models.CharField(max_length=220, unique=True)
location = models.CharField(max_length=220)
rating = models.DecimalField(
max_digits=6, decimal_places=2)
#slug = models.SlugField(max_length=220, unique=True)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="activity_post")
updated_on = models.DateTimeField(auto_now=True)
description = models.TextField()
featured_image = CloudinaryField('image', blank=False)
created_on = models.DateTimeField(auto_now_add=True)
likes = models.ManyToManyField(User, related_name='activity_likes', blank=True)
like_count = models.BigIntegerField(default='0')
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
def number_of_likes(self):
return self.likes.count()
def liked_by_user(self):
return self.likes.values_list('id', flat=True)
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['created_on']
def __str__(self):
return f"Comment {self.body} by {self.name}"
enter code here
My Signal to create / save the profile, also have it registered in apps.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import UserProfile
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()

Related

'project.Account' has no ForeignKey to 'project.Object': How to link an account model to the objects of a project?

I am trying to create an announcement website (All) that can be visible to others (the Users, for which I added an Account). For this I wanted to modify a little the user profile to add fields like telephone, email address...
So I modified admin.py:
from django.contrib import admin
from .models import Todo, Account
from django.contrib.auth.models import User
class AccountInline(admin.StackedInline):
model = Account
can_delete = False
verbose_name_plural = 'Accounts'
class TodoAdmin(admin.ModelAdmin):
readonly_fields = ('created',)
inlines = (AccountInline, )
admin.site.unregister(User)
admin.site.register(Todo, TodoAdmin)
But got back:
<class 'todo.admin.AccountInline'>: (admin.E202) 'todo.Account' has no ForeignKey to 'todo.Todo'.
So I added a ForeignKey to Todo with account = models.ForeignKey(Account, on_delete=models.CASCADE):
from django.db import models
from django.contrib.auth.models import User
class Account(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
email = models.CharField(max_length=100)
firstname = models.CharField(max_length=30)
lastname = models.CharField(max_length=50)
company = models.CharField(max_length=5)
def __str__(self):
return self.user.username
class Todo(models.Model):
title = models.CharField(max_length=100)
datetime = models.DateTimeField()
memo = models.TextField(blank=True)
created = models.DateTimeField(auto_now_add=True)
datecompleted = models.DateTimeField(null=True, blank=True)
important = models.BooleanField(default=False)
user = models.ForeignKey(User, on_delete=models.CASCADE)
account = models.ForeignKey(Account, on_delete=models.CASCADE)
def __str__(self):
return self.title
But I still have the error, and I don't have any Users in the admin panel anymore
You accidentally wrote unregister for Users in your admin.py file. It should be admin.site.register(User)
You misinterpretted the error: the error states that you don't have a foreign key in your Account model to Todo.
This means your inline admin code isn't correct as it's expecting the other way around.

How to make a serializer for multiple users (student & teacher)?

Hello I am very new to Django Rest Framework and I am having a hard time with the serializer. I extended the User Model using Abstract User. I inserted two new fields which are is_student and is_teacher then I set both of the values to false as default. I then put them in there own model then just applied a one-to-one relation for each of them to the user model. My problem is with the serializer. How do I make a serializer out of this. I want the student and teacher have relation with the user model as well as having the ability to do http actions such as get, post, put, etc.
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.conf import settings
# Create your models here.
class User(AbstractUser):
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
class Course(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
price = models.FloatField()
def __str__(self):
return self.name
class Student(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True)
age = models.IntegerField()
address = models.CharField(max_length=200)
def __str__(self):
return self.user.username
class Teacher(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True)
description = models.TextField()
course_teaching = models.ForeignKey(Course, on_delete=models.CASCADE)
students = models.ManyToManyField(Student)
def __str__(self):
return self.user.username
Check out an example of this type of serializer here: https://github.com/imagineai/create-django-app/blob/master/todoapp/serializers.py

Django | formfield_for_manytomany - name display in admin

I am just learning Django, please forgive any ignorance here.
Here's my models.py:
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
admin = models.BooleanField("Admin Status")
class Team(models.Model):
name = models.CharField("Team Name", max_length=20, default="")
admins = models.ManyToManyField(User, related_name="admins")
members = models.ManyToManyField(User, related_name="members")
Here's my admin.py
from django.contrib import admin
from .models import Team, Profile
from django.contrib.auth.models import User
class ProfileAdmin(admin.ModelAdmin):
list_display = ('user', 'admin')
admin.site.register(Profile, ProfileAdmin)
class TeamAdmin(admin.ModelAdmin):
list_display = ('name',)
def formfield_for_manytomany(self, db_field, request, **kwargs):
print(db_field)
if db_field.name == "admins":
kwargs["queryset"] = Profile.objects.filter(admin=True)
return super(TeamAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
admin.site.register(Team, TeamAdmin)
This works perfect, but the admins on my admin page are showing as "Profile object (1)," "Profile object (2)," etc...
What am I doing wrong? Or where do I change the way those display?
It takes the __str__ as names for the object, and by default that uses Model object (pk). You thus can override the __str__, for example with:
class Profile(models.Model):
# …
def __str__(self):
return str(user)

Save multiple values in one field (Django)

The problem:
I have a model, which is referencing the basic User model of django. Right now, if I submit the form Django updates my database by replacing the existing data with the new one. I want to be able to access both of them. (In weight and date field)
Models file:
I saw other posts here, where they solved a problem by specifying a foreign key, but that doesn't solve it for me.
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
# Create your models here.
class Profile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
weight = models.FloatField(max_length=20, blank=True, null=True)
height = models.FloatField(max_length=20, blank=True, null=True)
date = models.DateField(auto_now_add=True)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
Views file:
This is where I save the data that I get from my form called WeightForm
from django.shortcuts import render
from django.contrib.auth.models import User
from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from users import models
from users.models import Profile
from .forms import WeightForm
def home(request):
form = WeightForm()
if request.is_ajax():
profile = get_object_or_404(Profile, id = request.user.id)
form = WeightForm(request.POST, instance=profile)
if form.is_valid():
form.save()
return JsonResponse({
'msg': 'Success'
})
return render(request, 'Landing/index.html',{'form':form})
What I tried:
I used to have a OneToOneField relation with this model, but as you can see I changed it to foreignkey, according to answers I saw on this site.
Thanks if you've gotten this far in my mess :D
I didn't understood exactly what you mean by "I want to be able to access both of them. (In weight and date field)" but I guess you want user to be able to see their previous data of weight and Date also, so you can try doing this:
In your models.py do try doing this,
class Profile(models.Model):
user_id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
height = models.FloatField(max_length=20, blank=True, null=True)
def __str__(self):
return self.user.username
class UserData(models.Model):
Data_id = models.AutoField(primary_key=True)
user_id = models.ForeignKey(Profile, on_delete=models.CASCADE)
weight = models.FloatField(max_length=20, blank=True, null=True)
date = models.DateField(auto_now_add=True)
then u can have seperate forms for both the models and use them combined.
You can make a workaround
Create new model which would include something like "version"
Reference to version with foreign key
class ProfileChange(models.Model):
Date = models.DateField(default=datetime.datetime.today().strftime('%Y-%m-%d'))
#classmethod
def create(cls):
object = cls()
return object
class Profile(models.Model):
version = models.ForeignKey(ProfileChange,on_delete=models.CASCADE)
Unfortunately, you could see only one ProfileChange a day. If you want to see more of them, instead of models.DataField use models.IntegerField

Missing entry field in django admin's site after import Tinymce

After import the Tinymce, the entry of the models.post in the admin's site not show up(red draw). When i restart the page, it's show in a momment then off completely
Here is screenshot
main.admin.py
from django.contrib import admin
from .models import Author, Category, Post
admin.site.register(Author)
admin.site.register(Category)
admin.site.register(Post)
main.models.py
from django.db import models
from tinymce.models import HTMLField
from django.contrib.auth import get_user_model
from django.urls import reverse
User = get_user_model()
class Author(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_picture = models.ImageField()
def __str__(self):
return self.user.username
class Category(models.Model):
title = models.CharField(max_length=40)
def __str__(self):
return self.title
class Post(models.Model):
title = models.CharField(max_length=100)
overview = models.TextField()
detail = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
content = HTMLField(default='')
comment_count = models.IntegerField(default=0)
view_count = models.IntegerField(default=0)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
thumbnail = models.ImageField()
categories = models.ManyToManyField(Category)
featured = models.BooleanField()
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={
'id': self.id
})
The problem is due to the installation of TinyMCE through pip install django-tinymce. Try installing as:
pip install django-tinymce4-lite
then,
from tinymce import HTMLField (instead of 'tinymce.models import HTMLField')
class Post(models.Model):
...
content = HTMLField('Content')

Categories