https://docs.djangoproject.com/en/4.0/ref/contrib/sites/#associating-content-with-multiple-sites
How do I get all sites of an article ?
from django.contrib.sites.models import Site
from django.db import models
class Article(models.Model):
headline = models.CharField(max_length=200)
# ...
sites = models.ManyToManyField(Site)
def __str__(self):
print(self.sites) # Always prints sites.None and not siteName1, siteName2
return self.headline
There are all sorts of examples at Many-to-many relationships | Django documentation | Django, with some technical detail at Related objects reference | Django documentation | Django.
Briefly, sites
is a ManyToManyField, which means it’s not one object. It’s a reference to a set of objects, represented in Django as a queryset. So, the complete set of referenced sites should be self.sites.all()
. (The reverse case, where given a site and you want all the articles associated with it would be some_site.article_set.all()
.)
However, if you’re printing None
, that makes me think that you don’t have any sites associated with that article. It should print the reference to the related manager.
I thought I had tried this. I had my class variable name as site. Now I’ve renamed it to website and its all good. Wonder if using site and sites conflicted with the classname Site
?
class Portal(models.Model):
site = models.OneToOneField(Site, on_delete=models.CASCADE)
email = models.EmailField(max_length=100)
google_analytics_code = models.CharField(max_length=25)
created = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=True)
def __str__(self):
return self.site.name
class Article(models.Model):
headline = models.CharField(max_length=200)
sites = models.ManyToManyField(Portal)
No, that wouldn’t be it. Names are context and case-sensitive.
In the example you’ve shown immediately above, Article.sites
isn’t a reference to sites, it’s a reference to Portal
. So article.sites.all()
is a reference to all the Portal
associated with an Article
named article
. You could then iterate over that queryset to get the Site
object for each Portal
.
Got it - I ended up doing ", ".join(str(p) for p in self.websites.all())
1 Like