I was curious about using MySQL instead of SQLite for my Django project. Firstly, I would like to ask: where can I find an explicite guide of how to install MySQL with Django on Windows and if I use MySQL, will I type the exact type of code I would usually type in SQLite ?
For example:
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
When you type this in Django, it gets converted to:
CREATE TABLE "books_publisher" (
"id" serial NOT NULL PRIMARY KEY,
"name" varchar(30) NOT NULL,
"address" varchar(50) NOT NULL,
"city" varchar(60) NOT NULL,
"state_province" varchar(30) NOT NULL,
"country" varchar(50) NOT NULL,
"website" varchar(200) NOT NULL
);
So the same will be when using MySQL ?
Related
I am trying to run a app cloned from following repo
https://github.com/myogeshchavan97/fullstack_banking_app and stuck with mysql
I get following error when i run source /server/scripts.sql
I am using latest Server version: 8.0.23 Homebrew
ERROR 1064 (42000): You have an error in your SQL syntax; check the
manual that corresponds to your MySQL server version for the right
syntax to use near 'bank_account' at line 1
ERROR 1064 (42000): You
have an error in your SQL syntax; check the manual that corresponds
to your MySQL server version for the right syntax to use near
'BIGSERIAL PRIMARY KEY NOT NULL, first_name VARCHAR(32) NOT NULL,
last_name V' at line 2
ERROR 1064 (42000): You have an error in your
SQL syntax; check the manual that corresponds to your MySQL server
version for the right syntax to use near 'BIGSERIAL PRIMARY KEY NOT
NULL, access_token VARCHAR(500) NOT NULL, userid B' at line 2
scripts
CREATE DATABASE bank_account;
CREATE TABLE bank_user(
userid BIGSERIAL PRIMARY KEY NOT NULL,
first_name VARCHAR(32) NOT NULL,
last_name VARCHAR(32) NOT NULL,
email VARCHAR(32) NOT NULL,
password VARCHAR(255) NOT NULL,
unique(email)
);
CREATE TABLE TOKENS(
id BIGSERIAL PRIMARY KEY NOT NULL,
access_token VARCHAR(500) NOT NULL,
userid BIGSERIAL NOT NULL,
FOREIGN KEY(userid) REFERENCES bank_user(userid)
);
I get this error I tried with backticks as but unfortunately didn't work...I would appreciate your insight.
Try this:
CREATE TABLE bank_user( userid BIGINT PRIMARY KEY NOT NULL, first_name VARCHAR(32) NOT NULL, last_name VARCHAR(32) NOT NULL, email VARCHAR(32) NOT NULL, password VARCHAR(255) NOT NULL, unique(email) );
CREATE TABLE TOKENS( id BIGINT PRIMARY KEY NOT NULL, access_token VARCHAR(500) NOT NULL, userid BIGINT NOT NULL, FOREIGN KEY(userid) REFERENCES bank_user(userid) );
check the following link for mappings between PostgreSQL and MySQL.
In your case, instead of BIGSERIAL you need to use BIGINT.
The equivalent in MySQL would be:
CREATE TABLE bank_user (
userid BIGINT AUTO_INCREMENT PRIMARY KEY,
first_name VARCHAR(32) NOT NULL,
last_name VARCHAR(32) NOT NULL,
email VARCHAR(32) NOT NULL,
password VARCHAR(255) NOT NULL,
unique(email)
);
CREATE TABLE TOKENS (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
access_token VARCHAR(500) NOT NULL,
userid BIGINT NOT NULL,
FOREIGN KEY (userid) REFERENCES bank_user(userid)
);
Here is a db<>fiddle.
The equivalent of SERIAL is AUTO_INCREMENT.
Some comments:
32 characters may or may not be big enough for names. It is certainly not big enough for emails, which can get pretty long.
The password should be encrypted. Do not store clear-text passwords in the data.
I would be surprised if you really needed BIGINT for the userid. Are you really planning on having billions of users? A 4-byte integer should be sufficient.
NOT NULL is redundant when you declare a column to be the primary key.
I'm trying to create models taking a MySQL database as reference using Django, but when I try to migrate, it throws me the following error:
Cannot change column 'id': used in a foreign key constraint 'fk_post' of table 'demoniosmv.images'"
My models look like this:
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
class Images(models.Model):
#id = models.IntegerField(primary_key=True)
fk_post = models.ForeignKey('Post', related_name="images", blank=True, null=True, on_delete = models.CASCADE)
img_url = models.CharField(max_length=100, blank=True, null=True)
class Meta:
managed = True
class Post(models.Model):
#id = models.IntegerField(primary_key=True)
author = models.ForeignKey(User, related_name="posts", on_delete = models.CASCADE)
title = models.CharField(max_length=200, blank=True, null=True)
text = models.TextField(blank=True, null=True)
created_date = models.DateTimeField(default = timezone.now)
class Meta:
managed = True
And the SQL script from which I'm creating the database is this:
-- MySQL Script generated by MySQL Workbench
-- Sun Jul 21 14:14:44 2019
-- Model: New Model Version: 1.0
-- MySQL Workbench Forward Engineering
SET #OLD_UNIQUE_CHECKS=##UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET #OLD_FOREIGN_KEY_CHECKS=##FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET #OLD_SQL_MODE=##SQL_MODE, SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
-- -----------------------------------------------------
-- Schema demoniosmv
-- -----------------------------------------------------
-- -----------------------------------------------------
-- Schema demoniosmv
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `demoniosmv` DEFAULT CHARACTER SET utf8 ;
USE `demoniosmv` ;
-- -----------------------------------------------------
-- Table `demoniosmv`.`post`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `demoniosmv`.`post` (
`id` INT NOT NULL,
`title` VARCHAR(200) NULL,
`text` TEXT(1000) NULL,
`created_date` DATETIME NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;
-- -----------------------------------------------------
-- Table `demoniosmv`.`images`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `demoniosmv`.`images` (
`id` INT NOT NULL,
`fk_post` INT NULL,
`img_url` VARCHAR(100) NULL,
PRIMARY KEY (`id`),
INDEX `fk_post_idx` (`fk_post` ASC) VISIBLE,
CONSTRAINT `fk_post`
FOREIGN KEY (`fk_post`)
REFERENCES `demoniosmv`.`post` (`id`)
ON DELETE CASCADE
ON UPDATE NO ACTION)
ENGINE = InnoDB;
SET SQL_MODE=#OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=#OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=#OLD_UNIQUE_CHECKS;
For creating the models I used the insepctdb command, I'm using sqlclient for the MySQL connection, and I'm using Django 2.2.3 with Python 3.7.
I had to delete the files inside migrations and py_cache folders to make it work. All the files except for the init.py files
While creating item I got this error, though I can see category_id at sqlall:
table items_item has no column named category_id
migration commands:
$ python manage.py makemigrations items
No changes detected
$ python manage.py migrate
Running migrations:
No migrations to apply.
model.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=200)
# Create your models here.
class Item(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(null=True, blank=True)
image = models.ImageField(upload_to="item_images")
category = models.ForeignKey(Category)
show_in_front_page= models.BooleanField(default=True)
always_show_in_front_page= models.BooleanField(default=True)
is_trending=models.BooleanField(default=True)
sqlall
# $ python manage.py sqlall items
BEGIN;
CREATE TABLE "items_category" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" varchar(200) NOT NULL
)
;
CREATE TABLE "items_item" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" varchar(200) NOT NULL,
"description" text,
"image" varchar(100) NOT NULL,
"category_id" integer NOT NULL REFERENCES "items_category" ("id"),
"show_in_front_page" bool NOT NULL,
"always_show_in_front_page" bool NOT NULL,
"is_trending" bool NOT NULL
)
;
CREATE INDEX "items_item_6f33f001" ON "items_item" ("category_id");
COMMIT;
admin.py
from django.contrib import admin
# Register your models here.
from .models import Item, Category
admin.site.register(Item)
admin.site.register(Category)
If the category_id column is already in an applied migration file, but hasn't been created in the database., then the easiest fix would be to add the column manually. It's easy to work out the SQL from your sqlall output above.
./manage.py dbshell # open a db shell
# Add the column
ALTER TABLE items_item ADD COLUMN "category_id" integer NOT NULL REFERENCES "items_category" ("id");
# Add the index
CREATE INDEX "items_item_6f33f001" ON "items_item" ("category_id");
try deleting your db.sqlite3 file.
Then run makemigrations and migrate (the sqlite file will generates automatically).
I've written a couple of tests for really simple blog app, but the many to many relationship fails when I run the test: ./manage.py test myblog
DatabaseError: no such table: myblog_post_tag
Yet when I do ./manage.py sql myblog:
BEGIN;
CREATE TABLE "myblog_tag" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(50) NOT NULL
)
;
CREATE TABLE "myblog_post_tag" (
"id" integer NOT NULL PRIMARY KEY,
"post_id" integer NOT NULL,
"tag_id" integer NOT NULL REFERENCES "myblog_tag" ("id"),
UNIQUE ("post_id", "tag_id")
)
;
CREATE TABLE "myblog_post" (
"id" integer NOT NULL PRIMARY KEY,
"title" varchar(200) NOT NULL,
"pub_date" datetime NOT NULL,
"content" text NOT NULL
)
;
COMMIT;
It does create a table, yet it fails to do so while testing? Any help is appreciated.
Here's my test:
class TagModelTest(TestCase):
def test_create_tags_for_posts(self):
# tests tagging posts, postodd will have tags 1 & 3, posteven will be 2 & 4
postodd = Post(
title="testing odd tags",
pub_date=timezone.now(),
content='''hello everybody, we are testing some tagging
functionality here. This post should have odd tags.''',
)
posteven = Post(
title="test even tags",
pub_date=timezone.now(),
content ='''hello everybody, we are testing some tagging
functionality here. This post should have even tags.''',
)
#save them to db
postodd.save()
posteven.save()
# create the tags
tag1 = Tag(name="1")
tag2 = Tag(name="2")
tag3 = Tag(name="3")
tag4 = Tag(name="4")
# save all tags to db
tag1.save()
tag2.save()
tag3.save()
tag4.save()
# create the many2many relationship
postodd.tag.add(tag1)
And my models.py if needed:
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class Post(models.Model):
tag = models.ManyToManyField(Tag)
title = models.CharField(max_length=200)
pub_date = models.DateTimeField(verbose_name="Date published")
content = models.TextField()
def __unicode__(self):
return self.title
./manage.py sql myblog does not execute the SQL, it just outputs what it would execute if you ran syncdb.
In this case, it seems the table is missing from your db.
If this was a result of a modification to an existing app; for example you just added a new field to your model; then running syncdb won't affect the changes to your database. syncdb doesn't do any destructive operations (like adding or dropping tables or columns).
In this case you can manually run the query to add the column; or drop and recreate your tables with syncdb.
Since this is a common problem most people use a data migration tool like south to handle these changes for you. South will manage these small changes intelligently.
I seem to be stuck with creating an initialy deferrable foreign key relationship between two models in Django and using SQLite3 as my backend storage.
Consider this simple example. This is what models.py looks like:
from django.db import models
class Investigator(models.Model):
name = models.CharField(max_length=250)
email = models.CharField(max_length=250)
class Project(models.Model):
name = models.CharField(max_length=250)
investigator = models.ForeignKey(Investigator)
And this is what the output from sqlall looks like:
BEGIN;
CREATE TABLE "moo_investigator" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(250) NOT NULL,
"email" varchar(250) NOT NULL
)
;
CREATE TABLE "moo_project" (
"id" integer NOT NULL PRIMARY KEY,
"name" varchar(250) NOT NULL,
"investigator_id" integer NOT NULL REFERENCES "moo_investigator" ("id")
)
;
CREATE INDEX "moo_project_a7e50be7" ON "moo_project" ("investigator_id");
COMMIT;
"DEFERRABLE INITIALLY DEFERRED" is missing from the *investigator_id* column in the project table. What am I doing wrong?
p.s. I am new to Python and Django - using Python version 2.6.1 Django version 1.4 and SQLite version 3.6.12
This behavior is now the default. See https://github.com/django/django/blob/803840abf7dcb6ac190f021a971f1e3dc8f6792a/django/db/backends/sqlite3/schema.py#L16
Sqlite backend does not add "DEFERRABLE INITIALLY DEFERRED". Check the code