Reputation:
I'm trying to write a Django model, but as I read further and further in the docs, I find out that I have to take care about too many things and I'm getting really confused with all the considerations I have to bear in mind.
My most essential doubt is "When I define two classes, in which do I include the reference to the other when..."
"... and how do I create/manage these two classes when creating those objects".
I hope someone may explain it easier. I think that with these four things clear I may be able to write the model myself.
Upvotes: 1
Views: 92
Reputation: 4579
Django document is still a good place for you to start, and it is really comprehensive for both beginners and professionals. No other shortcut to master it except reading its document and playing with the example.
UserModel
stands for A
, UserProfile
stands for B
.
Suppose we have a UserModel
, and need one more table to keep the extra information, let's say UserProfile
. And we allow UserProfile
to be null. then we can use OneToOneField
to bind these two class.
from django.db import models
class UserModel(models.Model):
name = models.CharField('username', max_length=20)
class UserProfile(models.Model):
nickname = models.CharField('nick name', max_length=50, blank=True, null=True)
# blank tells the validator, this field could be blank, and null tells the db engine, this field could be null.
user = models.OneToOneField(UserModel, blank=True, null=True, on_delete=models.CASCADE)
u = UserModel.objects.get(pk=1)
nickname = u.userprofile.nickname # to access B from A, you can use the model name lowercase name for reference.
profile = UserModel.objects.get(pk=1)
username = profile.user.username # To access A from B, you can use the model name lowercase name for reference.
UserModel
stands for A
, UserProfile
stands for B
.
For the model definition, it is almost the same as case a). But we need to make sure B is coexistence with A, so we will need to remove Blank
and null
. And we must use post_save
hook to make suer B is also created with A is saved.
from django.db import models
from django.dispatch import receiver
from django.db.models.signals import post_save, pre_save
class UserModel(models.Model):
name = models.CharField('username', max_length=20)
class UserProfile(models.Model):
nickname = models.CharField('nick name', max_length=50)
user = models.OneToOneField(UserModel,on_delete=models.CASCADE)
@receiver(post_save, sender=UserModel)
def create_auth_token(sender, instance=None, created=False, **kwargs):
# This hook is automatically called when the UserModel is created, this is used to make suer UserProfile is also created when UserModel is created.
if created:
UserProfile.objects.create(user=instance)
The same as case a).
Author
stands for A
, Book
stands for B
.
For example, Author
is a model to save the book author information, and one author may write zero or many books, let's named it to Book
as model. (Suppose only allow one author for each book).
class Author(models.Model):
name = models.CharField('name of the author', max_length=20)
class Book(models.Model):
book_name = models.CharField('name of the book', max_length=50)
author = models.ForeignKey(Author, related_name='books')
# access B from A
author = Author.objects.get(pk=1)
books = author.books
# first book
book_name = books[0].book_name
# access A from B
book = Book.objects.get(pk=1)
author_name = book.author.name
If you allow one book has many authors, then we should use ManyToManyField
instead of ForeignKey
. The Book
model definition changed to this:
class BookAuthor(models.Model):
author = model.ForeignKey(Author)
book = model.ForeignKey(Book)
publish_at = model.DateTimeField(auto_add=True)
class Book(models.Model):
book_name = models.CharField('name of the book', max_length=50)
# through is used to tell django, we have defined another relationship table to bind Author and Book model.
authors = models.ManyToManyField(Author, through='BookAuthor')
author = Author.objects.get(pk=1)
first_book_name = author.book_set.order_by('publish_at')[0].book_name
book = Book.objects.get(pk=1)
author_names = [author.name for author in book.author_set.all()]
Place
stands for B
, Library
and Restaurant
stands for A
.
For example, we defined a generic class Place
, and Library
could be a place, same as Restaurant
.
class Place(models.Model):
address = models.CharField('address', max_length=100)
class Library(Place):
num_of_books = models.IntegerField('NO. of books in the library')
class Restaurant(Place):
restaurant_type = models.CharField('The type of the restaurant', max_length=10)
lib = Library.objects.get(pk=1)
lib.address # get the library address
lib.num_of_books # get the no. of books in this library
rest = Restaurant.objects.get(pk=1)
rest.address # get the restaurant address
rest.restaurant_type # get the restaurant type
For the above case, django will create a Place
table in db, because it is also a model, if you don't what it to be created, and treat it as Abstract
class as other programming language, you can redefined it as follow:
class Place(models.Model):
address = models.CharField('address', max_length=100)
class Meta:
abstract = True
Upvotes: 2