I have a simple module below and I have a field called following in the Person module.
class Person(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
image = models.FileField(upload_to="images/",blank=True,null=True)
following = models.ManyToManyField('self', related_name='followers', symmetrical=False, blank=True, null=True)
def __unicode__(self):
return self.name
I created 3 accounts called sarah , jim and ben. I managed to get Sarah to follow jim and ben but when I display who sarah followed , it return a querysets not their object themself . How can I work in reverse to get them into objects themself so I can relate them to my Person module and display the names of the people who sarah are following.
This is the part I don't understand
>>> from pet.models import *
>>> from django.contrib.auth.models import User
>>> sarah = User.objects.get(username='Sarah')
>>> jim = User.objects.get(username='Jim')
>>> ben = User.objects.get(username='Ben')
>>> Sarah = Person.objects.get(user=sarah)
>>> Jim = Person.objects.get(user=jim)
>>> Ben = Person.objects.get(user=ben)
>>> Sarah.following.add(Jim,Ben) //setup the many to many relationship
>>> Sarah.save()
>>> Sarah.following.all() // return a queryset of Person objects which john is following.
[<Person: Jim>, <Person: Ben>]
I want to return all the user objects that user are following in my template.
#SI Eric
>>> Sarah.following.all().values_list('name',flat=True)
[u'Jim', u'Ben']
>>> p = Sarah.following.all().values_list('name',flat=True)
>>> person = Person.objects.filter(user=p)
>>> print person
class Board(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
def __unicode__(self):
return self.name
Sarah.following.all().values_list('name', flat=True)
would output
['Jim', 'Ben']
As bernie suggested, you can set the unicode function and the default queryset returned will do the same. In this particular type of instance I prefer to be more explicit with what I'm getting from the objects, but that's just me.
Edit after question was updated:
I'm not sure I follow what you're trying to do. You have a queryset of the objects of the people who are following sarah. If you just want the names, the values list above will work. If you want to iterate over each individual object then you would do something like this:
for person in Sarah.following.all():
# person is an instance of Person
# you can access all the properties of the object by accessing person
print person.name
Alternatively, pass the entire queryset to the template by adding it to the context in the view:
context['following'] = Sarah.following.all()
Then in the template you could do this (for example):
<ul>
{% for person in following %}
<li>{{ person.name }}</li>
{% endfor %}
</ul>
Edit:
Both from within the template and the view code you can access any of the properties of each 'Person' object by just directly referencing them. So for example if you want to access the properties of the 'User' object that person has a Foreign Key relation to, you would just access it's properties directly, like so:
person.user.username
person.user.email
etc...
One last edit:
To get a queryset of 'User' objects based on the 'following` queryset for a person, you could do this:
users = User.objects.filter(pk__in=Sarah.following.all().values_list('user__pk', flat=True)
From there you should be able use that filter boards and other objects that reference the User model:
boards = Board.objects.filter(user__in=users)
Related
I have standart User model and Categories model like this;
class Categories(models.Model):
name=models.CharField(max_length=100)
def __str__(self):
return self.name
And here is another class for relation which associates some users with some categories;
class Interested(models.Model):
user = models.ManyToManyField(User)
category = models.ManyToManyField(Categories)
For example if I have Users such as Bob, Eric, Oliver, Michael
and categories such as Basketball, Football
and relations like that
Bob -> Basketball,Football
Eric-> Basketball
Oliver -> Football
(michael not interested in anything)
I want to get list of who interested in what? How can I handle this? Thank you for your help.
You can get the instance of Interested for a user with:
interested = Interested.objects.get(user="your user")
and list the linked categorys by:
interested.category.all()
But I would, if not nescessary for any other reason, just link the category directly to the user....
class Category(models.Model):
name = models.Charfield()
user = models.ManyToManyField(user)
This way you can get the categorys for a user:
categorys = Category.objects.filter(user="youruser")
and if you pass this to your template just do:
{% for category in categorys %} {{ category.name }}{% endfor %}
To get the users interested in a category, just get the Category instance with:
category = Category.objects.get(name="categoryname")
and the the related user models with:
usersincategory = category.user.all()
if you want this for all categorys just use a normal for loop:
categorys = Category.objects.all()
for category in categorys:
category.user.all()
I suppose this must be possible judging by this post but I can't seem to work out the syntax. I need to get the blog object with the picture field via the author foreign key.
Is this possible with get_object_or_404, and if so how?
#models.py
class Blog(models.Model):
author = models.ForeignKey(MyUser)
#author
class MyUser(AbstractUser):
picture = models.ImageField()
blog = get_object_or_404(Blog, pk=blog_id)
The query you want is like so (from the docs):
from django.db import models
class City(models.Model):
# ...
pass
class Person(models.Model):
# ...
hometown = models.ForeignKey(City)
class Book(models.Model):
# ...
author = models.ForeignKey(Person)
And then your query is:
b = Book.objects.select_related('author__hometown').get(id=4)
p = b.author # Doesn't hit the database.
c = p.hometown # Doesn't hit the database.
b = Book.objects.get(id=4) # No select_related() in this example.
p = b.author # Hits the database.
c = p.hometown # Hits the database.
except in your case your query would be: Picture.objects.select_related('author__blog').get(picture_name='somefilename.jpg')
You're saying I want the picture (and while your at it, the Author and their Blog) that relates to the picture name 'somefilename.jpg'. At least if I've understood your question and DB structure it is.
As Pureferret suggested in his answer
you can do it in following way,
blog = Blog.objects.get(pk=blog_id)
author = blog.author
and if you want to show that image in template just use
{{ auther.picture.url }}
I implemented a ManyToManyField for a following feature which allows users to follow other users and if they follow other user .
They would able to retrieve their's objects.
This is my module
class Person(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100, blank=True)
image = models.FileField(upload_to="images/",blank=True)
following = models.ManyToManyField('self', related_name='followers', symmetrical=False, blank=True, null=True)
birthday = models.DateField(blank=True,null=True)
def __unicode__(self):
return self.name
class Board(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
created = models.DateTimeField(auto_now_add=True)
picture = models.OneToOneField('Picture',related_name='picture',blank=True,null=True)
def __unicode__(self):
return self.name
The problem is when a user is following 2 users . I am only able to retrieve a single user objects instead of both users.
For example I created 3 users , Jimmy , Sarah and Simon . Sarah is following Simon and Jimmy
Jimmy has a board called Jimmy's Math Board ,Jimmy English Board
Simon has a single board called Simon's Whiteboard
The problem is underneath
>>> from pet.models import *
>>> from django.contrib.auth.models import User
>>> user = User.objects.get(username='Sarah')
>>> person = Person.objects.get(user=user)
>>> sarah = Person.objects.get(user=user)
>>> sarah.following.all() # SARAH IS FOLLOWING JIMMY AND SIMON
[<Person: Jimmy>, <Person: Simon>]
>>> users = User.objects.filter(pk__in=sarah.following.all().values_list('user__pk',flat=True))
>>> users
[<User: Jimmy>, <User: Simon>] # I'm able to retrieve their users
>>> board = Board.objects.filter(user=users) # when I search for their boards , I only retrieve a single user . Jimmy's board not Simon
>>> board
[<Board: Jimmy's Math Board>, <Board: Jimmy English Board>]
>>> person = Person.objects.filter(user=users)
>>> person
[<Person: Jimmy>]
How Can I retrieve both of these users board?
Because board = Board.objects.filter(user=users) is filtering by user it expects one user to be provided. If you were to do something like board = Board.objects.filter(user__in=users) which uses the __in filter, the filtering will correctly use the list of user objects.
You could also use a flat list of id's instead of objects like so board = Board.objects.filter(user__in=sarah.following.all().values_list('user__pk',flat=True))
I am building a simple interface to a biological database using the django-admin to populate the db. I want tot to use a many-to-many relationship for a questionnaire to fish species (one questionnaire can have more than one species and one species can be present in more than one questionnaire). The two models in question:
class Species(models.Model):
fish_spp_name = models.CharField(max_length=255, unique=True)
class Questionaire(models.Model):
# ...
fish_caught = models.ManyToManyField(Species)
now, I want to my data to contain a number of each species caught, per questionnaire. So, for example, I can associate 3 different species with questionnaire id=1, but how do I include that, say 2 of the first species, 1 of the second and 4 of the third were caught?
Check this: Extra fields on many-to-many relationships
Define another models Caught to hold the information per catch. Give it a related_name to make it easier to refer to in your code. You might also want to unique_together appropriate fields.
class Species(models.Model):
name = models.CharField(max_length=255, unique=True)
def __unicode__(self):
return '%s/%d' % self.name
class Questionaire(models.Model):
pass
class Caught(models.Model):
species = models.ForeignKey(Species)
number = models.IntegerField()
questionaire = models.ForeignKey(
Questionaire, related_name='catches')
def __unicode__(self):
return '%s/%d' % (self.species.name, self.number)
Use it like this:
(InteractiveConsole)
>>> from app.models import *
>>> s1 = Species(name='Salmon')
>>> s1.save()
>>> s2 = Species(name='Mackerel')
>>> s2.save()
>>> q = Questionaire()
>>> q.save()
>>> c1 = Caught(species=s1, number=7, questionaire=q)
>>> c2 = Caught(species=s2, number=5, questionaire=q)
>>> c1.save()
>>> c2.save()
>>> q.catches.all()
[<Caught: Salmon/7>, <Caught: Mackerel/5>]
>>>
I'm creating a Person Group and Membership as described in Django docs for intermediate model.
class Person(models.Model):
name = models.CharField(max_length=128)
def __unicode__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __unicode__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
It is possible to access the Person from a Group object with:
>>>Group.members.name
Does Django creates another query to fetch the Person?
Can I access the date_joined field from a Group object?
The thing that confuses me is that I would expect to get the Person name field with:
>>>Group.members.person.name
What happens if a Person has a field 'name' and also the intermediate model have a field 'name'.
The members field in your example is a ManyToManyField, so it's a way to access many people rather than one person.
The object that is under the members field is actually a special type of Manager, not a Person:
>>> print my_group.members
<django.db.models.fields.related.ManyRelatedManager object at 0x181f7d0>
To understand better what a Manager is, see the documentation.
To access a person's name you would do for example:
>>> for person in my_group.members.all():
>>> print person.name
You cannot access the fields in your Membership model via the Manager in the members field. To access any of the fields in it you would do:
>>> for membership in my_group.membership_set.all():
>>> print membership.date_joined
And so if you had a field called name in your Membership model, you would access it like this:
>>> for membership in my_group.membership_set.all():
>>> print membership.name
A second way to access a Person's name would be:
>>> for membership in my_group.membership_set.all():
>>> print membership.person.name
Note that membership_set is a default name for the manager pointing towards the membership, but it can be changed by specifying related_name in the corresponding foreign key. For example if the foreign key from the Membership to the Group would be defined like such:
group = models.ForeignKey(Group, related_name="group_members")
Then you would access the manager using group_members:
>>> for membership in my_group.group_members.all():
>>> print membership.name
Hope that helps a little :)
Use the manager of the membership class:
MyGroup.membership_set.all()
instead of:
MyGroup.members.all()