I would like to get all posts of all users which my user follow.
My User model looks like
from django.db import models
from django.contrib.auth.models import AbstractUser
from apps.friend_request.models import FriendRequest
# Save avatar to user specific directory in media files
def user_avatar_directory(instance, filename):
return f'{instance.username}/avatar/{filename}'
class User(AbstractUser):
# Field that is used as the unique identifier
USERNAME_FIELD = 'email'
# Fields that are required when using createsuperuser (username_field and password fields are required by default)
REQUIRED_FIELDS = ['username', 'first_name', 'last_name']
# Fields that shall be treated as public and can be exposed to all logged-in users
PUBLIC_FIELDS = ('id', 'username', 'first_name', 'last_name', 'country')
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150)
country = models.CharField(max_length=150, blank=True, null=True)
city = models.CharField(max_length=150, blank=True, null=True)
about = models.TextField(blank=True, null=True)
avatar = models.ImageField(upload_to=user_avatar_directory, blank=True, null=True)
followers = models.ManyToManyField(to='self', symmetrical=False, related_name='followees', blank=True)
my post model
from django.db import models
from django.conf import settings
class Post(models.Model):
user = models.ForeignKey(
#to=User,
to=settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='posts',
#null=True
)
content = models.CharField(
max_length=150,
blank=False
)
created = models.DateTimeField(
auto_now=True
)
liked_by = models.ManyToManyField(
#to=User,
to=settings.AUTH_USER_MODEL,
related_name='liked_posts',
blank=True
)
# TODO
# comments = Set('Comment')
# TODO sharing not yet clear what it is about
# shared = Optional('Post', reverse='sharing')
# sharing = Set('Post', reverse='shared')
def __str__(self):
return f'ID: {self.pk}: {self.content} '
class Post_Pic(models.Model):
created = models.DateTimeField(
auto_now=True
)
post_id = models.ForeignKey(
to=Post,
on_delete=models.CASCADE,
related_name='posts',
)
image = models.ImageField(
upload_to='post_pic'
)
def __str__(self):
return f'ID: {self.pk} Post: {self.post_id} File: {self.image.name}'
my views.py
class MyFollowersPosts(ListView):
"""
Get all followers
"""
queryset = Post.objects.all()
serializer_class = FollowesSerilizer
def get_queryset(self):
posts = []
for user in self.request.user.followers.all():
for post in Post.objects.filter(author=user.followed):
posts.append(post)
return posts
Problem is that I am always getting this error and I can´t find out where is problem
AttributeError at /backend/api/social/posts/following/
'AnonymousUser' object has no attribute 'followers'
Request Method: GET
Request URL: http://127.0.0.1:8000/backend/api/social/posts/following/
Django Version: 3.1.4
Exception Type: AttributeError
Exception Value:
'AnonymousUser' object has no attribute 'followers'
Exception Location: C:\Users\Dell\anaconda3\envs\motion-backend\lib\site-packages\django\utils\functional.py, line 241, in inner
Python Executable: C:\Users\Dell\anaconda3\envs\motion-backend\python.exe
Python Version: 3.9.1
Python Path:
['C:\Users\Dell\Desktop\day-5-django-motion-assignment',
'C:\Users\Dell\anaconda3\envs\motion-backend\python39.zip',
'C:\Users\Dell\anaconda3\envs\motion-backend\DLLs',
'C:\Users\Dell\anaconda3\envs\motion-backend\lib',
'C:\Users\Dell\anaconda3\envs\motion-backend',
'C:\Users\Dell\anaconda3\envs\motion-backend\lib\site-packages']
Server time: Mon, 04 Jan 2021 13:53:46 +0000
Your get_queryset should return a QuerySet, not a list. You furthermore do not need to obtain items with a loop, you can query with:
from rest_framework.permissions import IsAuthenticated
class MyFollowersPosts(ListView):
# …
permission_classes = [IsAuthenticated]
def get_queryset(self):
return Post.objects.filter(author__followees=self.request.user)
Furthermore the user should be logged in. You do this with the IsAuthenticated permission class.
You can use something like this :
user = request.user
followings_posts = Post.objects.filter(user__in = user.followees.all())
Related
I have two models, Account model & Thread model:
class Account(AbstractBaseUser, PermissionsMixin):
class Meta:
verbose_name_plural = "Account List"
email = models.EmailField(max_length=255, unique=True)
username = models.CharField(max_length=255, unique=True)
name = models.CharField(max_length=255, default="")
profile_image = models.ImageField(max_length=255, upload_to=profile_image_path, blank=True, null=True, unique=True)
about = models.TextField(max_length=255, default='Write something about yourself...', blank=True)
start_date = models.DateTimeField(default=timezone.now)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(auto_now=True)
objects = AccountManager()
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username", "name"]
def __str__(self):
return self.username
class Thread(models.Model):
options = (('active', 'Active'), ('deactivated', 'Deactivated'))
username = models.ForeignKey(Account, on_delete=models.CASCADE, to_field='username')
alt = models.TextField(max_length=255, blank=True)
image = models.ImageField(max_length=255, upload_to=thread_image_path, blank=True)
content = models.TextField(blank=True)
created = models.DateTimeField(blank=True, null=True, default=timezone.now)
status = models.CharField(max_length=11, choices=options, default='active')
If I have already created a thread that is ForeignKey to the Account model, I am not able to change the username of the Account model, returning the error FOREIGN KEY constraint failed. I guess the existing Thread model require a username to point to. Is there way to create a custom update method in view.py to update the ForeignKey automatically?
Here is my view.py:
class UserViewSet(viewsets.ModelViewSet):
serializer_class = UserSerializer
queryset = Account.objects.all()
permission_classes = (AllowAny,)
EDIT:
serializer.py
class ThreadSerializer(serializers.ModelSerializer):
profile_image = serializers.SerializerMethodField('get_profile_image')
created = serializers.DateTimeField(format="%d %B, %Y %H:%M:%S")
class Meta:
model = Thread
fields = (
'id',
'username',
'profile_image',
'alt',
'image',
'content',
'created',
'status')
def get_profile_image(self, thread):
profile_image_url = thread.username.profile_image.url
return profile_image_url
Error:
IntegrityError at /account/auth/user/1/
FOREIGN KEY constraint failed
Request Method: PUT
Request URL: http://127.0.0.1:8000/account/auth/user/1/
Django Version: 4.0.4
Exception Type: IntegrityError
Exception Value:
FOREIGN KEY constraint failed
Exception Location: c:\Users\85291\Desktop\vscode\my-app\web\env\lib\site-packages\django\db\backends\sqlite3\base.py, line 477, in execute
Python Executable: c:\Users\85291\Desktop\vscode\my-app\web\env\Scripts\python.exe
Python Version: 3.10.2
Python Path:
['C:\\Users\\85291\\Desktop\\vscode\\my-app\\web\\jtravel',
'c:\\Users\\85291\\.vscode\\extensions\\ms-python.python-2022.6.3\\pythonFiles\\lib\\python\\debugpy\\_vendored\\pydevd',
'C:\\Python310\\python310.zip',
'C:\\Python310\\DLLs',
'C:\\Python310\\lib',
'C:\\Python310',
'c:\\Users\\85291\\Desktop\\vscode\\my-app\\web\\env',
'c:\\Users\\85291\\Desktop\\vscode\\my-app\\web\\env\\lib\\site-packages']
Server time: Sun, 05 Jun 2022 16:40:53 +0800
delete to_field='username'
username = models.ForeignKey(Account, on_delete=models.CASCADE)
it is a reason of an error
In DRF I am facing an issue, whenever I do a POST request on the endpoint, on the field "name" which is a text field I get an exception "Field 'id' expected a number but got 'TITLE'", but when I change the value of "name" to an integer the request is successful I don't understand it becauses name is TextField in model and why its mixing Id and Name field with each other. I have deleted the migration files from the Project and DB and re-run the Migrations, but still facing this issue.
Following is my code:
models.py
class Project(models.Model):
admin = models.ForeignKey(User, on_delete=models.CASCADE, related_name='project_crated_by')
name = models.TextField(max_length=225, blank=False, null=False)
project_members = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='members', null=True, blank=True)
created_on = models.DateField(default=timezone.now)
tags = ArrayField(models.CharField(max_length=225, default=''), blank=True)
def __str__(self):
return self.name
objects = models.Manager()
views.py
class ProjectView(viewsets.ViewSet):
def create(self, request):
project_name_exist = Project.verify_project_name(request.data['admin'], request.data['name'])
if project_name_exist:
return Response({'message': 'You already have a project with this name',
'status': status.HTTP_200_OK})
serialized_project = ProjectSerializer(data=request.data)
if serialized_project.is_valid():
serialized_project.save()
return Response({'message': 'Project Created Successfully', 'status': status.HTTP_201_CREATED})
else:
return Response({'error': serialized_project.errors, 'status': status.HTTP_400_BAD_REQUEST})
serializer.py
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = '__all__'
A more generic and non-DIY solution is to use UniqueTogetherValidator on your serializer and let Django sort it out.
from rest_framework.validators import UniqueTogetherValidator
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = '__all__'
validators = [
UniqueTogetherValidator(
queryset=Project.objects.all(),
fields=['admin', 'name'],
message='You already have a project with this name'
)
]
And/or add it to the model for enforcing it on the database.
class Project(models.Model):
admin = models.ForeignKey(User, on_delete=models.CASCADE, related_name='project_crated_by')
name = models.TextField(max_length=225, blank=False, null=False)
project_members = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='members', null=True, blank=True)
created_on = models.DateField(default=timezone.now)
tags = ArrayField(models.CharField(max_length=225, default=''), blank=True)
def __str__(self):
return self.name
objects = models.Manager()
class Meta:
unique_together = ("admin", "name")
I am working on a small application containing models CustomUser and PollQuestion. CustomUser having ManyToMany relation between itself and a CustomUser can have multiple PollsQuestion as well so there is Foreign Key relation between them.
An authenticated user is only able to see polls raised by users he is following, to full-fill this requirement i have written following view**:-**
Actually this is not view this is an utility method returning the polls to original view.
def all_polls_utils(request):
following = request.user.get_all_followings().values_list("id")
user_id = [id[0] for id in following]
all_polls = PollQuestion.objects.none()
for u_id in user_id:
user = CustomUser.objects.get(id=u_id)
polls = user.poll_questions.all()
all_polls = all_polls | polls
return all_polls
Main Question:- Is there in better way to do the same?
Any suggestion will be highly appretiated
I am posting the models bellow:-
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class CustomUser(AbstractUser):
email = models.EmailField(max_length=250, null=False)
name = models.CharField(max_length=50, null=False)
username = models.CharField(max_length=50, null=False, unique=True)
password = models.CharField(max_length=15, null=False)
user = models.ManyToManyField('self', through='Relationship', symmetrical=False, related_name='related_to')
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['name', 'email']
def get_all_polls(self):
pass
def create_relationship(self, person):
status, obj = Relationship.objects.get_or_create(
to_person=person,
from_person=self,
)
return status
def remove_relationship(self, person):
Relationship.objects.filter(
from_person=self,
to_person=person
).delete()
return 'dummy_value'
def get_all_followings(self):
return self.user.all()
class Relationship(models.Model):
from_person = models.ForeignKey(CustomUser, related_name='from_people', on_delete=models.CASCADE)
to_person = models.ForeignKey(CustomUser, related_name='to_person', on_delete=models.CASCADE)
And PollQuestion:-
class PollQuestion(models.Model):
user = models.ForeignKey(CustomUser, null=True, on_delete=models.CASCADE, related_name="poll_questions")
# Other fields
Note:- You can also suggest me a better title for this post?
Thanks in advance,
Hope to here from you soon.
Simply
def all_polls_utils(request):
all_polls_by_followed = PollQuestion.objects.filter(
user__in=request.user.get_all_followings()
)
As an aside, you should probably rename the user many-to-many in CustomUser to e.g. followed_users (with a related name followers).
I'm having a problem with serializing the data with joined tables. Am i doing this right? i'm just a newbie in django.
here's my models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
class Agency(models.Model):
agency_id = models.CharField(primary_key=True, max_length=50)
agency_shortname = models.CharField(max_length=20, blank=True, null=True)
agency_longname = models.CharField(max_length=255, blank=True, null=True)
date_created = models.DateTimeField(blank=True, null=True)
class Meta:
managed = False
db_table = 'agency'
class Users(AbstractBaseUser):
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = []
user_id = models.CharField(primary_key=True, max_length=50)
first_name = models.CharField(max_length=50, blank=True, null=True)
middle_name = models.CharField(max_length=50, blank=True, null=True)
last_name = models.CharField(max_length=50, blank=True, null=True)
username = models.CharField(unique=True, max_length=50, blank=True, null=True)
password = models.CharField(max_length=100, blank=True, null=True)
agency = models.OneToOneField(Agency, models.DO_NOTHING)
date_created = models.DateTimeField(blank=True, null=True)
active = models.CharField(max_length=8)
login_status = models.CharField(max_length=6)
last_login = models.DateTimeField(blank=True, null=True)
class Meta:
managed = False
db_table = 'users'
Then in my serializers.py
from rest_framework import serializers
from .models import Users, Agency
class UserDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = '__all__'
class AgencyDetailSerializer(serializers.ModelSerializer):
agency_id = UserDetailSerializer()
class Meta:
model = Agency
fields = ['agency_id','agency_shortname','agency_longname']
and my views.py
from rest_framework.decorators import api_view, permission_classes
from rest_framework.response import Response
from .serializers import UserDetailSerializer
from .models import Users, Agency
from rest_framework.permissions import IsAuthenticated
#api_view(['GET'])
#permission_classes([IsAuthenticated])
def userData(request):
username = request.GET.get('username')
r_type = request.GET.get('type')
user = Users.objects.get(username=username).values('user_id','first_name','middle_name','last_name','username','email','agency__agency_id','agency__agency_shortname','agency__agency_longname')
user_serializer = UserDetailSerializer(user, many=False)
return Response(user_serializer.data)
I'm getting an error of 'Users' object has no attribute 'values', what seems be the problem? i'm building api based application with vue.js and django rest framework. Thanks a lot
get queryset does not have values attribute, using filter instead.
user = Users.objects.filter(username=username).values(...)
Regarding your case, using get is enough and custom your Serializer like this:
class UserDetailSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = '__all__'
agency = AgencyDetailSerializer(many=False, read_only=True)
Because values is not an attribute of model object. You can call values on queryset object. something like:
user = Users.objects.filter(username=username).values('user_id','first_name','middle_name','last_name','username','email','agency__agency_id','agency__agency_shortname','agency__agency_longname')
Note: You don't need to call values, just change this line to:
from rest_framework.generics import get_object_or_404
...
user = get_object_or_404(Users, **dict(username=username))
user_serializer = UserDetailSerializer(user)
...
Because serializer itself will handle it for you.
I am trying to modify the UserDetailsSerializer with a customized User Detail, but when the server is running, it throws an error of " 'User' object has no attribute 'user'". I tried a lot of methods and none of them work.
My code is:
mode.py
class userProfileModel(models.Model):
GENDER = [
('', ""),
('M', "Male"),
('F', "Female")
]
user = models.OneToOneField(User, related_name='userprofile', on_delete=models.CASCADE, default='')
age = models.DateField(auto_now_add=True)
gender = models.CharField(max_length=10, choices=GENDER, default='')
phone = models.IntegerField(default=0)
user_is_active = models.BooleanField(default=False)
def __str__(self):
return self.user.username
And serializers.py
from rest_auth.serializers import UserDetailsSerializer
from rest_framework import serializers
from .models import userProfileModel
class Profile(serializers.ModelSerializer):
user = UserDetailsSerializer()
class Meta:
model = userProfileModel
fields = ('user',)
class UserDetailsSerializer(UserDetailsSerializer):
profile = Profile(many=True)
class Meta(UserDetailsSerializer.Meta):
fields = UserDetailsSerializer.Meta.fields + ('profile',)
read_only_fields = ('',)
And settings.py
REST_AUTH_SERIALIZERS = {
'USER_DETAILS_SERIALIZER': 'app.serializers.UserDetailsSerializer',
}
When I run this code, it throws this error.
Got AttributeError when attempting to get a value for field profile on serializer UserDetailsSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the User instance.
Original exception text was: 'User' object has no attribute 'profile'.
use source='userprofile' as
class UserDetailsSerializer(UserDetailsSerializer):
profile = Profile(source='userprofile')
class Meta(UserDetailsSerializer.Meta):
fields = UserDetailsSerializer.Meta.fields + ('profile',)
read_only_fields = ('',)
Since User and userProfileModel in a OneToOne relation, you don't want to specify the many=True argument in the serializer