Models inheritance in django: getting OneToMany objects from parent class - django

Here is model structure: Client is User, Client can be corporate or person:
class Client(User):
#fields
class ClientCorporate(Client):
#fields
class ClientPerson(Client):
#fields
And client can make orders:
class Order(models.Model):
client=models.ForeignKey(Client)
#fields
I try to create common orders list for any type of client, here is view:
def orders_list(request):
client=request.user.client
return list_detail.object_list(request,
queryset = client.order_set.all(),
#templates ...
)
And it leads to an error:
DatabaseError while rendering: no such column: cabinets_order.client_id
I browse db and find that all User childs have column "user_prt_id". So, what's the best way to make it work in django? Create custom manager, or change models in appropriate way? ...

This error just means you don't have the database column client_id in your cabinets_order table.
Make sure you python manage.py syncdb. If you added the foreign key after syncdbing once, you'll have to reset it, or add the foreign key manually. You can generate the SQL needed by running python manage.py sqlall cabinets, then picking the ForeignKey generation bits.
If you can stand to lose your current data (if in development), just run python manage.py reset cabinets

Related

How to add new field to existing django model postgres

Let's suppose I have the following model:
class Test(models.Model):
field_one = models.CharField(max_length=80)
Now, we have created 2-3 Model objects with field_one field.
p1 = Test(field_one="Object1")
p1.save()
p2 = Test(field_one="Object2")
p2.save()
Later, I realised that I need to add another field field_two to my Test model.
class Test(models.Model):
field_one = models.CharField(max_length=80)
field_two = models.IntegerField(default=3)
Now, Doing makemigrations & migrate
and running server.
which will prompt the following error
django.db.utils.ProgrammingError: column mainapp_test.field_two does not exist
I understand that this error occurs due to my 2 existing objects in PostGresDB doesn't have field_two column.
Is there any effective way to add field_two column to my existing objects with some default value? or How to solve this problem?
Django Version: 2.0
Django ORM DB: PostGresql
When you add a field to an existing model, you must either provide a default value in the code, or set it to null/blank = True, or provide a one-off default while migrating.
Since you are providing a default in the code, the migration should run without issues. At least from experience, I've added several BooleanFields with default=False to my existing model with thousands of entries, and I never got a ProgrammingError.
Have you tried shutting down the Postgres backend before running makemigrations and migrate? I would think Django would do this but that's the only thing I can think of. Also, obviously, shut down the Django server if it's still running.

Django rest framework api with existing mysql database

How can I create a Django REST Framework API that connects to an already existing MySQL tables instead of creating them through modela.py. My models.py shows something like this:
class Author(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
def __str__(self):
return f'{self.first_name} {self.last_name}'
Instead of this, I need to take data directly from existing tables in MySQL.
For that you need to define same class name as your table name with meta char field
like for example
RandomTable(id INT(10),name varchar(10)) is your existing mysql table then the models.py for it will be
class AppnameRandomTable(models.Model)
id = models.CharField(db_column="id") #name of column of existing db
inside that you will need to write the fields of your existing table name in meta section
class Meta:
db_table = "RandomTable" #your existing mysql table name
time saving hack just create a class in models.py and on terminal run "python manage.py inspectdb" you will automatically get all the column names from there.
You can just copy and paste names from there , because for reading and writing on columns you need to define their variables in your class even if the table is existing mysql table
python manage.py inspectdb > models.py
If you run that command it will create a models.py in the project's root directory. Once you've done that you can either move it directly into the project or create a models folder and break it down into areas of concern from there. You will likely have to do the work of adding related_name = 'foo' to a lot of fields that have relationships with other models. That can be time-consuming but it works.

Django: how to add a field to an existing model without much rewrite of the code

our website lists local city events. It's Django-based so there's a lot of code related to 'event' model. Until now, we work only in one city and so all the events mean to be local.
Now we need to extend the website to another city. This means 'event' model gets a new attribute 'city', and our middleware will set a global value CurrentCity based on geoip.
We need to extend 'event' model so it would filter only records where 'city' attribute equals to CurrentCity value. There is too much code in different views and models working with the 'event' so we can't update each module.
Is there any single place to patch that would make our 'event' model aware of the CurrentCity value?
Depending a lot in your structure and Django version I think you have 2 options.
South
The best one is to install the application "South". I don't know if you already know it or you're using it but I think it should be your first option.
In case you're not using it, you should do this steps:
Install with pip install South
Create your first migration with:
python manage.py schemamigration YOURAPPNAME --initial
You need to fake this migration, because you have already the fullfilled database so you need to do:
python manage.py migrate YOURAPPNAME --fake
Add the new field to the model Event in the file models.py
Generate the new migration to make South create the new field in your database with:
python manage.py schemamigration YOURAPPNAME --auto
Final step, execute the migration created with:
python manage.py migrate YOURAPPNAME
Tips
--initial for the first migration --auto for the rest
The initial migration is faked because you already have tables in your database, if you try to migrate without the fake it will return error "Table already exists"
New Model City
Another option, in case you can't modify your actual Model, or maybe if it's too messy, another option is to generate an externa Model City like this:
class City(models.Model):
event_foreign = models.ForeignKey(Event)
event_many = models.ManyToManyField(Event, blank=True, null=True)
name = models.CharField....
postal_code = models.CharField....
# etc...
I don't know wich is optimal for you, a Foreign Key or a ManyToMany, depends if a City can have more than 1 Event or no, it's your choice.
When you have a model like this you can access from this City model to the Event (because of the ForeignKEy or ManyToMany) but this relation goes also in the other direction, if you have an Event you can get the City/cities related to it I'm gonna show two examples:
Example 1 using Foreign Key
city = City.objects.get(id=1)
city.event # Returns event
event = Event.objects.get(id=1)
event.city # Returns city
Example 2 using Many to Many
city = City.objects.get(id=1)
city.event.all() # Returns a list of events
event = Event.objects.get(id=1)
event.city_set.all() # Returns a list of cities

Database error in creating blog using django

Am trying to create simple blog using django.
At first,i created database with the command
python manage.py syncdb
when i try to save blog post,i get the following error
DatabaseError: table blog_app_post has no column named body
models.py code :
from django.db import models
from taggit.managers import TaggableManager
class Post(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
created = models.DateTimeField()
tags = TaggableManager()
def __unicode__(self):
return self.title
but the column named body is actually created in the Db.
BEGIN;
CREATE TABLE "blog_app_post" (
"id" integer NOT NULL PRIMARY KEY,
"title" varchar(255) NOT NULL,
"body" text NOT NULL,
"created" datetime NOT NULL
)
what does this error mean and anyone would propose a solution for this?
This is probably because you changed the structure of your posts data structure. What you need to do now is delete the schema for your previous table and paste in the new one.
You can avoid problems like this by using migration managers like south.
So, in order to solve this, run manage.py sql <app_name>, then you simply copy the latest SQL table on the list, the first one that is printed. Then you simply maange.py dbshell and then just paste and run the SQL.
How do you say that it's created, you checking it using python manage.py sqlall?
Did you add field body after running syncdb initially. In that case you will have to use a migration.

Create a django project from an existing database

I have a n existing MySQL database. I want to create a new django application with that database.
I read that I need to run "syncdb" each and every time when add a new model in django. That time adding a new table in database in <database_name>.<table_name> format. And fetching data from that table.
What is the correct method to fetch data from an existing database in django ?
This is my model:
from django.db import models
class Users(models.Model):
employee_id = models.CharField(max_length=30)
def __unicode__(self):
return self.employee_id
Use the Django model meta options to set db_table and db_column on your Models and Fields respectively. See these links for more info on how to use them:
https://docs.djangoproject.com/en/dev/ref/models/options/#db-table
https://docs.djangoproject.com/en/dev/ref/models/fields/#db-column