Setting a Django ForeignKey to multiple models - django

I have a simple model called WebProfile that stores a webpage URL and its title. This model has a ForeignKey to a Student model, which allows me to store the student's bookmarks.
I would like to reuse this model to also store bookmarks saved by teachers. What is the best way to have the owner ForeignKey point to either a Student or Teacher?
Note: in my actual use case, the target model classes are conceptually very different and do not share any common fields other than the WebProfile links.
class Student(models.Model):
...
class Teacher(models.Model):
...
class WebProfile(models.Model):
title = models.CharField(max_length=50)
link = models.URLField()
owner = models.ForeignKey('Student', on_delete=models.CASCADE, related_name="bookmarks")

If Teacher and Student are related to the User model you could change the ForeignKey in WebProfile to be related to the User model instead.
From there you can then workout when you get a WebProfile object whether the user is a Student or Teacher.

I was able to solve the problem by using Generic Relations as described in Django documentation
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
class WebProfile(models.Model):
title = models.CharField(max_length=50)
link = models.URLField()
owner_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
owner_id = models.PositiveIntegerField()
owner = GenericForeignKey('owner_type', 'owner_id')

Related

django models hierarchy question: related attributes of a ManyToManyField

As a fresh coder, I seriously have problems to build my models relations.
Please check these two cases, How can I set current_reading_pages on my Scenario2?
from django.db import models
# Scenario1: Users can record their reading progress of a book.
class Book(models.Model):
name = models.CharField(max_length=128)
class User(models.Model):
current_reading_book = models.ForeignKey('Book', on_delete=models.CASCADE)
current_reading_page = models.IntegerField()
Result1: No problems about database, but Users can records their progress of only one book.
Other scenario, which I want to build:
from django.db import models
# Scenario2: Users can record their reading progress of multiple books.
class Book(models.Model):
name = models.CharField(max_length=128)
class User(models.Model):
current_reading_books = models.ManyToManyField('Book')
# current_reading_pages = ???
I want to save all progress of current books, for example,
User A is reading 3 books, book1 till page 100, book2 till page 10, book3 till page 0.
And I found 'through' parameter in django ManyToManyField,
My codes become like below but it does not work as I expected.
from django.db import models
# Scenario3: Using through parameter in ManyToManyField
class Book(models.Model):
name = models.CharField(max_length=128)
class User(models.Model):
current_reading_books = models.ManyToManyField('Book', through='ReadingBook')
class ReadingBook(models.Model):
book = models.ForeignKey('Book', on_delete=models.CASCADE)
current_reading_page = models.IntegerField()
ERRORS:
test_model.ReadingBook: (fields.E336) The model is used as an intermediate model by 'test_model.User.current_reading_books', but it does not have a foreign key to 'User' or 'Book'.
I think, that first scenario is easy to realize.
just add user attribute into the custom class UserBook
for example
class UserBooks(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
current_page = models.IntegerField(default=1)
if user wanna check his progress, in views.py you can just filter by books = UserBooks.objects.filter(user=request.user)

Django: How to add a manytomany field(from user to user itself) to the built in user model

example field that i want to add in built in User model
class bulit_in_user_model(models.Model):
relationships = models.ManyToManyField('self',on_delete=models.CASCADE)
how to do that
Read more about referencing self using ManyToManyField.symmetrical here
from django.db import models
class MyUser(models.Model):
...
friends = models.ManyToManyField("self", blank=True)
Monkey patching could achieve your goal,but it's better to follow the normal User model Customization though
Inherit from AbstractUser, and specify AUTH_USER_MODEL = 'myapp.MyUser in your settings.
class MyUser(AbstractUser):
friends = models.ManyToManyField("self", blank=True)

django admin how to manipulate OneToMany related objects(not just inline)

I have 2 models.
One has a foreign key to another.
Say:
class Organization(models.Model):
title = models.CharField(max_length=300)
class User(models.Model):
name = models.CharField(max_length=300)
organization = models.ForeignKey(Organization)
I want to show all users who work in current organization in organizationAdmin, like a list of change links.
It should be possible
to add new user
to select existing user(no related to current organization) and set his organization to current
No need to edit them inline
Just like permissions in userAdmin + adding and changing them
Is there any ready solution? Not to make forms by hands
You can do that with exclude:
class UserInline(admin.TabularInline):
model = User
exclude = ['name', 'other_fields']
Or you can use ManyToMany relation:
class User(models.Model):
name = models.CharField(max_length=300)
class Organization(model.Model):
title = models.CharField(max_length=300)
users = models.ManyToManyField(User)

Django: How to define a ForeignKey to User OR to another model?

I'm building a site for people doing maintenance tasks in properties. The user can have clients and can perform maintenance tasks both in his properties and in his client's properties. How can I define the ownership of the property to be User OR Client?
My models should be something like this:
class Client(models.Model):
name = models.Charfield(max_length=100)
user = models.ForeignKey(User)
class Property(models.Model):
name = models.Charfield(max_length=100)
owner = models.ForeignKey(User OR Client)
class MaintenanceTask(models.Model):
name = models.Charfield(max_length=100)
property = models.ForeignKey(Property)
Obvliously, owner = models.ForeignKey(User OR Client) is not correct. How can I solve this problem?
And the general question:
How can I define a ForeignKey to User OR to another model?
You can use Generic Relation and more precisely GenericForeignKey. You can have a look at GenericForeignKey in Django doc
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
class TaggedItem(models.Model):
content_type= models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey()
The solution is a GenericForeignKey, as the other answer pointed. However, I was missing an example to understand it.
In the following post there is a very good example and a way to use GenericForeignKey As Single Form Field:
http://adamalton.blogspot.com.es/2014/02/displaying-django-genericforeignkey-as.html

Get all objects defined by a Django ManyToManyField relationship

The site I'm building allows users to create "posts" and has a Twitter-like concept of followed users. For a given user, I'd like to show all of the posts from the users that they follow.
Here are my simplified models:
class User
# a standard django.contrib.auth user model
class UserProfile(models.Model):
# my AUTH_PROFILE_MODULE for django-profiles
user = models.ForeignKey(User, unique=True)
following = models.ManyToManyField('self', symmetrical=False, related_name="followed_by")
class Posts(models.Model):
user = models.ForeignKey(User)
post = models.TextField()
Question: How do you create a queryset of all Post objects from the Users that a given User is following?
I think I've made it more complicated by creating the "follow" relationship on UserProfile, which is not the model with the ForeignKey relationship with Posts.
UPDATE! Here's the answer:
Posts.objects.filter(user__userprofile__in=UserProfile.objects.get(user=your_user_object).following.all())
Posts.objects.filter(user__in=UserProfile.objects.get(user=your_user_object).following)