This seems to be simple question but it is never answered anywhere and there is no obvious answer. I have two "cascading" ManyToMany models:
User has ManyToMany to Tag:
class User (models.Model):
...
watches_tags = models.ManyToManyField(Tag, related_name='watched_tag_set', blank=True, null=True)
ignores_tags = models.ManyToManyField(Tag, related_name='ignored_tag_set', blank=True, null=True)
and Tag has ManyToMany to Status:
class Tag (models.Model):
tag = models.TextField ()
status = models.ManyToManyField (Status)
Is there a ORM expression that will give me all the Statuses tagged with tags any given User watches/ignores? I could iterate over Tags in logic and concatenate QuerySets, but I want to use this in much more complicated Q-expression based query, and I want as much work to be pushed to the database engine.
Try this:
watched_statuses = Status.objects.filter(tag__watched_tag_set=user)
ignored_statuses = Status.objects.filter(tag__ignored_tag_set=user)
(Note that your related names on Tag are confusing since watched_tag_set is a set of Users, not Tags.)
Related
The products listed have two tags, one for category and one for more fine grained description. The problem is some of the tags have ampersands and spaces etc. A choicefield seems innapropriate, does DRF handle these things gracefully with a charfield?
Edit: For instance,
class Product(models.Model):
product_department = models.CharField(max_length=75, db_index=True)
product_detail = models.CharField(max_length=255, db_index=True)
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
# department could be "Clothing" for instance
# detail could be "scarves(winter) & winter accessories"
So I guess the question is how to keep get requests clean in that situation without creating a complicated integer or character mapping with a choicefield.
More details please:)
By tags do you mean fields? Can you show us the models?
My models.py are like this:
class Tag(models.Model):
name = models.CharField(max_length=255, unique=True)
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
tags = models.ManyToManyField(Tag, related_name='article_tags')
Lets say, I have a tag wit the name 'Movie Review', how do I get the number of articles that has a relationship with this tag? As in the count.
Thanks.
There are two ways to get the articles that are using a specific tag (your_tag in the examples below):
Either using a filtering on Article: Article.objects.filter(tags=your_tag)
Or using the related relation: your_tag.article_tags.all()
Once you did that, you can just use .count() to get the number of rows returned.
You can use Django's .count().
tag = Tag.objects.get(name='Movie Review')
article_count = tag.article_tags.all().count()
Use this query..
Article.objects.filter(tags__name='Movie Review')
to get the count
Article.objects.filter(tags__name='Movie Review').count()
Edited my question to make it more clear. And I am sorry if what i'm asking is obvious or easy to solve, I am just starting out.
Hello, I am developing a website which has 2 models for the content: Article and Comic. Now I want a system that allows me to tag Articles and Comics with certain keywords. These keywords can then be used to retrieve a list of objects from both the models and display them.
At first, I set up the system as follows:
class Article(models.Model):
.....
class Comic(models.Model):
.....
class Tag(models.Model):
tag = models.CharField(max_length = 25)
article = models.ForeignKey(Article)
comic = models.ForeignKey(Comic)
However, this did not work out.
Then I tried implementing 2 different tag models for the 2 different models: ArticleTag and ComicTag, in the following way:
class Article(models.Model):
.....
class ArticleTag(models.Model):
tag = models.CharField(max_length = 25)
article = models.ForeignKey(Article)
class Comic(models.Model):
.....
class ComicTag(models.Model):
tag = models.CharField(max_length = 25)
comic = models.ForeignKey(Comic)
This also did not work, as I was able to get a list of tags of an article, but I could not get a list of articles that had the same tag. And also it was using 2 different tag models so that was also not preferable.
A user suggested a ManyToManyField based on the previous information I had provided. However, how would this exactly work?
Now, what is the best way to create a content tagging system using Django? It should preferably work with just 3 models: Article, Comic and Tag, not 4 like I tried. In conclusion, I want a system that lets me get a list of objects from 2 models using one single tag. So, I would really appreciate help of any kind as I am an amateur programming (pretty obvious) and I am completely stumped by this problem.
You could use a ManyToManyField.
Basically something like the following. It's more intuitive if you change the name of ArticleTag.tag to ArticleTag.name. I've also added a related_name field to the M2M relationship so you can retrieve an article based on its tags using Article.objects.filter(tags__name="tag_name_here"). In the reverse direction, you could get all the tags for an article using ArticleTag.objects.filter(article__title="article_name_here").
class Article(models.Model):
title = models.CharField(max_length=140)
.....
class ArticleTag(models.Model):
name = models.CharField(max_length = 25)
articles = models.ManyToManyField(Article, related_name="tags")
[EDIT based on your updated question]
Based on your update, you could do this:
class Article(models.Model):
.....
class Comic(models.Model):
.....
class Tag(models.Model):
tag = models.CharField(max_length = 25)
articles = models.ManyToManyField(
Article,
related_name="tags",
blank=True,
null=True
)
comics = models.ManyToManyField(
Comic,
related_name="tags",
blank=True,
null=True
)
This way an Article/Comic can have many different tags, and any one tag can tag many different articles/comics. The blank=True, null=True means that you don't have to have an associated comic/article with a given tag, i.e., one tag could happen tag only comics but no articles.
To get a list of articles with the same tag:
Article.objects.filter(tags__name="your_tag_name")
I have just begun to play around with Django admin views, and to start off, I am trying to do something very simple: showing several fields in the listing of objects using list_display as explained here: https://docs.djangoproject.com/en/dev/ref/contrib/admin/
This is my dead simple code:
class ArticleAdmin(admin.ModelAdmin):
list_display = ('title', 'category')
Unfortunately, the list_display option is causing the columnar view to appear, but only some of the objects (40 out of 85) are now displaying in the listing. I cannot deduce why certain objects are showing over the others - their fields look like they are filled similarly. It's clearly not paginating, because when I tried it on an admin of another model, it showed only 2 objects out of about 70 objects.
What might be going on here?
[UPDATE] Article Model:
class Article(models.Model):
revision = models.ForeignKey('ArticleRevision', related_name="current_revision")
category = models.ForeignKey('meta.Category')
language = models.ForeignKey('meta.Language', default=get_default_language)
created = models.DateTimeField(auto_now_add=True, editable=False)
changed = models.DateTimeField(auto_now=True, editable=False)
title = models.CharField(max_length=256)
resources = models.ManyToManyField('oer.Resource', blank=True)
image = models.ManyToManyField('media.Image', blank=True)
views = models.IntegerField(editable=False, default=0)
license = models.ForeignKey('license.License', default=get_default_license)
slug = models.SlugField(max_length=256)
difficulty = models.PositiveIntegerField(editable=True, default=0)
published = models.NullBooleanField()
citation = models.CharField(max_length=1024, blank=True, null=True)
Before adding list_display:
After adding list_display:
[UPDATE] This behaviour occurs only when ForeignKey fields are included in list_display tuple. Any of them.
[UPDATE] Category model code:
class Category(models.Model):
title = models.CharField(max_length=256)
parent = models.ForeignKey('self')
project = models.NullBooleanField(default=False)
created = models.DateTimeField(auto_now_add=True, editable=False)
slug = models.SlugField(max_length=256, blank=True)
def __unicode__(self):
return self.title
This behavior is caused by a foreign key relation somewhere that is not declared as nullable, but nonetheless has a null value in the database. When you have a ManyToOne relationship in list_display, the change list class will always execute the query using select_related. (See the get_query_set method in django.contrib.admin.views.ChangeList).
select_related by default follows all foreign keys on each object, so any broken foreign key found by this query will cause data to drop out when the query is evaluated. This is not specific to the admin; you can interactively test it by comparing the results of Article.objects.all() to Article.objects.all().select_related().
There's no simple way to control which foreign keys the admin will look up - select_related takes some parameters, but the admin doesn't expose a way to pass them through. In theory you could write your own ChangeList class and override get_query_set, but I don't recommend that.
The real fix is to make sure your foreign key model fields accurately reflect the state of your database in their null settings. Personally, I'd probably do this by commenting out all FKs on Article other than Category, seeing if that helps, then turning them back on one by one until things start breaking. The problem doesn't have to be with a FK on an article itself; if a revision, language or category has a broken FK that will still cause the join to miss rows. Or if something they relate to has a broken FK, etc etc.
I want to sort a QuerySet of contacts by a related field. But I do not know how.
I tried it like this, but it does not work.
foundContacts.order_by("classification.kam")
Actually in a template I can access the kam value of a contact through contact.classification.kam since it is a OneToOne relationship.
The (simplified) models look like this:
class Classification(models.Model):
kam = models.ForeignKey(User)
contact = models.OneToOneField(Contact)
class Contact(models.Model):
title = models.ForeignKey(Title, blank=True, null=True)
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
It should be:
foundContacts.order_by("classification__kam")
Here is a link for the Django docs on making queries that span relationships: https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships
You can also see some examples in the order_by reference:
https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.order_by
as the documentation indicates, it should be used as in queries about related models
https://docs.djangoproject.com/en/3.0/ref/models/querysets/#order-by
foundContacts.order_by("classification__kam")
I've struggled a lot with this problem, this is how I solved it:
contact ordered by "kam" (Classification) field:
show_all_contact = Contact.objects.all().order_by(title__kam)
classification ordered by Users email (no sense in it, but only show how it works):
show_all_clasification = Classification.objects.all().order_by(kam__email)