Null ID in Django Admin - python

I'm trying to add a new product in my Products model in Django Admin, yet for some reasons the id field always become null after adding.
Below is my code:
models.py
from django.db import models
class Products(models.Model):
id = models.BigAutoField(primary_key=True) # incremental id
title = models.CharField(max_length=200)
def __str__(self):
return self.title
admin.py
from django.contrib import admin
from import_export.admin import ImportExportModelAdmin
from .models import *
class ProductsAdminConfig(ImportExportModelAdmin):
model = Products
search_fields = ('title',)
list_filter = ('title', )
list_display = ('id', 'title', )
admin.site.register(Products, ProductsAdminConfig)
Originally I created my database table Products with SQLAlchemy, converting CSV to Mysql. However, I wanted to be able to add a new product inside Django Admin as well.
I have tried emptying my SQL table, clearing my migration folder and run py manage.py makemigrations and py manage.py migrate, but the error still persisted.
When I tried adding a new product, the data rows with null ids still got generated.
Could you suggest me a way to solve this? Thank you!
UPDATE
This is how I create my table
import pandas as pd
from sqlalchemy import create_engine
class DfToMySQL:
def __init__(self, db, host, user, passwd, port, charset='utf8'):
self.db = db
self.host = host
self.user = user
self.passwd = passwd
self.port = port
self.charset = charset
def set_dataframe(self, path):
self.path = path
self.df = pd.read_csv(self.path, encoding="utf-8-sig")
def connect(self):
self.engine = create_engine(f'mysql+pymysql://{self.user}:{self.passwd}#{self.host}:{self.port}/{self.db}')
def drop_duplicated_rows(self, cols):
if cols:
self.df = self.df.drop_duplicates(subset=cols) # empty param if drop all duplicates
else:
print('\nPlease specify column(s) with duplicated rows!')
def to_mysql(self, table_name='table_name'):
self.table_name = table_name
self.df.to_sql(name=self.table_name, con=self.engine.connect(), if_exists = 'replace', index=False)
def print_sample_df(self, row=20):
print(self.df.head(row))
def df_from_mysql(self, table_name):
con = self.engine
df = pd.read_sql(f'SELECT * FROM {table_name}', con=con)
return df
def add_index_column(self):
arr = range(1, len(self.df) + 1)
self.df.insert(0, "index", arr, allow_duplicates=False)
self.df['index'] = self.df['index'].apply(str)
def add_id_column(self):
arr = range(1, len(self.df) + 1)
self.df.insert(0, "id", arr, allow_duplicates=False)
self.df['id'] = self.df['id'].apply(str)
def to_xlsx(self):
self.df.to_excel(r'sample.xlsx', encoding="utf-8-sig", index=False, header=True)
def execute_query(self, query=''):
self.query = query
self.con = self.engine.connect()
self.con.execute(query)
if __name__ == '__main__':
db = 'homing_pigeon2'
user = 'root'
passwd = ''
host = 'localhost'
port = 3306
charset='utf8'
csv_path = r"../csv/products.csv"
table_name = 'products'
d = DfToMySQL(db=db, host=host, user=user, passwd=passwd, port=port, charset=charset)
d.set_dataframe(csv_path)
d.print_sample_df()
d.connect()
d.add_id_column()
d.print_sample_df()
d.to_xlsx()
d.to_mysql(table_name=table_name)
CONCLUSION
I guess when creating a datable using SQLAlchemy with managed=False in the Products model, the only way I could add a new product inside Django Admin without any errors is using ImportExportModelAdmin in admin.py

Your script that creates the table is not including an autoincrement.
I believe you'll need to that after you've run your script. It is the database that assigns the id field for a BigAutoField primary key.
See the mysql documentation at:
https://www.techonthenet.com/mysql/auto_increment.php
I'm not certain of the command to make in existing field to have autoincrement after creation in mysql.
EDIT
See https://stackoverflow.com/a/2169090/4872140
ALTER TABLE document MODIFY COLUMN document_id INT auto_increment
Similar question:
sqlalchemy: how to add a table row with autoincrement in mysql

Related

Fetch two columns from db using SQLalchemy

I am learning python and trying to create a drop-down in my form with the data from another table. here is my code
Models.py
class empmasterModel(db.Model):
__tablename__ = "empmaster"
Empnum = db.Column(db.Integer, primary_key=True)
Employee_Number = db.Column(db.Integer(),primary_key=True,unique = True)
Employee_Name = db.Column(db.String())
Employee_Type = db.Column(db.String())
Coreid = db.Column(db.String())
EmailId = db.Column(db.String())
def __init__(self, Employee_Number,Employee_Name,Employee_Type,Coreid,EmailId):
self.Employee_Number = Employee_Number
self.Employee_Name = Employee_Name
self.Employee_Type = Employee_Type
self.Coreid = Coreid
self.EmailId = EmailId
def __repr__(self):
return f"{self.Employee_Number}:{self.Employee_Name}:{self.Employee_Type}:{self.Coreid}:{self.EmailId}"
Above is my models.py code with class empmaster from which DB table I need the employee number and employee name.
app.py
#app.route('/component/add', methods=['GET', 'POST'])
def componentadd():
error_msg = ''
success_msg = ''
if request.method == 'GET':
empmaster_data = empmasterModel.query.all()
print(empmaster_data , "dbbbbbbbbbbbbb")
return render_template('component/add.html', empmaster_data=empmaster_data)
Above is the app.py code where I am trying to fetch data from empmaster table. But here I am getting whole table data but not two-column data. I tried two column names in brackets after the filter too but it did not work. I searched for many solutions but was not getting desired results. Can somebody help me?
If you have session management, you can do something like:
session.query(
empmasterModel.Employee_Number.label("Employee_Number"),
empmasterModel.Employee_Name.label("Employee_Name")
).all()
If you use Flask with no session management, you can get the session from the SQLAlchemy instance.
db = SQLAlchemy() # Usually in you app.py
And then:
db.session.query(
empmasterModel.Employee_Number.label("Employee_Number"),
empmasterModel.Employee_Name.label("Employee_Name")
).all()

Pandas to_sql() table not allowing me to insert new rows

I have code that converts a csv into an sqlalchemy table. When I try and use db.session.add() it creates an entry in the datatable, but the id is null. This stops me from being able to interact with the data. I tried creating a normal SQL alchemy table and was able to insert rows fine, but for whatever reason the way pandas added the table is preventing me from adding more rows to the table. I will attach the relevant code. Let me know if you need more
db = SQLAlchemy()
DB_NAME = "database.db"
app = Flask(__name__)
sslify = SSLify(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db.init_app(app)
class Master(db.Model):
__tablename__ = "Master"
__table_args__ = {'extend_existing':True}
index = db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(150))
full_name = db.Column(db.String(150))
serial_number = db.Column(db.String(150))
asset_tag = db.Column(db.Integer)
def __repr__(self):
return '<Comments %r>' % self.id
def __init__(self, username, full_name, serial_number, asset_tag):
self.username = username
self.full_name = full_name
self.serial_number = serial_number
self.asset_tag = asset_tag
file_name = 'master.csv'
df = pd.read_csv(file_name)
df['asset_tag'].fillna('-999', inplace=True)
df['asset_tag'] = df['asset_tag'].astype('int')
df.replace(-999," ",inplace=True)
df.fillna(" ", inplace=True)
df.to_sql(con = app.config['SQLALCHEMY_DATABASE_URI'], index_label='index', name=Master.__tablename__, if_exists='append')
#app.route('/adds', methods = ['GET','POST'])
def adds():
thefullname = request.form.get('add_full')
theuser = request.form.get('add_user')
theasset = request.form.get('add_asset')
theserial = request.form.get('add_serial')
theadd = Master(username = theuser, full_name=thefullname, asset_tag=theasset, serial_number=theserial)
db.session.add(theadd)
db.session.commit()
return render_template('home.html')

Update not commited on mysql server flask-sqlalchemy

I am able to perform 'select' queries to my Mysql database.
However, the "insert" ones don't change the database, only the python objects. So when I restart the flask app, all the commited(?) editions are gone.
Views:
from flask import Flask, render_template, request, redirect, url_for, flash, Response
from sqlalchemy import exc
from models import *
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'kjhS7usfHGJHDez78'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+mysqldb://admin:admin#127.0.0.1:3306/grenier'
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
db.create_all()
#app.route('/ajax/submit_edition', methods=['POST'])
def submit_edition():
if request.method == 'POST':
given_id=1
show = Shows.query.filter_by(id=given_id).first()
show.short_description = "Hello"
try:
db.session.commit()
db.session.flush()
return "ok"
except exc.SQLAlchemyError:
return "Error in commiting the edition"
No particular exception is found. The route always returns "ok".
Models:
from sqlalchemy import Column, ForeignKey
from sqlalchemy.dialects.mysql import LONGTEXT, YEAR
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Shows(db.Model):
__tablename__ = "shows"
id = Column(db.Integer, ForeignKey("programmation.id"), primary_key=True)
date = Column(db.DATETIME)
title = Column(db.VARCHAR(50))
short_description = Column(db.VARCHAR(200))
type = Column(db.VARCHAR(20))
background_image = Column(db.VARCHAR(150))
content = Column(LONGTEXT)
def serialize(self, whatTo):
result = {}
if 'id' in whatTo:
result['id'] = self.id
if 'date' in whatTo:
result['date'] = str(self.date)
if 'title' in whatTo:
result['title'] = self.title
if 'short_description' in whatTo:
result['short_description'] = self.short_description
if 'type' in whatTo:
result['type'] = self.type
if 'background_image' in whatTo:
result['background_image'] = self.background_image
if 'content' in whatTo:
result['content'] = self.content
return result
class Programmation(db.Model):
__tablename__ = "programmation"
id = Column(db.Integer, primary_key=True)
semester = Column(db.Integer)
year = Column(YEAR)
When I look at the logs, the sql request is created for the select. But for the insert commit(), there is nothing.
Thank you !
The problem is usage of two different SQLAlchemy instance. When you call db.create_all() method it creates all tables which which inherited from db.Model but in your views you don't have any model inherited from db = SQLAlchemy(app). All your models inherited from other SQLAlchemy instance. To fix this import the db object from views to models module and use it as parent class for inheritance:
#models.py
from views import db
#db = SQLAlchemy() #remove this line
class Show(db.Model):
...

how to join two model of two separated database python peewee

I'm using peewee to use Mysql database.
import peewee
db_1 = peewee.MySQLDatabase('db_1', **{'user': 'root'})
db_2 = peewee.MySQLDatabase('db_2', **{'user': 'root'})
class User(peewee.Model):
id = peewee.PrimaryKeyField()
username = peewee.CharField()
class Meta:
database = db_1
class Tweet(peewee.Model):
id = peewee.PrimaryKeyField()
tweet = peewee.CharField()
user = peewee.IntegerField(db_column='user_id')
class Meta:
database = db_2
I want to execute this code:
m = Tweet().select(Tweet, User).join(
User, join_type=JOIN_INNER, on=User.id == Tweet.user
).where(
User.id == 13
)
but it raises this error:
peewee.ProgrammingError: (1146, "Table 'db_2.user' doesn't exist")
How I can fix it?
I thinkbest solution for problem use view on second database.
I create a views of users into db_2 and that code is work.

SqlAlchemy + Mysql: Unable to drop tables due to IntegrityError

When I try to reinitialize my database, I keep getting an IntegrityError:
sqlalchemy.exc.IntegrityError: (IntegrityError) (1217, 'Cannot delete or update a parent row: a foreign key constraint fails') '\nDROP TABLE users' ()
In my init_db script, I have:
def main(argv=sys.argv):
if len(argv) != 2:
usage(argv)
config_uri = argv[1]
setup_logging(config_uri)
settings = get_appsettings(config_uri)
engine = create_engine('...')
Session.configure(bind=engine)
session = Session()
Base.metadata.bind=engine
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)
It would let me drop the Users table, which is:
class User(Base):
__tablename__='users'
__table_args__={
'mysql_engine':'InnoDB',
'mysql_charset':'utf8',
}
user_id = Column(Integer, primary_key=True, unique=True)
username = Column(VARCHAR(16), primary_key=True, unique=True)
name = Column(VARCHAR(16))
password = Column(VARCHAR(20))
email = Column(VARCHAR(30))
creation = Column(DateTime, default = datetime.datetime.now)
def __init__(self, un, name, pw, email):
self.username = un
self.name = name
self.email = email
self.password = pw
I see two possible reasons:
Unmapped table: You have another table in the database which has a ForeignKey to the users table, but which is not mapped to any sqlalchemy model and therefore is not dropped during drop_all operation.
Missing ForeignKey mapping: Some relationship is missing in the sqlalchemy model. For example, the addresses table on the DB has a ForeignKey which points to the users table, but your model Address (or to put it properly, the mapper for the Address) does not configure this ForeignKey, and therefore during drop_all sqlalchemy has no way of knowing that this table should be dropped before the referenced one (users).

Categories