joining two separate app models django - python

okay so I have just a test blog system to practice my django skills. I have 2 apps one called article on called likes here they are:
article models:
from django.db import models
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length = 200)
description = models.TextField()
pub_date = models.DateTimeField('Date Published',auto_now = True)
def __str__(self):
return self.title
and here is the likes models:
from django.db import models
from apps.article.models import Article
# Create your models here.
class Like(models.Model):
article_id = models.ForeignKey(Article)
likes = models.IntegerField(default = 0)
def __str__(self):
return self.Likes
now im rendering out the pages but I want to display how many likes each article has. How can I join both these models. Change the objects.all method to also grab the likes from the Like model

You can use FOO_set, docs about this here, basically you do this to get all likes:
article.likes_set.all()
and you can just use count() to get number

First you might want to rename article_id to article since when you use the attribute, you will actually get the article and not just the id.
In this case you seem to have a many-to-one relationship between Like and Article. That means you need to refer to the likes as 'like_set'. So if you happen to have the object stored in article, you can get all the likes with article.like_set.all() and the count with article.like_set.count().
Reference: https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_one/
If you're interested in fetching this ahead of time you can use prefetch_related to save the additional database calls:
https://docs.djangoproject.com/en/1.4/ref/models/querysets/#prefetch-related
It would like something like this:
articles = Article.objects.all().prefetch_related('like_set')

Related

How can I construct a Django model whose fields are dependent upon another model's fields

I currently am making a simple newspaper Django application, and am working on the Articles model which looks as follows:
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
#date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
get_user_model(),
on_delete=models.CASCADE,
)
topic = models.CharField(max_length=255)
score_choices = [(-5,'-5'), (-4, '-4'), (-3,'-3'), (-2, '-2'), (-1,'-1'),
(0,'0'),(1,'1'), (2,'2'), (3,'3'), (4,'4'), (5,'5')]
score = models.IntegerField(choices=score_choices, default=0)
I am attempting to create another model that looks something like this:
class Topic(models.Model):
topic_name = models.CharField(max_length=255)
average_score =
Within the topic model, what I would like to do is somehow query all the Articles that have topic_name as their topic, and then return a list of scores that have been entered for Articles with that topic.
I'm currently pretty lost on this issue and I'm not even sure anymore if using the Django models is the best route. I've been reading through the Django Documentation as well as Third-Party books for a while but I can't find any reference here.
To summarize, I have two models: Article and Topic. Article has a field called 'topic' as well and I would like to create a field for my Topic class that is a function of the score field for all Article objects whose 'topic' field agrees with that of my separate Topic class. I apologize if this is confusing and I don't know all the terminology as I am trying to teach myself.
I have read through Django Documentation's pages on Models, Queries, Many-to-Many Relationships and various other properties. I still am unsure as to the solution.
Something like the following would work, using aggregation:
from django.db.models.aggregates import Avg
class Topic(models.Model):
topic_name = models.CharField(max_length=255)
def average_score(self):
return Article.objects.filter(topic=self.topic_name).aggregate(avg=Avg('score')).get('avg')

Django Model for players

I'm working on a django website that can allow me to display some information about players and matches for a game.
There will be multiple matches and multiple players. The problem I'm having is that I'm not sure if this is what I should be doing:
class Player(models.Model):
player_id = models.IntegerField(default=0)
matches = models.ManyToMany(Match)
class Matches(models.Model):
match_id = models.IntegerField(default=0)
players = models.ManyToMany(Player)
or I should be doing:
class Player(models.Model):
player_id = models.IntegerField(default=0)
class Matches(models.Model):
match_id = models.IntegerField(default=0)
players = models.ManyToMany(Player)
A player can be in multiple matches, and a match can contain multiple players, which is why I'm a bit confused.
You should define the relation in only one of the models, so the second example is the correct one.
In the first one (you have a typo there that should be Matches by the way) you are creating two separate M2M relations between the two models that you don't want to have in your case.
On an unrelated note, you don't need to to have player_id and match_id columns as Django will automatically create id columns for your models.
The following code will solve your model structure for your project.
class TimeStamped(models.Model):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Player(TimeStamped):
name = models.CharField(max_length=50)
extra_info = models.TextField()
matches = models.ManyToManyField('Match')
def __unicode__(self):
return self.name
class Match(TimeStamped):
title = models.CharField(max_length=50)
extra_info = models.TextField()
class Meta:
verbose_name_plural = 'Matches'
def __unicode__(self):
return self.title
The TimeStamped model is a good idea for every project you build. If you are using Python 3 then replace __unicode__ with __str__. Don't use plural in model names. Use verbose_name_plural, that is the convention in my opinion. It seems like you might have a problem with query players from a Match instance. Read the documentation for a detailed info on that. If you can't find that post here. Since this post is not about the querysets so I skipped that part.
Absolutely right for this scenario, ManyToMany relation is required to setup in DB.
id is the default field in Django model if you are not providing any other primary key. And ID is incremental. As per my opinion, Following models are enough to satisfy your scenario.
class Player(models.Model):
name = models.CharField(max_length=255)
class Match(modles.Model):
player = models.ManyToMany(Player, related_name="matches")
According to above model sample, you can accessing matches of one player and players who played a single match.
match = Match.objects.get(id=1)
print match.player.all() # It will print all players for match of id 1
player = Player.objects.get(id=1)
print player.matches
You definetelly have to use ManyToManyField, you can add it only to one model:
class Player(models.Model):
player_id = models.IntegerField(default=0)
matches = models.ManyToMany(Match)
class Matches(models.Model):
match_id = models.IntegerField(default=0)
After declaring models, Player objects have access to their related Matches objects in next way:
player.matches.all()
Matches objects have access to their related Player objects in next way:
match.player_set.all()
See article Many-to-many relationships, Django documentation, there are plenty of use full information of how to dial with ManyToMany relations in Django.

django: sort by foreignkey in model manager

class Author(models.Model):
name = models.CharField()
class Article(models.Model):
author = models.ForeignKey(Author)
created_at = models.DateTimeField(auto_now_add=True)
In a custom model manager for Author, how could one proceed to sort all the authors by the creation date of their most recent Article? Is this possible without using raw sql or for loops?
To show research effort and clarify the question, here's the (pseudo)code of how I'd do that in raw Python. It is untested and would probably not work because of the if not article.author in sorted_authors condition.
from django.db import models
from .models import Article
class AuthorsManager(models.Manager):
def get_sorted_authors(self):
articles = Article.objects.all().order_by('creation_date')
sorted_authors = []
for article in articles:
# not sure if this if condition would work
if not article.author in sorted_authors:
sorted_authors.append(article.author)
return sorted_authors
Another possible solution: add a last_article_datetime field to Author and sort by that. Widely more efficient and concise. Question still standing for any other use-case though.
Maybe like this:
Author.objects.annotate(lc=Max('article__created_at')).order_by('lc')

Listing foreign keys related to a proxy model in django admin

My models.py looks like this :
class Author(models.Model):
name = models.CharField()
class DraftBooks(models.Model):
title = models.CharField()
author = models.ForeignKey(Author)
status_choices = ((1,Draft),(2,Published))
status = models.SmallIntegerField(choices=status_choices)
class PubBooks(DraftBooks):
class meta:
proxy = True
verbose name = 'Published Books'
I am using a proxy model since I want a different change list view for books in draft state and books which have been published.To achieve this,my admin.py looks like this :
class AuthorAdmin(admin.ModelAdmin):
pass
admin.site.register(Author, AuthorAdmin)
class DraftBooksAdmin(admin.ModelAdmin):
list_display = ('title','author','status')
def queryset(self):
return DraftBooks.objects.filter(status='1')
admin.site.register(DraftBooks, DraftBooksAdmin)
class PubBooksAdmin(admin.ModelAdmin):
list_display = ('title','author','status')
def queryset(self):
return PubBooks.objects.filter(status='2')
admin.site.register(PubBooks, PubBooksAdmin)
This setup works perfectly fine.In my admin,now I have 3 change list views,one which shows a list of all authors,one which shows book which are in a draft state and finally one which shows the list of books which are in a published state.
I now need to add a hyperlink to every item (Author) in the authors' list overview that links to a view showing all books of the specific authors.For Example:
J.K. Rowling (books)
J.R.R. Tolkien (books)
where books is a hyperlink to a site showing all books of a particular author.
Now I am completely clueless as to how to do this.Django Xadmin has a plugin which provides just this feature.This Stackoverflow question also provides answer to this problem.But the problem is that they do not work in proxy models with the custom filters that I have.When I try to get the list of books by an author,I get only the books which are in Draft state.I would ideally want all the books,Draft and Published by an author.How do i achieve this ?

Django inheritance

Please have a look:
class Categorie(models.Model):
id = models.AutoField('id', primary_key=True)
title = models.CharField('title', max_length=800)
articles = models.ManyToManyField(Article)
class Article(models.Model):
id = models.AutoField('id', primary_key=True)
title = models.CharField('title', max_length=800)
slug = models.SlugField()
indexPosition = models.IntegerField('indexPosition', unique=True)
class CookRecette(Article):
ingredient = models.CharField('ingredient', max_length=100)
class NewsPaper(Article):
txt = models.CharField('ingredient', max_length=100)
So I created "CookRecette" and "NewsPaper" as "Article".
I Also create a "Categorie" class who link to (manyToMany) "Article".
But in the admin interface, I can't link from "Categorie" to an "CookRecette"or "NewsPaper".
Same from the code.
Any help ?
Cheers,
Martin Magakian
PS: I'm so sorry but actually this code is correct! So everything is working fine, I can see my "CookRecette"or "NewsPaper" from "Categorie"
I'll start by saying that you don't need to define the 'id' field, if you don't define it then Django will add it automatically.
Secondly, the CookRecette and NewsPaper objects are not linked to the Categorie object by any means (ForeignKey, OneToOne, OneToMany, ManyToMany) so they wouldn't be able to be accessed that way anyway.
After you have linked the models together in whichever way you wish, you might want to have a look at http://docs.djangoproject.com/en/1.2/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin which will show you how to quickly edit related objects in the Djano admin console.
NewsPaper has part of it as Article object. If you will create new NewsPaper object, you will see a new object in articles. So in admin interface, when managing Categories, you will be able to select any article, and some of them are NewsPaper.
You can add news paper to a category like this:
category = Categorie(title='Abc')
category.save()
news_paper = NewsPaper(slug='Something new', indexPosition=1, txt='...')
news_paper.save()
category.articles.add(news_paper)
You can retrieve news papers from specific category like this:
specific_category = Categorie.objects.get(title='Abc')
NewsPaper.objects.filter(categorie_set=specific_category)

Categories

Resources