0

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.

enter image description here

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

William Le
  • 825
  • 1
  • 9
  • 16
  • when you look at the database what columns are there? Run a sql query like `select * from yourapp_products` – AMG Feb 28 '22 at 16:01
  • @AMG I have 'id' and 'title' columns, both are empty – William Le Feb 28 '22 at 16:03
  • @SeanWilliam is deleting your table(s) and recreating them an option? – Iain Shelvington Feb 28 '22 at 16:05
  • Based on your example, `hello` and `halo` should be in the title. Sure you are on the right database? – AMG Feb 28 '22 at 16:07
  • @IainShelvington well I did that and add ```class Meta: managed = False db_table = 'products'``` but doing that makes me unable to add a new product in django admin without getting this error – William Le Feb 28 '22 at 16:07
  • if managed is False, you'll need to create the table per https://docs.djangoproject.com/en/4.0/ref/models/options/#managed. What does your create sql look like? – AMG Feb 28 '22 at 16:10
  • @AMG when i add a new product inside django admin, the id field in my database table is Null also, as well as in the django admin products table – William Le Feb 28 '22 at 16:10
  • I suspect your database does not have the autoincrement on. Since the table is unmanaged, you have to create that manually. Or set managed back to True. – AMG Feb 28 '22 at 16:14
  • @AMG I just updated the way I implemented to update my datatable. Could you have a look? – William Le Feb 28 '22 at 16:14
  • @AMG i tried ```managed=True``` and still got the same error :(( – William Le Feb 28 '22 at 16:15

1 Answers1

1

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

AMG
  • 1,606
  • 1
  • 14
  • 25