Django model for books - python

I want to define a class for books.
A book consists of several chapters.
A chapter consists of several sections.
A section consists of several subsections.
Is it okay to do it as follows?
class Book(models.Model):
pass
class Chapter(models.Model):
book = models.ForeignKey('Book', on_delete=models.CASCADE)
class Section(models.Model):
chapter = models.ForeignKey('Chapter', on_delete=models.CASCADE)
class SubSection(models.Model):
section = models.ForeignKey('Section', on_delete=models.CASCADE)
content = models.TextField()
Or is there a better way?

Yes, this is the standard way to do it, as it maps the corresponding SQL closely.
In Chapter you define book as a foreign key
Book class will automatically get a variable called chapter_set, which contains a list of chapter
This alone proves that you are doing it correctly. See related managers for more information
Same for subchapter

Related

the use of the underscore : q.choice_set.all()

I am working on the Django
Writing your first Django app, part 2
In the section "2.4.4 Playing with the API".
If someone could explain to me how does the underscore works in this code q.choice_set.all()
It's pretty simple. Let's consider these two models:
class Author(models.Model):
name = models.Charfield(max_lenght=100)
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
name = models.Charfield(max_lenght=100)
Explain:
We have some Authors that each author has some books.
but what if we want to get all books of a specific author?
let's assume we want all books that written by Sara:
my_author = Author.objects.get(name='Sara')
Here is the magic! Django will automatically generate the backward relation for this object called book_set which contains all books writen by Sara.
The naming rule is straightforward, <related_model_name>_set.
So, you can get those books by writing this line:
sara_books = my_author.book_set.all()
It's nice, isn't it ? wait, it could be nicer!
book_set is not a good name for me, i want a more human readable name!
you can easily change this by adding related_name to the author field of Book model:
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='her_books') # you can name it anything you want
name = models.Charfield(max_lenght=100)
then, you can get same books like this:
sara_books = my_author.her_books.all()
it's now more human readable :) Hope you get it.

Django: Use other model classes as choices for a field

I'm writing a Django app that includes a poll section, and I want to offer the ability to create different types of questions. So, I have these models for the rating part
# Do I really need this class?
class BaseRating(models.Model):
class Meta:
abstract = True
# For questions like: "Rate your experience with XXXXX"
class FiveStarRating(BaseRating):
rating = models.PositiveSmallIntegerField(null=True, blank=True, validators=[MaxValueValidator(5)])
# For questions like: "Would you recommend XXXXX"?
class YesNoRating(BaseRating):
rating = models.BooleanField()
I now want to create a new question, and I want to specify the rating system for it:
If I create the question "How would you rate xxxxx", I'd use FiveStarRating model
If I create the question "Are you satisfied with xxxx", I'd use YesNoRating
So, how should I design the question model?
class Question(models.Model):
title = models.CharField(max_length=255)
# rating??
# I can't create a foreignkey field to the base class...
EDIT: I am finally using django-dynamic-forms, but I consider the first response as an acceptable one too
From what i can see, you're not using the BaseRating model for anything, so it's safe to remove it.
As for the questions, in my case, i'll create two new models that have foreign keys to both FiveStarRating and YesNoRating so the data can be exclusive from each other. so you'll end up having two models like this.
class FiveStarQuestion(models.Model):
title = models.CharField(max_length=255)
rating = fields.ForeignKey(FiveStarRating)
class YesNoQuestion(models.Model):
title = models.CharField(max_length=255)
rating = fields.ForeignKey(YesNoRating)
but if you want to share the titles among the two questions (I would second this approach because there might be two questions with the same title)
Example:
How would you rate Stackoverflow
and
How Satisfied are you with Stackoverflow
It makes sense to have only one title called Stackoverflow and use that Reference as a foreignkey in our tables. So in this case, you can keep the Question model and have ForiegnKey fields that point to it.
class Question(models.Model):
title = models.CharField(max_length=255)
The create the two models as follows:
class FiveStarQuestion(models.Model):
title = models.ForeignKey(Question)
rating = fields.ForeignKey(FiveStarRating)
class YesNoQuestion(models.Model):
title = models.ForeignKey(Question)
rating = fields.ForeignKey(YesNoRating)

Model redundant django tables?

I am working to figure out the model for a Django project: an app to track Books.
Among other fields, every Book has either/both a Printer and a Publisher, which are basically identical. So, here's how it stands:
class Book(models.Model):
title = models.CharField(max_length=100)
printer = models.ForeignKey('Printer')
publisher = models.ForeignKey('Publisher')
class Printer(models.Model):
name = models.CharField(max_length=100)
location = models.CharField(max_length=100)
class Publisher(models.Model):
name = models.CharField(max_length=100)
location = models.CharField(max_length=100)
It seems to me this is bad database form: it's not DRY. In addition, quite often, a Book might be printed by a firm which publishes the same or another book: in other words, the tables can overlap. So, the two models Printer and Publisher should really be combined, while they need to remain distinct in the admin.
My question: how best to do this? Should I create another model, Firm, and create one-to-one relationships between it and Printer/Publisher?
The Django way to handle that is to create an Abstract Base Model. This is the DRY way to create your models. Here is the code:
class BaseModel(models.Model):
name = models.CharField(max_length=100)
location = models.CharField(max_length=100)
class Meta:
abstract = True
class Printer(BaseModel):
pass
class Publisher(BaseModel):
pass
This will allow you to specify redundant fields only once. Also, if you need to add any extra fields to one model, just add them instead of using pass.

How do I make a class a sub-group of another class?

from django.db import models
class products(models.Model): #Table name, has to wrap models.Model to get the functionality of Django.
name = models.CharField(max_length=200, unique=True) #Like a VARCHAR field
description = models.TextField() #Like a TEXT field
price = models.IntegerField()
def __unicode__(self): #Tell it to return as a unicode string (The name of the to-do item) rather than just Object.
return self.name
class categories(models.Model):
I'm a python newbie and I'm trying to create an e-commerce store. As you can see above, I've created the products class, but in the Categories class, I need to include all the products I create come under a certain category. I have no clue how to do this.
Sounds like you just want a ForeignKey from Product to Category.
Take a look at Many to Many
I think a Product can belong to Many categories so it should have a ManyToMany relationship to the Category model.

Django: Referencing a manytomany field that has been defined in another model

I'm trying to work out how to calculate the number of books written by an author. The book model sets up the manytomany field with the author model. I have no idea how even google something like this which I thought would be very simple to do but I don't even know how to start.
Here's the stripped down code:
class Author(models.Model):
first_name = models.CharField()
last_name = models.CharField()
def books(self):
"""Return a list of comma separated list of books by the author"""
pass
class Book(models.Model):
title = models.CharField()
authors = models.ManyToManyField(Author)
Maybe I could do a filter query to get books by a particular author but it doesn't seem like the django way to do it? I'm also not sure how to pass the filter function a python object rather than text.
Thanks
when you define a foreignkey or manytomany field, django sets up a reverse relation for you, which in your case is book_set. so something like:
def books(self):
books = self.book_set.all()
return ', '.join([book.title for book in books])
see related objects in the docs

Categories

Resources