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.
Related
I'm making a movie app in Django. I have a model named Movie with its usual properties. I want to create another model named Cast where I'll create different actors. For a given movie, I want to be able to link different actors and also the actors shouldn't be removed when a movie is deleted. I tried using ForeignKey for the Cast at the actors field in Movie model. Thus it looked like this:
class MovieCast(models.Model):
"""
Model for the actors in a movie
"""
actor_name = models.CharField(max_length=100)
class Movie(models.Model):
"""
Base class for the properties our movie will have
"""
**other items**
cast = models.ForeignKey(MovieCast, on_delete=models.PROTECT)
What the problem is that the models do show up in admin site and I am able to add an actor to the MovieCast model, but in the cast field of the Movie model, I can't add more than one actors.
You work with a ManyToManyField [Django-doc] to represent relations where a movie can have multiple MovieCasts and a MovieCast can belong to multiple Movies.
For example:
class MovieCast(models.Model):
actor_name = models.CharField(max_length=100)
class Movie(models.Model):
name = models.CharField(max_length=128)
cast = models.ManyToManyField(
MovieCast,
related_name='movies'
)
We can then construct for example two movies and two MovieCast objects:
titanic = Movie.objects.create(name='Titanic')
laborday = Movie.objects.create(name='Labor Day')
leonardo = MovieCast.objects.create(actor_name='Leonardo DiCaprio')
kate = MovieCast.objects.create(actor_name='Kate Winslet')
titanic.cast.add(leonardo, kate)
laborday.cast.add(kate)
For more information, see the many-to-many relationships section of the documentation.
I have the following Django model to store sparse product data in a relational database. I apologize myself for any wrong relationship in the code below (ForeignKey and/or ManyToMany might be wrongly placed, I am just playing around with Django for now).
class ProdCategory(models.Model):
category = models.CharField(max_length=32, primary_key=True)
class ProdFields(models.Model):
categoryid = models.ForeignKey(ProdCategory)
field = models.CharField(max_length=32)
class Product(models.Model):
name = models.CharField(max_length=20)
stock = models.IntegerField()
price = models.FloatField()
class ProdData(models.Model):
prodid = models.ManyToManyField(Product)
fieldid = models.ManyToManyField(ProdFields)
value = models.CharField(max_length=128)
The idea is to store the name, stock and price for each product in one table and the information for each product in the (id, value) format in another table.
I do know, a priori, the fields that each product category should have. For instance, a product of type Desktop should have, among others, memory size and storage size as fields, whereas another product of category Monitor should have resolution and screen size as fields.
My question is: How do I guarantee, in Django, that each product contains only the fields for its category? More precisely, when specifying a product of category Monitor, how to assure that only resolution and screen size are fields in the ProdData table?
I found a similar question Django: Advice on designing a model with varying fields, but there was no answer on how to assure the above.
Thank you in advance.
Django is an excellent framework, but it is still just an abstraction over a relation database.
What you are asking isn't efficiently possible in a relational database, so it will be tough to do in Django. Primarily, because at some point your code will need to be converted to tables.
There are basically 2 ways you can do this:
A product class with a ManyToMany relation to an attribute table:
class Product(models.Model):
name = models.CharField(max_length=20)
stock = models.IntegerField()
price = models.FloatField()
product_type = models.CharField(max_length=20) eg. Monitor, desktop, etc...
attributes = models.ManyToManyField(ProductAttribute)
class ProductAttribute(models.Model):
property = models.CharField(max_length=20) # eg. "resolution"
value = models.CharField(max_length=20) # eg. "1080p"
But, your logic around certain classes of objects having certain properties will be lost.
Use inheritance. Django is just Python, and inheritance is certainly possible - in fact its encouraged:
class Product(models.Model):
name = models.CharField(max_length=20)
stock = models.IntegerField()
price = models.FloatField()
class Desktop(Product):
memory_size = models.CharField(max_length=20)
storage_size = models.CharField(max_length=20)
class Monitor(Product):
resolution = models.CharField(max_length=20)
screen_size = models.CharField(max_length=20)
Then you can do queries on all products - Products.objects.all() - or just Monitors - Monitor.objects.all()` - and so on. This hard codes the possible products in code, so a new product type requires a database migration, but it also gives you the ability to embed your business logic in the models themselves.
There are trade-offs to both these approaches which you need to decide, so picking is up to you.
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.
Consider the following two Django models:
class Item(models.Model):
'''
Represents a single item.
'''
title = models.TextField()
class Information(models.Model):
'''
Stores information about an item.
'''
approved = models.BooleanField(default=False)
multipurpose_field = models.PositiveIntegerField()
Due to the way the models are organized, I am forced to use a PositiveIntegerField in Information for referencing an Item instead of using a ForeignKey. This makes queries more difficult.
I would like to select all items referenced by an Information instance with approved set to True. In other words, I would like to do this:
Information.objects.filter(approved=True)
...except that the query will return instances of Information instead of the Item referenced in multipurpose_field.
I probably could do this with raw SQL:
SELECT app_item.title FROM app_item
LEFT JOIN app_information
ON app_information.multipurpose_field = app_item.id
WHERE app_information.approved = 1
Is there a way to do this without resorting to raw SQL (which often isn't very portable)?
ForeignKey's field type is determined by the related field. Consider redesigning your models this way:
class Item(models.Model):
id = models.PositiveIntegerField(primary_key=True)
title = models.TextField()
class Information(models.Model):
approved = models.BooleanField(default=False)
multipurpose_field = models.ForeignKey(Item)
Then your query will be represented this way:
Item.objects.filter(information__approved=True)
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