Better way to fetch related object, in Self Refrencing ManyToMany Relationship? - python

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).

Related

Get all post from users which my user follow

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())

Username from django auth_user as foreign key in another table

I have this model:
models.py
class InsertIP(models.Model):
sourceIP=models.CharField(max_length=18)
destinationIP=models.CharField(max_length=18)
port=models.CharField(max_length=10)
comment=models.CharField(max_length=200, null=True, blank=True)
class Meta:
db_table="fw_rules"
And I need to add column User which contains the name of user who creates the record. I need to create foreign key from username from django auth_user
Can you please help me?
Thank you.
You can do it like this:
class InsertIP(models.Model):
sourceIP = models.CharField(max_length=18)
destinationIP = models.CharField(max_length=18)
port = models.CharField(max_length=10)
comment = models.CharField(max_length=200, null=True, blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
db_table="fw_rules"
Then in your view you will access it like this:
ip = InsertIp.objects.get(pk=pk) # query the InsertIp object
user = ip.user # get the user using a . operator

I cannot register a user using Django-Rest-Framework

I can't add a new user using Django Rest Framework. Here is my code from models.py:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
password = models.CharField(max_length=15, default= None)
first_name = models.CharField(max_length=100, validators=[name_validator])
last_name = models.CharField(max_length=100, validators=[name_validator])
email = models.CharField(max_length=100, validators=[mail_validator])
created_at = models.DateTimeField(auto_now_add=True)
As you can see I am using models.OneToOneField cause I want to extend the default user to add some more fields.
Bellow is my serializers.py file:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
permissions_classes = [
permissions.AllowAny
]
fields = '__all__'
The viewset is the following:
class UserViewset(viewsets.ModelViewSet):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
When I go to my endpoints and try to add a new user, I cannot put anything in the "user" field:
Click for image
I am a beginner and it would be of great help.
Thank you!
you can to this
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
password = models.CharField(max_length=15, default= None)
first_name = models.CharField(max_length=100, validators=[name_validator])
last_name = models.CharField(max_length=100, validators=[name_validator])
email = models.CharField(max_length=100, validators=[mail_validator])
created_at = models.DateTimeField(auto_now_add=True)
serializer.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
class ProfileSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
class Meta:
model = Profile
fields = '__all__'
views.py
class UserViewset(viewsets.ModelViewSet):
queryset = Profile.objects.all()
serializer_class = ProfileSerializer
permission_classes = [permission. AllowAny,]
When you want to extend the default user to add some more fields, the best way for that is substituting a custom User model by inheritance the AbstractUser model. Using this way, you can CRUD the user easily.

How to find the correct relationships between my tables?

I'm trying out a new django social media project which has User, Status and Comment. The relationship between them is such that, User has a relationship to Status, User has relationship to Comment and there also exists a relationship between Status and comment.
So to achieve this I built four tables, i.e, User, Comment, Status and UCSModel. Where UCSModel is the table which has the foreign keys of the rest three tables. UCSModel is more like the relations table consisting of all ID's
So here is my models.py
from django.db import models
class User(models.Model):
username = models.CharField(max_length=50, unique=True)
email = models.CharField(max_length=200)
password = models.CharField()
def __str__(self):
return self.username
class Comment(models.Model):
comment = models.CharField()
def __str__(self):
return self.comment
class Status(models.Model):
status = models.CharField()
def __str__(self):
return self.status
class USCRelation(models.Model):
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
comment = models.ForeignKey(Comment, null=True, on_delete=models.CASCADE)
status = models.ForeignKey(Status, null=True, on_delete=models.CASCADE)
Being new to Django, I wanted to know if there is any better way of building relationships between tables. Especially when all the three tables are interrelated to each other like in my case above.
Find the below DB design, this would help you optimising your queries:
from django.db import models
class User(models.Model):
username = models.CharField(max_length=50, unique=True)
email = models.CharField(max_length=200)
password = models.CharField()
def __str__(self):
return self.username
class Status(models.Model):
status = models.CharField()
def __str__(self):
return self.status
class Comment(models.Model):
comment = models.CharField()
status = models.ForeignKey(Status, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.comment
Hope this helps!

radio buttons incorrectly written to the database in django

I've a registration form, where user must chose one of 2 options.
Django renders all correctly, django admin also have it ok, but db records all possible choices as value.
forms.py
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email','password1','password2']
class UserProfileForm(forms.ModelForm):
terms_compliance = forms.BooleanField(label=mark_safe('I agree with terms and conditions '))
class Meta:
model = UserProfile
widgets = {'role': forms.RadioSelect}
fields = ('role','terms_compliance')
def __init__(self):
self.fields['terms_compliance'].initial = True
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
role_choices = [('publisher','Publisher'), ('advertiser','Advertiser')]
role = models.CharField(max_length=15, choices=role_choices, default=None)
terms_compliance = models.BooleanField()
def __str__(self):
return self.user.username
In new instance (which is user.userprofile.role_choices) I need advertiser or publisher, but all I have is: [('publisher','Publisher'), ('advertiser','Advertiser')]
If you want to provide choices in a Database Field. Do like this:
class UserProfile(models.Model):
class RoleChoice(ChoiceEnum):
PUBLISHER = 'Издатель'
ADVERTISER = 'Рекламодатель'
user = models.OneToOneField(User, on_delete=models.CASCADE)
role = models.CharField(max_length=15, choices=RoleChoice.choices(), default=None)
terms_compliance = models.BooleanField()
def __str__(self):
return self.user
In Views.py, populate the DB like this.
For example:
...
choice = request.query_params.get('choice') or UserProfile.RoleChoice.PUBLISHER.value
...
For more details read from here: https://django-mysql.readthedocs.io/en/latest/model_fields/enum_field.html

Categories

Resources