which is the better design of database for article Like function? - django

I'm using Django to develop a news website.Now I'm developing the like function in news detail page, this function is like that at the bottom of the news, there is a like button, once you click it the amount of like will add 1.
Now I have 2 choices to design the table of the database in django we call it model.I'm not sure which design is better.
First:just use one News model
class News(models.Model):
...code..
is_up = models.BooleanField(default=True)
up_count = models.IntegerField(default=0)
Once is_up ,up_count will add 1.
Sceond:use 2 models,News model and a separate Like model
class News(models.Model):
...code..
up_count = models.IntegerField(default=0)
class Like(models.Model):
"""
点赞表
"""
nid = models.AutoField(primary_key=True)
user = models.ForeignKey('UserInfo', null=True, on_delete=models.CASCADE)
news = models.ForeignKey("News", null=True, on_delete=models.CASCADE)
is_up = models.BooleanField(default=True)
class Meta:
unique_together = [
('news', 'user'),
]
Any friend can tell which design is better ?

If you use the second one, you can know more information, depending on whether you need the data, or you can use ManyToManyField like this:
class News(models.Model):
...code..
likes = models.ManyToManyField('UserInfo')
This will record who liked this news.

Related

django unique_for atributes in models

In the past, I think there was a model atrtibute named unique_for to define a foreignKey but I can't find it anymore.
Suppose a model named Recommendation. A User can recommend many websites but only one by domain. So, I wanted to set a unique_for('user', 'recommendation.domain') or something like like this.
What's the current way to do it ?
Recommendation Model:
class Recommendation(models.Model):
is_recommended = models.BooleanField(default=True)
what = models.ForeignKey('Website', on_delete=models.CASCADE)
who = models.OneToOneField(User, on_delete=models.CASCADE)
title = models.CharField(max_length=255)
why = models.CharField(max_length=255, null=True, blank=True)
when = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ["-when"]
User Model is the Django built in.
Thanks
I've found my answser.
The attribute is unique_together and not unique_for

Django : Displaying ManyToManyField in admin page as a Table

I have the following two models.
class Question(models.Model):
id = models.AutoField(primary_key=True)
question_body = models.TextField(blank=True)
question_response = models.TextField(blank=True)
def __str__(self):
return self.question_body
class SIGRound(models.Model):
sig = models.CharField(max_length=9, choices=SIG_CHOICES)
round_number = models.IntegerField(default=1)
round_description = models.CharField(max_length=500)
questions = models.ManyToManyField(Question)
I want to use the SIGRound from the admin page and since it is a many to many field, many answers on StackOverflow suggested to use filter_horizontal or inline
So I implemented both and checked out how they looked, filter_horizontal does not give me what I want and with inline it looks like this:
This is the code I am currently using:
class QuestionInline(admin.TabularInline):
model = SIGRound.questions.through
#admin.register(SIGRound)
class SIGRoundAdmin(admin.ModelAdmin):
inlines=[QuestionInline]
But I want to display this field as a table, similar to list_display in the normal admin page, how would I go about doing this?

Django Query: How to find all posts from people you follow

I'm currently building a website with the Django Framework. I want on the homepage of my website to display all posts made by people the user is following. Here are the classes for Profile, Story and Follow:
class Profile(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=30, null=True)
last_name = models.CharField(max_length=30, null=True)
class Follow(models.Model):
following = models.ForeignKey('Profile', on_delete=models.CASCADE, related_name="following")
follower = models.ForeignKey('Profile', on_delete=models.CASCADE, related_name="follower")
follow_time = models.DateTimeField(auto_now=True)
class Story(models.Model):
author = models.ForeignKey('accounts.Profile', on_delete=models.CASCADE, related_name="author")
title = models.CharField(max_length=50)
content = models.TextField(max_length=10000)
As you can see Follow uses two Foreign Keys to represent the following and the follower. Is there a way to query all stories from people the user is following?
I really don't know what to filter. Or is this maybe a job for aggregation? If someone could help me, that would be awesome!
following_feed = Story.object.filter(???).order_by('-creation_date')
One can use double underscores (__) to look "through" relations (like ForeignKeys, etc.).
So here we can filter like:
Story.objects.filter(
author__following__follower=my_profile
)
So by using author we obtain a reference to the Profile of the author, then with following we look at the Follow model and then finally with follower we again obtain a reference to Profile(s): the profile(s) of the follower(s).
my_profile of course need to be substituted with a Profile object (the profile of the person that is a follower of the authors of the Storys you wish to obtain).
This will generate a query like:
SELECT s.*
FROM story AS s
JOIN follow AS f ON f.following_id = s.author_id
WHERE f.follower_id = 123
where 123 is the id of the my_profile.
If a person is following another person multiple times (here this can happen since you do not enforce that the follower, following tuples are unique in the Follow model), then the corresponding Storys will be yielded multiple times.
It is therefore probably better to add a unique_together constraint in the Follow model:
class Follow(models.Model):
following = models.ForeignKey(
'Profile',
on_delete=models.CASCADE,
related_name="following"
)
follower = models.ForeignKey(
'Profile',
on_delete=models.CASCADE,
related_name="follower"
)
follow_time = models.DateTimeField(auto_now=True)
class Meta:
unique_together = (('following', 'follower'), )
It might also be worth to see the Follow model as the through model of a ManyToManyField [Django-doc].
Note that I haven't tested the code I am posting so tell me if something is missing.
First, you need to get all the Profiles that your users follow. Then you have to get the Stories that they have.
followed_people = Follow.objects.filter(follower=current_user).values('following')
stories = Story.objects.filter(author__in=followed_people)

Add new rows to related model on creation of parent model in Admin

I have models for adding products. The name of the products are in several languages, so I made a on-to-many raltion with a 'Name'-model.
This is my models
class Product(models.Model):
active = models.BooleanField()
class ProductName(models.Model):
productName = models.CharField(max_length=250)
product = models.ForeignKey('Product', on_delete=models.CASCADE)
language = models.ForeignKey('Language', on_delete=models.CASCADE)
def __str__(self):
return self.productName
class Language(models.Model):
language = models.CharField(max_length=55)
languageAbbreviation = models.CharField(max_length=10)
def __str__(self):
return self.language
Now in the admin page of mysite, I want to add product names on creation of a product.
I tried some misarable attempt with some thing I found about 'admin.TabularInline'. But I think that is wrong because nothing is working with that.
Any suggestion about how to solve this is much appreciated!
A model admin like this:
class ProductAdmin(admin.ModelAdmin):
class ProductNameInline(admin.TabularInline):
model = ProductNameInline
fields = ['productName', 'language']
model = Product
inlines = [ProductNameInline]
should provide you with a page that allows you set the name(s) of a product.
Make sure all the necessary static files for the javascript are available.

Django composite unique on multiple model fields

Let us say I have a model for social network posts, users and likes:
class Post(models.Model):
submitter = models.ForeignKey(User, null=False, default=None)
content = models.CharField()
date = models.DateField()
with_likes = PostLikeCountManager()
objects = models.Manager()
class Like(models.Model):
user = models.ForeignKey(User)
post = models.ForeignKey(Post)
time = models.DateTimeField(auto_now_add=True)
It would be helpful to think of Post model as representing a Facebook post. Now, I would like to limit one like per post per user. How do I achieve that? One way would be to create a composite primary key on (user, post) attributes of Like class. I don't know how to achieve that in Django. The other would be to use unique=True on two attributes simultaneously. Is that possible?
Thanks.
Yes, use unique_together:
class Like(models.Model):
user = models.ForeignKey(User)
post = models.ForeignKey(Post)
time = models.DateTimeField(auto_now_add=True)
class Meta:
unique_together = ('user', 'post')
unique_together will be deprecated in the future version, instead you could apply UniqueConstraint. This and this link gives example code.
class Like(models.Model):
user = models.ForeignKey(User)
post = models.ForeignKey(Post)
time = models.DateTimeField(auto_now_add=True)
class Meta:
constraints = [
models.UniqueConstraint(fields=['user', 'post'], name='unique_user_post'),
]