How can i alter my code so that the user logged is not able to follow themselves. I tried unique_together but could not get it to work
I will be using a button on other users profile pages to add the user to the logged in users following list in this table.
class FollowList(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
following = models.ManyToManyField(User, related_name='followers')
I'd suggest you use something like intermediary model. ManyToMany in fact is a model with two ForeignKey fields: first is for your FollowList model and second is for linking the User instance. So you have an extra relation to your model. Better way:
class Follow(models.Model):
follower = models.ForeignKey(User, on_delete=models.CASCADE, related_name='my_following_users')
following = models.ForeignKey(User, on_delete=models.CASCADE, related_name='my_followers')
class Meta:
unique_together = (
('follower', 'following'),
)
def save(self, *args, **kwargs):
if self.follower.pk != self.following.pk: # preventing of following themselves
return super().save(*args, **kwargs)
# use like this
dev YourView():
Follow.objects.create(follower=request.user, following=user)
UPD:
If you need to set multiple followers with once request, do something like this:
dev YourView():
items = []
for uid in ("<user ids here>"):
items.append(Follow(follower=request.user, following__pk=uid))
Follow.objects.bulk_create(items)
Related
The Viewset def list looks like this:
class ThreeDimensionalModelViewSet(viewsets.ViewSet):
serializer_class = ThreeDimensionalModelSerializer
queryset = ThreeDimensionalModel.objects.all()
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def list(self, request):
models = ThreeDimensionalModel.objects.all()
serializer = ThreeDimensionalModelSerializer(models, many=True)
print(request.user.id)
return Response(serializer.data)
The serializer looks like this:
class ThreeDimensionalModelSerializer(serializers.ModelSerializer):
class Meta:
model = ThreeDimensionalModel
fields = ['File', 'Uploaded', 'Owner', 'Previous', 'SharedWithUser']
read_only_fields = ['Owner']
The model looks like this:
class ThreeDimensionalModel(models.Model):
File = models.FileField(upload_to='models')
Owner = models.ForeignKey('auth.User', on_delete=models.SET_NULL, null=True, related_name='Owner')
Uploaded = models.DateTimeField(auto_now_add=True)
Previous = models.ForeignKey("self", on_delete=models.SET_NULL, default=None, null=True)
SharedWithUser = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='SharedWithUser')
When a user requests models at /api/models it should only show the models that are the same owner Id as his.
If no additional data is sent with that request then obviously you can't filter by user.
The straightforward way to do it is that for logged in users the cookie will contain user information such as userId.
When your endpoint recognizes the user who made the requested is logged in, it will use that as the filter for the query instead of all() as seen in the Django docs
https://docs.djangoproject.com/en/3.2/topics/db/queries/#retrieving-specific-objects-with-filters
To summarize - if the user is not logged in (or supplies the information as part of the request in some way) then the request is anonymous and there is no way to know who made it
I've created a Many-to-Many relationship for the model UserProfile, to enable users to grant access to a particular feature to one another. The relationship works as expected with the use of symmetrical=False to ensure a user access is one-way.
Model
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone = models.IntegerField(blank=True, null=True)
image = models.ImageField(upload_to='profile_image', default="default_thumbnail.jpg")
department = models.ForeignKey(DepartmentModel, on_delete=models.SET_NULL, null=True)
allow_booking_access = models.ManyToManyField("self", blank=True, symmetrical=False)
def __str__(self):
return self.user.username
class UserInline(admin.StackedInline):
model = UserProfile
can_delete = False
verbose_name_plural = 'UserAccounts'
class UserAccount(BaseUserAdmin):
inlines = (UserInline,)
I am able to query the users that a particular user wants to grant access to via: (for example id=1)
UserProfile.objects.get(id=1).allow_booking_access.all()
However, I would like to retrieve the users that have granted access to the particular user.
How would I do this?
Additional Information
Using Relation
Database Information
You can filter with:
UserProfile.objects.filter(allow_booking_access=my_user)
With your sample data, it will return the UserProfile with id=7 for this query.
or if you want to query in reverse:
UserProfile.objects.filter(userprofile=my_user)
With your sample data, it will return the UserProfiles with id=7, id=3, user=4 and user=7 for this query.
I have following models,
class User(models.Model):
name = models.CharField(max_length=255)
...
class InsuranceProfile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
...
class ProductExpertiseMaster(models.Model):
class Meta:
db_table = 'product_expertise_master'
name = models.CharField(max_length=255)
main_category = models.CharField(max_length=255)
class UserProductExpertise(models.Model):
user = models.ForeignKey(User, on_delete=models.DO_NOTHING)
product_expertise = models.ForeignKey(ProductExpertiseMaster, on_delete=models.DO_NOTHING)
So what I am trying to do is I want to filter records based on various fields some of the belong to User model & some of them belong to the InsuranceProfile model.I am filter the records based on User & InsuranceProfile model which is working fine. Now i want to add one more filter which will be based on the UserProductExpertise model.I want to get all the InsuranceProfiles with User details who have some matching condition with product expertise entries in UserProductExpertise model. Any help would appreciated.
You can try like this using __isnull:
InsuranceProfile.objects.filter(user__userproductexpertise__isnull=False)
It will return all the users who has an entry in in UserProductExpertise model. For querying, you need to use all lowercase of the model name, (ie userproductexpertise) and add __isnull at the end of it.
I think you should make some changes in your models before proceeding further.
UserProductExpertise model is the bridge table between ProductExpertiseMaster and User, which provides a many-to-many relationship. If you won't add additional fields to UserProductExpertise model, you can drop it and define user relation in ProductExpertiseMaster model.
If you prefer using seperate model for this relationship, on_delete=models.DO_NOTHING is prone to errors, you can change it to models.CASCADE
Here is an example with many-to-many relation:
class User(models.Model):
name = models.CharField(max_length=255)
class InsuranceProfile(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.CharField(("Content"), max_length=500)
class ProductExpertiseMaster(models.Model):
class Meta:
db_table = 'product_expertise_master'
name = models.CharField(max_length=255)
main_category = models.CharField(max_length=255)
user = models.ManyToManyField(User, verbose_name=("Users"), related_name="expertises")
For filtering your query:
InsuranceProfile.objects.filter(user__expertises__isnull=False)
I am working on developing a Trello-like website with Django Rest Framework.
I want to add selected users to BoardAccess model, a through table for User model and Board model, two of which are in Many to Many relationship. Being added to BoardAccess table will mean that the respective users will be having access to matching boards.
Models.py
class Board(models.Model):
name = models.CharField(max_length=50)
access_granted = models.ManyToManyField(User, through='BoardAccess', related_name='access_boards')
team = models.ForeignKey(Team, on_delete=models.CASCADE) # a team can have many boards
class BoardAccess(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
board = models.ForeignKey('Board', on_delete=models.CASCADE)
For User, I am currently using Django's default Auth User model and extending it with a Profile model via OneToOne Field.
Serializers.py
class BoardAccessSerializer(serializers.ModelSerializer):
members = serializers.SerializerMethodField()
added_users = # ???
new_name = serializers.CharField(
write_only=True, required=False, source='name') # in case of requests for renaming the board
def get_members(self, instance):
members = User.objects.filter(profile__team=instance.team)
return UserBoardSerializer(members, many=True).data
I would like to know what field / relations / another serializer should be assigned to added_users, which I think should be write_only=True, in order to successfully de-serialize input from the client-side containing primary keys of selected users.
get_members() method is used to first display information of all team members, from which a client will select users to be added to the board.
Views.py
class BoardAccessRetrieveUpdateAPIView(generics.RetrieveUpdateAPIView):
serializer_class = BoardAccessSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
team_id = self.kwargs.get('team_id')
team = get_object_or_404(Team, id=team_id)
queryset = Board.objects.select_related(
'team').prefetch_related(
'access_granted').filter(team=team)
return queryset
I am new to DRF, so there may be a lot of points to be improved from the above. I would really appreciate every help!!
You can override the update method in your serializer, and get the user ids from the client side from initial_data
def update(self, instance, validated_data):
// do the actions on create
users = self.initial_data.get('users')
instance.access_granted.add(*users)
instance.save()
return instance
Also when using ModelSerializer have to add Meta class:
class BoardAccessSerializer(serializers.ModelSerializer):
class Meta:
model = Board
fields = "__all__"
I am new to Django and trying to create an App with two User Types (Freelancers and Customers). I understand how to create a User profile Class and it works well for me:
class UserProfile(models.Model):
user = models.OneToOneField(User)
description = models.CharField(max_length=100, default='')
country = models.CharField(max_length=100, default='')
website = models.URLField(default='')
phone = models.IntegerField(default=0)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
This works well for me on a one user type user. But now I am building an app with 2 types of users (freelancers and customers), what is the best approach to get this done. Both users will have different view and info. Should I:
Create 2 different apps, and repeat the normal registeration and login for each.
If I do the above, hope the freelancers when logged in won't access customers view.
How do I add user type to the user profile if I decide to use one app and model for it.
Please I need a step by step beginner approach, or a link to relevant source.
Thanks.
You could try this:
class UserProfile(models.Model):
user = models.ForeignKey(User)
#define general fields
class Freelancer(models.Model):
profile = models.ForeignKey(UserProfile)
#freelancer specific fields
class Meta:
db_table = 'freelancer'
class Customers(models.Model):
profile = models.ForeignKey(UserProfile)
#customer specific fields
class Meta:
db_table = 'customer'
You can then have as many Users as you want from the UserProfile.
You should need just use Groups Django mechanism - you need to create two groups freelancer and let say common and check whether user is in first or second group - then show him appropriate view
To check whether user is in group you can use
User.objects.filter(pk=userId, groups__name='freelancer').exists()
You Could Try extending the Default Django Auth User like this
Create an App with Account or Whatever name you like , then in models.py write like below
class User(AbstractUser):
is_head = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_public = models.BooleanField(default=False)
Add Auth Extended Model in Settings.py
AUTH_USER_MODEL = 'accounts.User'
Migrate your Account app and you are all set with Your User Extended Model.