How do I access django join table data? - django

I'm trying to access data in a join table using django. I have a list of users and a list of groups in a ManyToMany relationship.
class Member(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
groups = models.ManyToManyField(Group, related_name="members")
class Team(models.Model):
name = models.CharField(max_length=25)
creator = models.ForeignKey("footballteamapi.Member", on_delete=models.CASCADE)
The join table looks like this:
footballteamapi_member_teams
id+member_id+team_id
1+1+1
2+1+2
3+2+1
How do I go about accessing that table since there's no coinciding model to reference (i.e. Team.objects.all())?

You can use access the Team table in the reverse direction like so:
member = Member.objects.get(id="<member-id>")
teams = member.team_set.all()
But I like to set the related_name option on the ForiegnKey field like so:
class Team(models.Model):
creator = models.ForeignKey(..., related_name='teams')
...
Then the above changes to:
member = Member.objects.get(id="<member-id>")
teams = member.teams.all()

Related

Have each user have a model attached to them, and that model has a many to one relationship with items

I am trying to create a Django application where each User has one model attached to them ( a list of Plants ) and that model is composed of individual plants. I already know I can have the plants connected to the plant list through a many-to-one relationship using foreign key as shown down below:
class PlantList(models.Model):
plant_list_id = models.AutoField(primary_key=True)
class Plant(models.Model):
plantlist = models.ForeignKey(PlantList, on_delete = models.CASCADE)
name = models.CharField(max_length = 20)
wateringInterval = models.PositiveSmallIntegerField()
However, I want each user to have a plant list attached to them that can be displayed uniquely for each user, according to the plants that they add to their list. How would I make it so that each user has a plant list?
I was trying to have it inside the register form but couldn't figure out how to do it and I wanted each plantlist to have a unique ID so that I can add plants to it easier.
class AddNewPlant(forms.Form):
name = forms.CharField(label='Name',max_length = 20)
wateringInterval = forms.IntegerField(label='Watering Interval')
The thing is, you don't need the model PlantList.
What you should do instead is: set a ForeignKey to the User Model inside the Plant Model, and in that foreign_key set a related_name='plants'.
To access the User Model use:
from django.contrib.auth import get_user_model
code example:
class Plant(models.Model):
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='plants')
name = models.CharField(max_length = 20)
wateringInterval = models.PositiveSmallIntegerField()
Then you can access all user's plants using:
first_user = get_user_model().objects.first().plants
Try this:
class User(models.Model):
plant_list = models.ForeignKey(PlantList, on_delete=models.CASCADE)
this is for connecting plant_list with the user. Also, you need to change the relationship between plant and plant_list, so that users can have the same plants as well like below:
class Plant(models.Model):
plantlist = models.ManyToManyField(PlantList)
that way different users can have the same plants on their plant_list and every user has only one plant_list.

Django two parameter filter query with foreign key

My Django models look like this:
class User(models.Model):
userid = models.CharField(max_length=26,unique=True)
#some more fields that are currently not relevant
class Followers(models.Model):
user = models.ForeignKey('User',related_name='usr')
coins = models.IntegerField()
followers = models.CharField(max_length=26, null=True, blank=True)
I would now like to make a filter query in my Followers table selecting every entry where users have ID x and followers have ID y (I expect to get one result from the query).
To visualize what I have tried and know won't work is this:
queryfilter = Followers.object.filter(followers=fid, user=uid)
and this:
queryfilter = Followers.object.filter(followers=fid, user__userid=uid)
In the end I would like to access the coins:
c = queryfilter.coins
It may be possible that I cannot do it with one single query and need two, since I am trying to do a filter query with two tables involved.
Firstly, I have modified your 'Followers' model (for naming convention).
models.py
class Follower(models.Model):
user = models.ForeignKey('User', related_name='followers')
coins = models.IntegerField()
key = models.CharField(max_length=26, null=True, blank=True)
Your queryset should be ..
views.py
#coins
coins = Follower.objects.filter(key=fid, user__userid=uid).get().coins

Query a many to many field of referenced table using ORM

My models are as follows:
class AppUser(models.Model):
id = models.AutoField(primary_key=True)
user = models.OneToOneField(User)
states = models.ManyToManyField(State)
class ABC(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=50)
email = models.EmailField()
app_user = models.ForeignKey(AppUser, null=True, blank=True)
I want to query my database for list of objects present in ABC model and I want to filter it according to the list of States.
I am trying something like this:
ABC.objects.filter(app_user__states__in = state_list).values('id','name')
But this is not working. Can I even access a many to many field like this or do I need to create a custom through table.
Yes, you can.
For queryset:
ABC.objects.filter(app_user__states__in = [1,2]).values('id', 'name')
you'll get sql like this:
>>> print(ABC.objects.filter(app_user__states__in = [1,2]).values('id', 'name').query)
SELECT "test_abc"."id", "test_abc"."name"
FROM "test_abc"
INNER JOIN "test_appuser" ON ("test_abc"."app_user_id" = "test_appuser"."id")
INNER JOIN "test_appuser_states" ON ("test_appuser"."id" = "test_appuser_states"."appuser_id")
WHERE "test_appuser_states"."state_id" IN (1, 2);
Looks fine. Maybe it doesn't work as you expected?

Django two-way relationship between group and group members

I am trying to model a two-way relationship between group members and the group they belong to.
More specifically, I'd like to model something like this:
class Member(models.Model):
name = models.CharField(max_length=50)
my_group = models.ForeignKey('Group')
#leader = models.BooleanField()
class Group(models.Model):
name = models.CharField(max_length=50)
leader = models.ForeignKey('Member')
So I want every member to be linked to a group. But each group should have a leader. I'd normally add a "leader" attribute to assign a leader for a group or add an extra model / table. However, I would like to be able to choose the leader from the members list for a specific group in the Django Admin interface and the above attempt results in an error of course, because the two models reference each other.
Here's the error:
ERRORS: app1.Group.leader: (fields.E303) Reverse query name for 'Group.leader' clashes with field name 'Member.my_group'. HINT: Rename field 'Member.my_group', or add/change a related_name argument to the definition for field 'Group.leader'
What's the best way to achieve this?
You can have intermediate model called Membership to define the level of membership
models:
class Member(models.Model):
name = models.CharField(max_length=50)
# may be a relations to User here
class Group(models.Model):
name = models.CharField(max_length=50)
members = models.ManyToManyField(Member, through=Membership)
class Membership(models.Model):
group = models.ForeignKey(Group)
members = models.ForeignKey(Member)
# member level
is_leader = models.BooleanField(default=False)
you can check the documention on ManyToMany fields for some more examples.

how to query all objects in one set that do not have a foreign key in another object in django

I have the following objects:
class Customer(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
customer = models.ForeignKey(Customer)
class GroupMember(models.Model):
group = models.ForeignKey(Group)
member = models.ForeignKey(Member)
class Member(models.Model):
customer = models.ForeignKey(Customer)
I can get all the members assigned to a group with this:
group_members = group.groupmember_set.all()
All of the members available for a certain customer with this:
member_list = customer.members.all()
I want to create a list of all of members available for a customer that are not assigned to a group. Something like:
not_group_members = Member.objects.filter(?)
How can I create this query?
With your current setup, that's not possible since Member has a non-nullable foreign key to group.
However, if you change to this:
class Member(models.Model):
customer = models.ForeignKey(Customer, null=True)
Then you can find Members that are not in any group.
not_group_members = Member.objects.filter(group=None)
customer.members.filter(groupmember_set__isnull=True)
(I used members here because you did, even though the default related name would be member_set.)
I was able to accomplish this with:
customer.members.filter(groupmember__isnull=True)