How to make a one to many relationship in Django/Mysql?
I have an identical situation to this post, yet, my django returns errors on the admin page:
get() returned more than one order2pizza-- it returned 5!
order2pizza with that pizza already exists.
My mysql database have composite keys on a tertiary table to order and pizza to link multiple pizzas to an order.
models.py:
class Orders(models.Model):
order_id = models.AutoField(primary_key=True)
order_name = models.CharField(max_length=100, blank=True, null=True)
class Pizza(models.Model):
Pizza= models.AutoField(primary_key=True)
Pizza_name= models.CharField(max_length=50, blank=True, null=True)
class order2pizza(models.Model):
order = models.ManyToManyField(Orders, models.DO_NOTHING, )
pizza_id= models.IntegerField()
class Meta:
unique_together = (('order ', 'pizza_id'),)
A many-to-many relation can be expressed in two ways. First, you can manually specify a "join" model, like this:
class Orders(models.Model):
order_name = models.CharField(max_length=255, blank=True)
class Pizza(models.Model):
Pizza_name= models.CharField(max_length=255, blank=True)
class Order2Pizza(models.Model):
order = models.ForeignKey(Order, models.CASCADE)
pizza = models.ForeignKey(Pizza, models.CASCADE)
class Meta:
unique_together = ['order ', 'pizza']
This is useful if you want to put extra fields on the Order2Pizza model. A field named quantity would be very useful in your example.
The second option is to use a ManyToManyField. This will automatically create the join model for you:
class Orders(models.Model):
order_name = models.CharField(max_length=255, blank=True)
pizzas = models.ManyToManyField('Pizza', related_name='orders')
class Pizza(models.Model):
Pizza_name= models.CharField(max_length=255, blank=True)
In your original question you put the ManyToManyField on the Order2Pizza model, which is nonsensical.
However, the source of your bug is probably your manual inclusion of several *_id fields. Don't do that. They will always be created automatically by Django and you should never have to specify them manually. Instead, try the two options above and see how they work.
Related
I have 4 models: Products (the list of products: freezers, microwaves, tvs and pcs), ProductType (entertainment and home appliances), Credit (a credit is registered on each purchase) and PurchaseReason (the reason why the customer has bought the product).
The PurchaseReason depend on the productType, so the purchaseReason has a foreignKey field productType.
In addition, each credit has a product as foreignKey and a purchaseReason as foreignKey.
Also, I have the ProductReason field as a choice field in the credit model, and I want the options to be set dynamically based on the product field of the credit model.
I'm creating an API so I think this cant be handle with modelForms, but i'm not sure. The hard work would be with the serializers (DRF) and with the django-admin (specially this one because in my product the django admin plays an important role)
What would be the best approach to manage my models in Django?
Here are my models. In credit I'm not sure how to implemente the purchase reason:
class Credit(models.Model):
client = models.ForeignKey('clients.Client', on_delete=models.SET_NULL)
name = models.CharField(max_length=30, null=False, blank=True)
product = models.ForeignKey('product',on_delete=models.SET_NULL)
reason_purchase = models.ChoiceField(????)
class PurchaseReason(models.Model):
product_type = models.ForeignKey(product_type, on_delete=models.CASCADE)
reason = models.CharField(max_length=30, null=False, blank=True)
class ProductType(models.Model):
name = models.CharField(max_length=30, null=False, blank=False)
class Product(models.Model):
model = models.CharField(max_length=30, default=None, null=True)
product_type = models.ForeignKey(product_type, on_delete=models.CASCADE)
When we use the foreign key, we need to mention the model name of that particular model so that we can integrate that particular model in that model as a reference entity. Have a look at this example.
from django.db import models
class Reporter(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.EmailField()
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
class Article(models.Model):
headline = models.CharField(max_length=100)
pub_date = models.DateField()
reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
def __str__(self):
return self.headline
class Meta:
ordering = ['headline']
you've not mentioned the model name properly. it should be Product in place of 'product' in the Credit class, product field.
use this reference https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_one/
i think you should be able to use the Foreignkey field properly after this. Although, if you can't, you can share the actual objective. i will help you to write the correct model.
Best wishes :)
I need to model a many to many relationship.
I've read some documentation, but I don't know how to model.
I'll give you an example of what I want to do.
I have two entities, Album and song.
They have a many to many relationship.
class Song(models.Model):
name = models.CharField(unique=True, max_length=255)
class Album(models.Model):
nombre = models.CharField(unique=True, max_length=255)
songs = models.ManyToManyField(Song, blank=True)
The user in the frontend, provides me the data of an album that I must save.
It provides me the name of the album and the name of the songs.
How could I model it on the serializers?
Nothing runs.
I think you can delete that blank=True i think it automatically can be blank.
class Song(models.Model):
name = models.CharField(unique=True, max_length=255)
class Album(models.Model):
nombre = models.CharField(unique=True, max_length=255)
songs = models.ManyToManyField(Song, related_name='songs', blank=True)
and you can make the serializer.
Django will create a table for many to many relationships. You can do this by yourself as well with customized fields. For example, you may like to save the order for songs in an album:
class Song(models.Model):
name = models.CharField(unique=True, max_length=255)
class Album(models.Model):
name = models.CharField(unique=True, max_length=255)
class AlbumSong(models.Model):
album = models.ForeignKey('Album', null=False, on_delete=models.PROTECT)
song = models.ForeignKey('Song', null=False, on_delete=models.PROTECT)
order = models.PositiveIntegerField(null=False)
removed = Bit1BooleanField(null=False, default=False)
Hello all I am making auction website like ebay, I have this model design which has many other extra attributes model classes for different categories. But here let's take an example of a PC one which will be used for its sub-categories Desktop and Laptop.
Now the problem, I want to create ModelForm for users. For instance if user selects Desktop as their product to put on auction, how will that modelform code look like? So the Desktop respected fields are given to the user to fill from the extra_pc_attributes class? The problem is that, wouldn't it get tedious to write separate modelform for each category and also in the views.py use those as objects.
Maybe use Jsonfield instead of creating a whole EAV old-fashioned table for extra attributes? But I am new and I don't know how it will work or even if it applies to this situation.
class Categories(MPTTModel):
name = models.CharField(max_length=50, unique=True)
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
class auction_product(models.Model):
product_name = models.CharField(max_length=64)
category = models.ForeignKey(Categories, on_delete=models.CASCADE)
date_added = models.DateField(default=timezone.now)
user = models.ManyToManyField(User, through='product_ownership', related_name='product_user')
product_bid = models.ManyToManyField(User, through='bid', related_name='product_bid')
product_comment = models.ManyToManyField(User, through='comment')
album = models.OneToOneField(ImageAlbum, related_name='product_model', on_delete=models.CASCADE)
def __str__(self):
return self.product_name
#Extra PC Attributes
class extra_pc_attributes(auction_product):
processor = models.CharField(max_length=264)
ram = models.FloatField()
brand = models.CharField(max_length=64)
motherboard = models.CharField(max_length=264)
case = models.CharField(max_length=264)
screen_size = models.FloatField()
weight = models.FloatField()
I have a blog project and users can create posts with similar titles, How can I prevent a user or even the admin from proceeding without getting an error that the title already exists so that I can avoid future errors in the website such as get() returned more than one Post-it returned 2!
I have tried to use class meta for unique together but still, post was saved with the same title
Here is the post model
class Post(models.Model):
designer = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
slug = models.SlugField(blank=True, null=True, max_length=120)
def __str__(self):
return self.title
class Meta:
unique_together = ('title', 'slug')
You can add unique=True
title = models.CharField(max_length=100, unique=True)
See the docs here.
What I'm trying to achieve is, having model Person that is created and managed by Django have a ManyToMany field with model Property that was "created" using inspectdb and already exists in the database.
(Property contains Geographical data and cannot be managed or changed by Django)
When trying to migrate, it raises :
ValueError: Related model 'cadastroapp.Property' cannot be resolved
Full stack here
Worth nothing that I removed from the migration file the step to create model Property, since it already exists and AFAIK there's no way to tell Django this in the model Class
models.py (simplified) :
class Person(models.Model):
objectid = models.AutoField(primary_key=True)
properties = models.ManyToManyField(
'Property',
through = 'Person_Property',
)
class Meta:
db_table = 'django_person'
class Person_Property(models.Model):
cod_person = models.ForeignKey('Person', on_delete=models.CASCADE)
cod_property = models.ForeignKey('Property', on_delete=models.CASCADE)
class Meta:
db_table = 'django_person_property'
class Property(models.Model):
objectid = models.BigIntegerField(unique=True, primary_key=True)
created_user = models.CharField(max_length=765, blank=True, null=True)
created_date = models.DateTimeField(blank=True, null=True)
last_edited_user = models.CharField(max_length=765, blank=True, null=True)
last_edited_date = models.DateTimeField(blank=True, null=True)
shape = models.TextField(blank=True, null=True) # This field type is a guess. - ESRI Shape
class Meta:
managed = False
db_table = '"GEO"."PROPERTY"'
There are a couple errors in your models.py file.
When defining a Foreignkey or ManytoMany field, you don't want the model name to be in quotes.
Please change:
class Person(models.Model):
properties = models.ManyToManyField(
'Property',
through = 'Person_Property',
)
and
class Person_Property(models.Model):
cod_person = models.ForeignKey('Person', on_delete=models.CASCADE)
cod_property = models.ForeignKey('Property', on_delete=models.CASCADE)
to:
class Person(models.Model):
properties = models.ManyToManyField(
Property,
through = 'Person_Property',
)
and
class Person_Property(models.Model):
cod_person = models.ForeignKey(Person, on_delete=models.CASCADE)
cod_property = models.ForeignKey(Property, on_delete=models.CASCADE)
then delete your migration file cadastroapp.0006_auto_20161122_1533.
then run makemigrations and migrate again.
This may still not migrate without errors, but it will get us on the right track.
I think that you want to put the model name in quotes. In case you leave it without quotes you have to ensure that the model is defined before the ManyToMany field has been defined. So you will need to have first class Property and then class Person in your file. When you put model name as "Property" then you do not need to care about order of class definitions.