I changed the model, synced the db, and now when i do:
Prs = Products.objects.filter(PrName__icontains='bla')
I get the error:
ERROR: column search_products.pr_name does not exist
LINE 1: SELECT "search_products"."id", "search_products"."pr_name", ...
But pr_name was the old model, this is how the new model looks like:
class Products(models.Model):
PrName = models.CharField(max_length=255)
PrDescription = models.CharField(max_length=4000)
PrPrice = models.DecimalField(max_digits=5, decimal_places=2)
PrCompany = models.ForeignKey(Companies)
def __str__(self):
return self.PrName
Why am i getting this error? I synced the db 100 times, checked all the code, there is no reference to pr_name anywhere?
Have you tried restarting your server? If you are using anything other than the development server, you'll probably need to do that manually after making changes like this.
Unfortunately the thing you try to do is not supported by django out of the box :-(
but you can do it ether by adding a db_column to the fields or by exporting the data, removing the table from the database, edit the export file, recreate the database table and reimporting the data.
Also look at the various schema evolution solutions out there
Related
Context:
I'm playing around with setting up a DRF project using the postgresql sample database located here: Postresql Sample DB
Problem:
The sample database is already set up with intermediate tables film_category and film_actor. When using manage.py to inspectdb it generates these intermediate tables explicitly (FilmCategory and FilmActor) and they serve no purpose in the code as they only contain the ids for the two related fields. If I were to create them using the Django ORM I could just declare:
class Film(models.Model):
...
actors = models.ManyToManyField(Actor, related_name='films')
Django creates these tables "behind the curtain" so they take up no space in my code. I attempted to just set up a ManyToManyField like so:
actors = models.ManyToManyField(Actor, db_table='film_actor', related_name='films')
categories = models.ManyToManyField(Category, db_table='film_category', related_name='films')
When attempting to migrate, however, this fails giving me the following error:
psycopg2.errors.DuplicateTable: relation "film_actor" already exists
I don't think I want to create this ManyToManyField without explicitly telling it which db_table to use because I believe that would generate an entirely new intermediate table and I lose access to all the data already stored in those intermediate tables in the original sample database.
I was able to get it to work without errors and the expected operations function normally by doing:
actors = models.ManyToManyField(Actor, through='FilmActor', related_name='films')
But now I have an explicitly defined FilmActor and FilmCategory model sitting in my models.py that I cannot remove without causing errors:
class FilmActor(models.Model):
actor = models.ForeignKey(Actor, models.CASCADE)
film = models.ForeignKey(Film, models.CASCADE)
last_update = models.DateTimeField()
class FilmCategory(models.Model):
film = models.ForeignKey(Film, models.CASCADE)
category = models.ForeignKey(Category, models.CASCADE)
last_update = models.DateTimeField()
Has any dealt with explicitly defined intermediate tables generated from an existing DB with inspectdb? Is there a way to get rid of those models that were generated while still allowing the normal ManyToMany operations? Technically what I want to do is working, I just feel like having those two intermediate tables explicitly declared as models in my code when they have no additional data (other than "last_update") feels icky.
I'm reading this tutorial to lear the basics of django and I'm facing a problem I can't solve.
I'm at this page http://www.tangowithdjango.com/book17/chapters/models_templates.html at the sluglify function approach.
In the tutorial the author says we have to create a new line in our category model for th slugfield. I folow strictly all the steps just as I show here:
from django.db import models
from django.template.defaultfilters import slugify
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
likes = models.IntegerField(default=0)
views = models.IntegerField(default=0)
slug = models.SlugField(unique=True)
def __unicode__(self):
return self.name
class Page(models.Model):
category = models.ForeignKey(Category)
title = models.CharField(max_length=128)
url = models.URLField()
views = models.IntegerField(default=0)
def __unicode__(self):
return self.title
When I run the "makemgiration" command everything works as expected: I choose the first option and provide ‘’ . BUT when I run "migrate" I get:
django.db.utils.Integrity error: Slug column is not unique
What is going on here? I've repeated several times the migrations and tried other default codes but with the same ending. I can't figure out what im doing wrong. They only thing left is that i'm giving something else instead of ‘’ (Firstly I thoughtthey were '' or ").
Thankyou for your time and help!
Delete db.sqlite3 and re run
python manage.py syncdb
Then perform the migrations
python manage.py makemigrations rango
python manage.py migrate
and re run your population script. This is a downside of Django that whenever you change models.py the db must be recreated.
I am also going through the tutorial and I was having the same issue a couple days ago.
I believe the problem is that you are trying to add a new field (slug) and have it be unique for each of the elements in your table but if I'm not mistaken you already have some data in your table for which that value does not exist and therefore the value that this field would get for those rows is not unique, hence the "django.db.utils.Integrity error: Slug column is not unique".
What I did was simply to delete the data in the table (because it was only a couple of fields, so no big deal) and THEN perform the addition of the field to the model. After doing that, you can put the data back in the table (if you're following the tutorial you should have a script for automated table population so you just run that script and you're golden). Once you have done that, all the rows in the table should have a unique slug field (since it is automatically generated based on the category name) and that solves the problem.
Note that if your table is very large, this may not be a very good solution because of the deletion of data so perhaps there is a better way, like adding that field to the model without it being unique, then running a script that sets the slug field for every row to an unique value and then setting the model's field as unique but I'm not very knowledgeable on SQL and the first solution worked just fine for me so it should work for you as well.
try deleting the sqlite3.db file from the project's directory. i was stuck on a similar problem and that really works..also even if you modify your population script, you have to delete and the recreate the db file to see the changes made....
I have 2 tables, the relation is one to many, "Book" (id, name, author) -> "BookStatus" (id, status, date). I want to get all the books with their LAST status (according the field 'date') in a queryset. How can I accomplish that?
After that, how could I show that field (status) through my model "Book", something like Book.last_status.
Thanks in advance
Unfortunately this isn't easy to do through the ORM. The reason is that the SQL required for this is surprisingly complex. First you need to fetch the latest status date, then join the status matching that status.
If you need only access to the latest status on Python side, then you can use book.statuses.latest() (generates a query per model), or possibly a property on the model:
#property
def latest_status(self):
latest_status = None
for status in self.statuses.all():
if latest_status is None or latest_status.date < status.date:
latest_status = status
return latest_Status
Now you can use latest_status on Python side to fetch the latest status of the book. If you add prefetch_related when fetching books, accessing latest_status will not generate a query.
If you need access to the latest status when querying things become much more complicated. I have often used a solution where I create views in to the database for latest items, then use those views through the ORM. So, something like this in the database:
CREATE VIEW latest_book_status_view AS (
SELECT null AS id,
book_status.book_id,
book_status.id AS status_id
FROM book_status
WHERE book_status.date = (SELECT max(inner_status.date)
FROM book_status inner_status
WHERE inner_status.book_id = book_status.book_id)
);
In models.py:
class LatestBookStatus(models.Model):
# Note the null id column above. It will be used as fake primary key
# for this model.
book = models.OneToOneField(Book, null=True, on_delete=models.DO_NOTHING, related_name='latest_status')
status = models.OneToOneField(BookStatus, null=True, on_delete=models.DO_NOTHING)
class Meta:
db_table = "latest_book_status_view"
managed = False
Now you should be able to issue queries where you filter on status:
Book.objects.filter(latest_status__status__date__gte=today())...
And you can fetch the latest status by:
qs = Book.objects.select_related('latest_status__status')
# access it
qs[0].latest_status.status.date
Unfortunately this setup is complex and comes with some problems. For example, when testing you will need some way to generate the views in to the testing database. Django 1.7 migrations and RunSQL operation is one way to do this.
In short: if you need access to latest status on Python side, use the property approach. If you need access to the latest status on SQL side, be prepared for a more comlex solution. One possible solution is given above.
Be sure to set nice related_name and setup proper get_latest_by for BookStatus.
books = Book.objects.prefetch_related('statuses')
books[0].statuses.latest()
I have a Foreign Key from one model into another model in a differente database (I know I shouldn't do it but if I take care properly of Referential Integrity it shouldn't be a problem).
The thing is that everything works fine...all the system does (relationships on any direction, the router takes care of it) but when I try to delete the referenced model (which doesn't have the foreign key attribute)...Django still wants to go throught the relationship to check if the relationship is empty, but the related object is on another database so it doesn't find the object in this database.
I tried to set up on_delete=models.DO_NOTHING with no success. Also tried to clear the relationship (but it happens clear doesn't have "using" argument so I it doesn't work either). Also tried to empty the relationship with delete(objects...), no success.
Now I am pretty sure the problem is in super(Object,self).delete(), I can not do super(Object,self).delete(using=other_database) because the self object is not in another database just the RelatedManager is. So I don't know how to make Django to understand I don't want even to check that relationship, which by the way was already emptied before the super(Object,self).delete() request.
I was thinking if there is some method I can override to make Django avoid this check.
More graphical:
DB1: "default" database (orders app)
from django.db import models from shop.models import Order
class IOrder(models.Model):
name = models.CharField(max_length=20, unique=True, blank=False, null=False)
order = models.ForeignKey(Order, related_name='iorders', blank=True, null=True)
DB2: "other" database
class Order(models.Model):
description = models.CharField(max_length=20, blank=False, null=False)
def delete(self):
# Delete iOrder if any
for iorder in self.iorders.using('default'):
iorder.delete()
# Remove myself
super(Order, self).delete()
The problem happens when supper(Order.self).delete() is called, then it can not find the table (iorder) in this database (because it is in 'default')
Some idea? Thanks in advance,
I already resolved my issue changing super(Order,self).delete() with a raw SQL delete command. Anyway I would love to know if there is a more proper way of doing this
I have a Shops model and would like each shop to be able to login to my application. Following as best I can the guide at http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/ and various other googlings, I've got part of the way there, but I've run into a problem. When I try to login as a shop, I get the following error:
OperationalError at /login/
(1054, "Unknown column 'shops.user_ptr_id' in 'field list'")
Shops model:
class Shops(User):
shop_id = models.AutoField(primary_key=True)
shop_code = models.CharField(unique=True, max_length=5)
shop_type_fk = models.ForeignKey(ShopTypes,
null=True,
db_column='shop_type_id',
blank=True)
address_fk = models.ForeignKey(Addresses, db_column='address_id')
phone_number = models.CharField(max_length=30)
#email = models.EmailField(max_length=255, blank=True)
description = models.TextField(blank=True)
does_gift_aid = models.NullBooleanField(null=True, blank=True)
objects = UserManager()
class Meta:
db_table = u'shops'
I've sync'd the database, so surely it should have made the column user_ptr_id. Does anyone know where I'm going wrong?
"I've sync'd the database, so surely it should have made the column user_ptr_id."
What makes you think that? Especially in light of this clear statement in the docs for syncdb:
Syncdb will not alter existing tables
syncdb will only create tables for
models which have not yet been
installed. It will never issue ALTER
TABLE statements to match changes made
to a model class after installation.
Changes to model classes and database
schemas often involve some form of
ambiguity and, in those cases, Django
would have to guess at the correct
changes to make. There is a risk that
critical data would be lost in the
process.
If you have made changes to a model
and wish to alter the database tables
to match, use the sql command to
display the new SQL structure and
compare that to your existing table
schema to work out the changes.
It does sound like you had an existing shops table before changing it to inherit from User (as Daniel notes), and syncdb does not update the schema for existing tables.
You need to drop the table and then run syncdb, if possible. Otherwise you need to go into your database and add the user_ptr_id field manually, if you know how to do that. The definition should look something like this:
"user_ptr_id" integer NOT NULL UNIQUE REFERENCES "auth_user" ("id")