I've started learning Django from a YouTube course.
In the models.py file, there are two classes.
class Album(models.Model):
artist = models.CharField(max_length = 250)
album_title = models.CharField(max_length = 250)
album_logo = models.CharField(max_length = 1000)
def __str__(self):
return self.album_title + ' - ' + self.artist
class Song(models.Model):
album = models.ForeignKey(Album, on_delete=models.CASCADE)
file_type = models.CharField(max_length=10)
song_title = models.CharField(max_length=250)
genre = models.CharField(max_length=250)
def __str__(self):
return self.song_title
I added the genre in the Song after the migration. That's why I'm having problem while adding data.
In the interactive shell, if I try to save() , it shows there's no 'genre' field. If I try to migrate again, it shows something like this:
You are trying to add a non-nullable field 'genre' to song without a
default; we can't do that (the database needs something to populate
existing rows). Please select a fix:
1) Provide a one-off default now
(will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py Select an option:
What's the proper way of adding or deleting fields?
add default="" to genere field
class Song(models.Model):
album = models.ForeignKey(Album, on_delete=models.CASCADE)
file_type = models.CharField(max_length=10)
song_title = models.CharField(max_length=250)
genre = models.CharField(max_length=250, default="")
def __str__(self):
return self.song_title
As the error message shows, you add a field genre to Song model without adding default="" nor null=True parameters to it. When you migrate it, django don't know how to deal with the old data that has been inserted into the database without genere field. So you should set them to null with null=True or other default value with default="".
You can also just keep your code. But when you use the migrate command, you should tell django that you will give a default value like the django recommanded:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
press 1 and enter key. input "" and then django will set all the old data genre="".
Related
I have a choices field which has a set of limited number of choices like:
class Choices(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
This now is a foreign key to another model which has some data like:
class Item(models.Model):
name = models.Charfield(max_length = 255)
choice = models.ForeignKey(Choices, on_delete=models.CASCADE)
I want that if a choice does not exist, one may be able to add a new Choice item while submitting the form and add it to the database, then the newly created choice can be used again.
Please help me accordingly.
I'm working on the Django section of CS50 around the 30min mark on the video with the modes 'ForeignKey' section.
When i run the make migration i get the error.
You are trying to add a non-nullable field 'agent' to product without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
Select an option: 2
if I set the default as a string value i get the error saying it was expecting an id.
If i set it as 1 then i get the following.
The row in table 'clutter_product' with primary key '1' has an invalid foreign key: clutter_product.agent_id contains a value '1' that does not have a corresponding value in clutter_supplier.id.
class Supplier(models.Model):
company = models.CharField(max_length=64)
contact = models.CharField(max_length=64)
email = models.CharField(max_length=128, blank = True)
def __str__(self):
return f"{self.id} {self.company} {self.contact} {self.email}"
class Product(models.Model):
name = models.CharField(max_length=64)
sku = models.CharField(max_length=64, blank = True)
unit_cost = models.IntegerField()
rrp = models.IntegerField()
average_fee = models.IntegerField()
shipping_fee = models.IntegerField()
agent = models.ForeignKey(Supplier, default=1, on_delete=models.CASCADE, related_name="suppliers")
I would suggest to try these steps:
First, delete the migration file which is causing this problem.
Second change the model like this:
class Product(models.Model):
# rest of the fields
agent = models.ForeignKey(Supplier, null=True, default=None, on_delete=models.CASCADE, related_name="suppliers")
Third run makemigrations and migrate.
Fourth create a instance of supplier using supplier = Supplier.objects.create(company="ABC", contact="contact", email="a#b.c", pk=1)
Fifth(optional) Update the existing Product to haven a supplier-Product.objects.update(agent=supplier).
Sixth, if you want to constrain Products to be created with an agent, then remove null=True, default=None from agent field in Product model. Then run makemigrations and migrate.
i encountered the following problem when i try to migrate list of models one of which contains a ManyToMany field.
class Item(models.Model):
File "C:\Users\helin\Downloads\Django\E-commerce\Farmers\Farmersapp\models.py", line 60, in Item
sluger = farmer.First_Name
AttributeError: 'ManyToManyField' object has no attribute 'First_Name'
Below are the models i created.any help is appreciated.Thank you
class Farmer(models.Model):
id = models.AutoField(default=1,primary_key=True)
First_Name = models.CharField(max_length=15)
Last_Name = models.CharField(max_length=15)
def __str__(self):
return self.First_Name+" "+self.Last_Name
def get_farmer(self):
return self.farmer.First_Name+" " +self.farmer.Last_Name
class Item(models.Model):
id = models.AutoField(default=1,primary_key=True)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=6)
price = models.FloatField()
description = models.TextField(blank=True)
image = models.ImageField()
farmer = models.ManyToManyField(Farmer, through='ItemAmount',related_name='item')
sluger = farmer.First_Name
slug = models.SlugField(default=sluger)
def __str__(self):
return self.category
class ItemAmount(models.Model):
farmer = models.ForeignKey(Farmer, on_delete=models.CASCADE)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
First, would suggest to take a look at Python style guide, like lowercase attribute names, etc.
Django auto-creates id primary-key field on every model, unless other field is set as primary-key. So, this part can be safely avoided.
get_farmer method - how is it different from str? Also, these are model instance methods ((self)), so there is no self.farmer field on Farmer object - this will fail.
class Farmer(models.Model):
# id AutoFied is created by default by django, so no need to specify
# id = models.AutoField(default=1,primary_key=True)
first_name = models.CharField(max_length=15)
last_name = models.CharField(max_length=15)
def __str__(self):
return self.first_name + " " + self.last_name
farmer = models.ManyToManyField() - as it is ManyToMany, this means many farmers, so it is better to name field farmers, also same applies to reverse relation - Farmer might have multiple items - related_name=items.
sluger - is it a field? Also, it might have many farmers, so which one to pick?
slug - referencing self fields in default is not good idea, better set default in forms.
You can make slug CharField and set its value in save() method for example.
class Item(models.Model):
# id AutoFied is created by default by django, so no need to specify
# id = models.AutoField(default=1,primary_key=True)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=6)
price = models.FloatField()
description = models.TextField(blank=True)
image = models.ImageField()
farmers = models.ManyToManyField(
Farmer,
through='ItemAmount',related_name='items'
)
slug = models.SlugField()
def __str__(self):
return self.category
You can start with minimum working models and add new fields / methods one by one - it would be easier to debug and you will have base working app.
I have created the following model:
class World(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=200)
setting = models.CharField(max_length=200)
creation_date = models.DateTimeField('date created')
when I run manage.py makemigrations I get the following error:
You are trying to add a non-nullable field 'id' to world without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
Why does Django think I have an id field, and how do I get rid of this error?
I had previously set an ID field in my World model, this was confusing something as I had deleted it, I have added the line:
id = models.AutoField(primary_key=True)
When i ran makemitigrations again it asked me if I had renamed the ID field to this new one and I clicked yes and this sorted it out.
My model is now:
class World(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default='')
name = models.CharField(max_length=200)
setting = models.CharField(max_length=200)
creation_date = models.DateTimeField('date created')
I have a model:
class Review(models.Model):
name = models.CharField(max_length = 50)
link = models.CharField(max_length = 100)
book_id = models.IntegerField()
review_id = models.IntegerField()
content = models.TextField()
rating = models.IntegerField()
author = models.CharField(max_length = 50)
If I open admin http://127.0.0.1:8000/admin/my_app/review/ I'll see the list of records. For each record Django Admin display only one field ('Name' in my case). How Django Admin choise the field to display in the list of records.
Firstly I thinked that it is a first field in my model. I have moved Name-field down in the field list and recreate the database, but there was nothing to change.
Django calls the __unicode__ method on the model. For configuring the displayed fields in the change list see the detailed documentation!