Python Django models basics - python

I am learning django and trying to create a simple Question-Answer app where users can also like the questions and/or answers. Now what I want to do is track who liked a particular question/answer so I created a separate model for tracking this as follows:
class Votes(models.Model):
answer_id = models.ForeignKey(Answers, related_name='likes_answers', null=True, default=None, db_column='answer_id')
question_id = models.ForeignKey(Questions, related_name='likes_questions', null=True, default=None, db_column='question_id')
likes_count = models.IntegerField(blank=True, default=0)
liked_by = models.ForeignKey(User, related_name='like_user', null=True, default=None, on_delete=models.CASCADE)
Now the problem with this approach is that everytime a question or an answer is liked there will be an entry to this model which will create multiple entries of same question_id or answer_id with different users. Although the users are different, but a lot of answer_ids and question_ids are getting repeated...Is that right approach or can I make it better?

I guess a better approach would be using many-to-many fields: users are able to like multiple questions/answers, and questions/answers may be liked by multiple users.
Assuming your Answer has a foreign key to a particular question, the models may look like this:
class Question(models.Model):
# .. other attributes
liked_by = models.ManyToManyField(User, related_name = 'liked_question')
class Answer(models.Model):
question = models.ForeignKey(Question)
# .. other attributes
liked_by = models.ManyToManyField(User, related_name = 'liked_answer')
To get all users that liked the answer, you use
answer_object.liked_by.all()
For the (often-used) likes count, you would simply use
answer_object.liked_by.count()
Many-to-many fields work the other way around too, so to determine likes by a user, you may use (thanks to the related name)
user_object.liked_question_set.all()
user_object.liked_answer_set.all()

It's not a python, django question, it's fit an RDBMS design question.
But to answer your question,
If you want to check the duplicate from voting by user then it's right approach.
Other approach is update the voting post id to the user table. It's of course bad approach.

Related

How do I filter possible field values in django admin or at model level for fields linked through nested ForeignKey?

I have the two following models:
class Question(models.Model):
question_content = models.TextField(max_length=500)
related to:
class PossibleAnswer(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
answer = models.CharField(max_length=120)
I would like to have a tree structure for a questionnaire, in which the option to go from one question or another might depend on the answer to the previous question. So I wanted to create another model as follows:
class Relation(models.Model):
child = models.ForeignKey(Question, on_delete=models.CASCADE, related_name="child")
parent = models.ForeignKey(Question, on_delete=models.CASCADE, related_name="parent")
parent_answer = models.ForeignKey(PossibleAnswer, on_delete=models.CASCADE, related_name="parent_answer")
Now the issue I have, is that in the django admin, when selecting through parent_answer, it gives me the possibility to select any answer. That is, not only the ones that are linked to the selected parent question (via a foreign key).
I believe that the admin does not do dynamic filtering, but I would at least like the possibility to select on parent_answer is filtered once the parent question has been selected and the record saved. Or that this would somehow be enforced at the model level.
Is this possible?
Any help highly appreciated!

How do I create a 'couple' relationship in Django?

I've got a model called Couple. Couple describes the relationship between two Auth.User records.
class Couple(models.Model):
created = models.DateTimeField(auto_now_add=True)
partner_one = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name='partner_one')
partner_two = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, related_name='partner_two')
I'm having trouble referencing the partner in a reliable from their user model because now I need to know which is partner one, partner two. This is obviously not an elegant solution. Is there a better way to achieve what I'm trying to do here?

Django. Should I use ForeignKey or Addtional Cross Table for one to many relation?

I'm aware of this question was asked before, but that question doesn't have concise answer for my problem. I'm bit confused after seeing two examples in order to impelement OneToManyRelation.
In my example:
class Product(BaseModel):
name = models.CharField(max_length=255)
class Advantages(BaseModel):
title = models.CharField(max_length=255)
product = models.ForeignKey(Product, CASCADE)
Different products can have many advantages linked to it, so I'm using ForeignKey for this, but here I saw that it is also possible to use cross table relation in order to implement OneToManyRelation
categories & sub categories with many to many relationship
class ProductAdvantage(BaseModel):
title = models.CharField(max_length=255)
product = models.ForeignKey(Product, CASCADE)
Which one best practice for the OneToManyRelation? One product can have many advantages
Thank you for the answer

Creating A Relationship Between Two User Models

Im building a website which will have teachers and students. Im using the default Django User models and originally ignored Teachers and treated all my Users as Students. Today I began trying to separate my users into Teachers and Students and am having a lot of difficulty. Im obviously missing some fundamental knowledge and have read a lot online but am going around in circles.
A teacher can have many students and a student can have one teacher.
First I thought Id need separate Student and Teacher models. So everyone now is a User, and I will attach either a Student or Teacher model to each (is this sloppy?).
Now for the relationship. I tried creating a relationship between teachers and students within their own models, but it didnt work so I figured id need a separate TeacherStudentRelationship class to hold the relationships.
This is my implementation so far:
class Student(models.Model):
student = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return f'{self.student.username}'
class Teacher(models.Model):
teacher= models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return f'{self.teacher.username}'
class TeacherStudentRelationship(models.Model):
student = models.ForeignKey(User, on_delete=models.CASCADE)
teacher = models.OneToOneField(User, on_delete=models.CASCADE)
This doesnt throw any errors, though in Django Admin I can create multiple instances of TeacherStudentRelationship and assign a student to a teacher in multiple instances (should only be able to assign a student to a teacher once). I can also only assign a single student to a single teacher within one instance even though the relationship is one-to-many.
I also have a problem with my implementation. I have a signal fire every time a user is created which generates a Student model and links it with the User. This is fine when I have students enrolling on my site, though it means my Admin also needs a Student model (or else it throws errors). I also planned on creating Teachers in the Django Admin panel, but this will cause issues there too as they will need Student models. How would you implement this?
Thank you.
Instead of having a separate relationship like this, you can have a ManyToMany Relation in your teacher model. Like this:
class Student(models.Model):
student = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return f'{self.student.username}'
class Teacher(models.Model):
teacher= models.OneToOneField(User, on_delete=models.CASCADE)
students = models.ManyToManyField(Student)
In that way, it won't need to create new student when you are create a Teacher instance or vice versa.
Update
From comments, unfortunately you can't remove signals unless you use custom User model in django. You can try like this:
CHOICES = (('student', "Student"), ('teacher', "Teacher"))
class User(AbstractUser):
user_type = models.CharField(choices=CHOICES, max_length=255)
has_teacher = models.ForeignKey('self', null=True, default=None)
REQUIRED_FIELDS = ['user_type', 'email']
Then, you can define what kind of user it is during the User creating process, hence you do not need the signals. Also, you can store auth data of student and teacher in same model.

Creating a model related to an arbitrary number of other models

I deleted my previous question, since it was terribly worded and my non-working examples were just confusing.
I have a series of models, such as Vehicle, Computer, Chair, and whatnot. My goal is to be able to attach an arbitrary number of images to each of them. That's my question: what's the best design pattern to achieve this?
What I've tried so far is to create an abstract model, AttachedImage. I then inherit from this model, and create more specific models, like VehicleImage, ComputerImage, or ChairImage. But this doesn't feel like the right way to pursue this.
As I mentioned in the comment on the deleted question, the correct way to do this would be to use generic relations.
Make your AttachedImage model concrete, but add content_type and object_id fields and the content_object GenericForeignKey. That content_object field can now point to an instance of any model.
To make the reverse relationships easier, you can add GenericRelation accessors to your Vehicle, Computer and Chair models.
Thanks to Daniel Roseman's, I found out about generic relationships. You can find a great overview and tutorial about them here. There are basically two ways to achieve this.
The first one is using generic relationships as explained in the tutorial I linked. This system is very versatile and powerful, but in my case, this would add an additional layer of complexity that quite frankly I don't need.
If you're a newbie with Django like I am, you can consider a much more straightforward, but less 'systematic' pattern, also detailed in that tutorial I linked: simply add a ForeignKey field for each one of the objects you want your main model to be related to. Following the example I used in my question:
class AttachedImage(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
author = models.ForeignKey(User, on_delete=models.CASCADE)
image = models.ImageField(upload_to=image_path) # TO FIX: aƱadir la ruta
is_default = models.BooleanField(default=False)
To this, you just add fields for the relationships you will need, such as:
parent_vehicle = models.ForeignKey(Vehicle, on_delete=models.CASCADE, null=True)
parent_computer = models.ForeignKey(Computer, on_delete=models.CASCADE, null=True)
parent_chair = models.ForeignKey(Chair, on_delete=models.CASCADE, null=True)
And just use them as you regularly would. The downside is ending up with all those extra fields you don't really need, but being NULLable, they won't take up much space. The other downside is that doing this with a big number of models is probably overkill, in which case you should really use the first solution.
If you don't want to use the GenericForeignKey, you can implement your own polymorphic models, with multiple table inheritance. Following are the pseudo-models for the same:
class Attachable(models.Model):
pass
class Image(models.Model):
attachable = models.ForeignKey(Attachable, related_name='images')
class Video(models.Model):
attachable = models.ForeignKey(Attachable, related_name='videos')
class Vehicle(Attachable):
vehicle attrs...
class Computer(Attachable):
computer attrs...
class Chair(Attachable):
chair attrs...
For later optimizations, Attachable can also have an attribute which describes its subtype.

Categories