本篇文章首席CTO笔记来给大家介绍有关django如何手动建表以及django 建表的相关内容,希望对大家有所帮助,一起来看看吧。
本文目录一览:
1、django怎样自动创建数据库table2、django orm创建数据表3、django使用已有的数据库表怎么建立model4、我是怎么做到使用django动态定义表单的5、菜鸟求助。django中我想建一个用户表(名,密码),和一个个人信息表(名,头像,出生年月等)。6、django有几种建表方式django怎样自动创建数据库table
;
django创建数据库表方法如下:
catcher:mysite catcher$ python manage.py makemigrations books
Migrations for 'books':
0001_initial.py:
- Create model Author
- Create model Book
- Create model Publisher
- Add field publisher to book
catcher:mysite catcher$ python manage.py sqlmigrate books 0001
BEGIN;
--
-- Create model Author
--
CREATE TABLE "books_author" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "first_name" varchar(30) NOT NULL, "last_name" varchar(40) NOT NULL, "email" varchar(254) NOT NULL);
--
-- Create model Book
--
CREATE TABLE "books_book" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(100) NOT NULL, "publication_date" date NOT NULL);
CREATE TABLE "books_book_authors" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "book_id" integer NOT NULL REFERENCES "books_book" ("id"), "author_id" integer NOT NULL REFERENCES "books_author" ("id"));
--
-- Create model Publisher
--
CREATE TABLE "books_publisher" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "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);
--
-- Add field publisher to book
--
ALTER TABLE "books_book" RENAME TO "books_book__old";
CREATE TABLE "books_book" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(100) NOT NULL, "publication_date" date NOT NULL, "publisher_id" integer NOT NULL REFERENCES "books_publisher" ("id"));
INSERT INTO "books_book" ("publication_date", "publisher_id", "id", "title") SELECT "publication_date", NULL, "id", "title" FROM "books_book__old";
DROP TABLE "books_book__old";
CREATE INDEX "books_book_2604cbea" ON "books_book" ("publisher_id");
COMMIT;
catcher:mysite catcher$
catcher:mysite catcher$ sudo python manage.py migratePassword:Operations to perform: Apply all migrations: admin, contenttypes, books, auth, sessionsRunning migrations: Rendering model states... DONE Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying books.0001_initial... OK Applying sessions.0001_initial... OKcatcher:mysite catcher$
django orm创建数据表
Django里面,管理数据库和sqlarchemy类似,也是通过orm框架来实现的。所有的数据库的建立,都是在model.py里面通过类来实现的。
首先看看如何创建一个单表:
a. 先定义一个类,继承models.Model, 然后根据需求定义参数,这些参数的类型和变量后面会进一步阐述
models.py
from django.db import models
class UserInfo(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=64)
b. 注册app
settings.py
INSTALLED_APPS = [
‘django.contrib.admin‘,
‘django.contrib.auth‘,
‘django.contrib.contenttypes‘,
‘django.contrib.sessions‘,
‘django.contrib.messages‘,
‘django.contrib.staticfiles‘,
‘app01‘,
]
c.执行命令。 第一条命令会生成一个初始化文件,第二个命令会生成对应的表
python manage.py makemigrations
python manage.py migrate
这样,就在PyCharm自带的sqlite数据库里面成功的生成了一个app01_UserInfo的表。这个表默认会有一个自增的id作为主键,另外两个字段是我们通过类创建的。
d. 如果希望使用mysql,因为Django默认使用了MySqldb模块,这个在3.0版本里面不存在,会直接报错。我们需要改为pymysql的模块,方法如下:
在project同名文件夹下的__init__文件中添加如下代码即可:
import pymysql
pymysql.install_as_MySQLdb()
2. 对于单表的增删改查询
查询
获取所有结果,获取到的结果是一个QuerySet的类似列表的对象,每一个元素本身又是一个对象,包括了id,name,password等属性。
obj = models.UserInfo.objects.all()
QuerySet [UserInfo: UserInfo object, UserInfo: UserInfo object, UserInfo: UserInfo object, UserInfo: UserInfo object, UserInfo: UserInfo object]
可以通过filter进行过滤,相当于sql的where语句,因为结果也是QuerySet,因此需要再使用first()获取第一个值
obj = models.UserInfo.objects.filter(id=nid).first()
增加
models.UserInfo.objects.create(username=u,password=p,user_group_id=3)
删除,可以在filter的基础上进行删除
models.UserInfo.objects.filter(id=nid).delete()
修改,有两种常见方式
第一个方式
models.UserInfo.objects.filter(id=nid).update(username=u,password=p)
第二个方式
obj=models.UserInfo.objects.filter(id=nid)
obj.username=u
obj.save()
django使用已有的数据库表怎么建立model
在网上看到都是使用Django的models和makemigration,migrate命令来创建新表,并使用。可是我的数据已经存在了已经创建好,并且已经存储有数据了,不能再重新创建新表了。了解Django的表明和models名称的映射关系就可以让Django使用已经存在的表。
假如在Django存在models如下:
[python] view plain copy
from django.db import models
# Create your models here.
class Sciencenews(models.Model):
id = models.CharField(max_length=36,primary_key=True)
first_module = models.CharField(max_length=30,default="News")
second_module = models.CharField(max_length=30,default="Latest News")
title = models.CharField(max_length=300)
author = models.CharField(max_length=60,null=True)
publish_date = models.CharField(max_length=35,null=True)
content = models.TextField(null=True)
crawl_date = models.CharField(max_length=35,null=True)
from_url = models.CharField(max_length=350,null=True)
执行数据迁移命令:
[python] view plain copy
python manage.py makemigration
python manage.py migrate
会在数据库中生成名称为show_sciencenews的数据表。show为应用名称,此处我的应用名称为show。可以看到Django创建表的命名规则:应用名_模型名。
我的存储爬取到的数据的表格名称原来为science_news,想要Django使用它,而不是创建新的表,只需要把的它的名称改为:应用名_要与该表映射的models名称,在此处我改为show_sciencenews。然后使用如上的数据迁移命令,这时可能会提示数据表已经存在的错误,不用理会,models已经和数据表映射上了。接下来只需要正常使用models和数据表就可以了。
我是怎么做到使用django动态定义表单的
第一节 数据结构
最近的项目开发,用到了这样的数据结构:
主要是来管理设备的.
下面我列一下它简化的结构,不需要更多了,其余的只是多余或者说是锦上添花:
设备分类(相当于设备的大分类)的数据结构:
[python] view plain copy
class Category(models.Model):
name = models.CharField(max_length=40)
具体设备的数据结构:
[python] view plain copy
class Equipment(models.Model):
name = models.CharField(max_length=100)
category = models.ForeignKey(Category, related_name="cg_equip_list")
设备参数的数据结构:
[python] view plain copy
class Characteristic(models.Model):
category = models.ForeignKey(Category, related_name="eq_characteristics")
name = models.CharField(max_length=40)
设备参数的值的数据结构:
[python] view plain copy
class CharacteristicValue(models.Model):
equipment = models.ForeignKey(Equipment, related_name="eq_characteristic_values")
characteristic = models.ForeignKey(Characteristic, related_name="eq_key_values")
value = models.CharField(max_length=100)
可能好多人会问:你怎么不把设备的参数值直接定义到设备的数据结构中去呢?
我的回答就是:这样可以自己定义更多的设备.
每个设备的参数是不一样的,比如说电脑的参数基本上就是:
CPU频率,内存大小,硬盘大小,显示器类型,显示器大小等等.
而打印机的参数可以这样:
最大打印纸张幅面,打印机类型等等.
这样两种有着不同参数的设备该怎么将它们的数据保存至数据库中呢?
按照刚才上面的提问,我们将需要建立2个表,电脑表和打印机表,分别包含相应的参数在列中.这样的话,如果再多一种设备,比如照相机,我们又得多建立一张数据表,而疲于维护数据库了.
但是按照参数与设备分离,以参数表的形式定义各类设备的参数,以外键链接到设备分类表.
再将具体设备的各项参数的值放入参数值表中,就可以保存各个设备的参数了.
参数值的数据表中,一个参数属于哪个设备,主要根据设备的id,和参数的id来确定.
这样的表结构就相对来说比较通用.
比较麻烦的就是,增加一个设备的时候,同时要增加它相应的参数值,它的参数不在设备表中,这样就要通过参数表来查询:
在参数表中,参数的设备分类id=具体设备的所属设备分类id的行就是该设备所拥有的参数.
比如说:
设备分类表中数据:
id name
1 台式计算机
2 打印机
参数在参数表中保存了以下几行数据:
id name category
1 CPU频率 1
2 MAC地址 1
3 内存大小 1
4 显示器大小 1
5 显示器类型 1
6 硬盘大小 1
7 最大打印幅面 2
可以一目了然的看出台式计算机有6个参数,打印机有1个参数.
第二节 解决方案的选用
数据结构搞清楚了,现在的问题是怎么录入这些参数的值呢?
困难在于,每种设备的参数的个数是不确定的,因此,在定义form的时候,我们不能固定的定死form的 field个数,只有动态的增减field的个数.
那么,怎么动态生成一个有不同数目field的form呢?
这里,我的想法就是,既然参数个数保存在数据库中了,那么肯定是要查询数据库来动态生成了.
那么,使用django,该用什么具体的方法呢?
我自己是试过不少的方法的,也是在调试的过程中慢慢找到了解决这个问题的方法.
过程是这样的:
我开始想的解决的方案有:
1.使用ajax来动态的生成form
2.使用admin中的方法,用inline的 方法,在增加一个设备的同时增加几个参数
3.使用formset来制作
4.使用formtools中的formwizard(表单向导)来制作.
问题的困境主要在于参数值的表中有2个外键,所以不好确定该怎么弄.
前面三种方法我仅仅试了一下,调试了一两天就放弃了,主要原因就是:
1.ajax我目前还是不太熟,要想用好它,又得转向去学习一些相关的javascript库,一时半会弄不好.
2.admin中的inline是针对一种数据model的,增加的参数值也是相同的,比如说可能增加成6个CPU参数.而且是用在admin中的,想抠出来自己使用还挺麻烦的.
3.formset中的form也是要求相同的数据模型,但是参数值表中2个外键高的你根本没法使用formset,formset是在简单的数据结构情况下录入数据用的.
formset有一个函数就是add_fields,这个函数比较有用,但是form没有这个函数.了解了原理就简单了,就是form['field_name']=forms.CharField()之类就可以为一个form 实例添加field了.
我觉得formset是可以解决问题的,但是前提是构造formset前,必须提前知道formset中有几个参数值的form在里面(就是要知道某种分类的设备有几个参数,好在formset中构建几个form,CharacteristicValue的form,每个form采用不同的参数来进行初始化initial).
在一个页面中,先增加设备的form,因为设备的参数个数不是固定的,需要动态的增加含有几个参数值表单的formset,这样就可以选择设备的参数了.formset比较适用于使用固定个数的form.所以这样就给使用formset增加了难度,如果要让这种方式能够使用,最终还是要用到ajax来根据用户选择设备类型的时候,动态的生成formset.
formset需要在view中初始化.
所以这种方式我没有采用.
我采用的是表单向导的方式.
django的contrib中提供了formtools,用过了,会用了才觉得真好用.我是看英文文档一点一滴的学会使用的,感觉真的很方便.
但是上面的4的解决方案的实现过程倒是很艰难的.我弄了3天才弄出点眉目来.
第三节 具体的实现
django中表单向导使用起来很简单的.
[python] view plain copy
from django.utils.translation import ugettext_lazy as _
from django import forms
from django.forms.formsets import BaseFormSet
from django.forms.fields import FileField
from django.forms.util import ValidationError
from django.shortcuts import render_to_response
from django.contrib.formtools.wizard import FormWizard
from ddtcms.office.equipment.models import Equipment,Characteristic,CharacteristicValue
class EquipmentForm(forms.ModelForm):
class Meta:
model = Equipment
class CharacteristicValueForm(forms.Form):
def clean(self):
a=self.fields
s=self.data
self.cleaned_data = {}
# 下面的这一段for 是从 django的forms.py中的 full_clean 中复制来的
for name, field in self.fields.items():
# value_from_datadict() gets the data from the data dictionaries.
# Each widget type knows how to retrieve its own data, because some
# widgets split data over several HTML fields.
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
try:
if isinstance(field, FileField):
initial = self.initial.get(name, field.initial)
value = field.clean(value, initial)
else:
value = field.clean(value)
self.cleaned_data[name] = value
if hasattr(self, 'clean_%s' % name):
value = getattr(self, 'clean_%s' % name)()
self.cleaned_data[name] = value
except ValidationError, e:
self._errors[name] = self.error_class(e.messages)
if name in self.cleaned_data:
del self.cleaned_data[name]
#cl=self.cleaned_data
#debug()调试用的,查看cl的值,主要是看self.cleaned_data的值,如果return了,就看不到了
return self.cleaned_data
class EquipmentCreateWizard(FormWizard):
def done(self, request, form_list):
return render_to_response('equipment/done.html',
{
'form_data': [form.cleaned_data for form in form_list],
})
def get_form(self, step, data=None):
"Helper method that returns the Form instance for the given step."
form = self.form_list[step](data, prefix=self.prefix_for_step(step), initial=self.initial.get(step, None))
if step == 1:
if data:
cg = data.get('0-category', 1)
cs = Characteristic.objects.all().filter(category__id=cg)
for c in cs:
form.fields['Characteristic-'+str(c.id)] = forms.CharField(label = c.name)
g=form.fields
#debug()
return form
# 从wizard.py中复制过来进行更改的.
def render(self, form, request, step, context=None):
"Renders the given Form object, returning an HttpResponse."
old_data = request.POST
prev_fields = []
if old_data:
hidden = forms.HiddenInput()
# Collect all data from previous steps and render it as HTML hidden fields.
for i in range(step):
old_form = self.get_form(i, old_data)
hash_name = 'hash_%s' % i
prev_fields.extend([bf.as_hidden() for bf in old_form])
prev_fields.append(hidden.render(hash_name, old_data.get(hash_name, self.security_hash(request, old_form))))
if step == 1:
cg = old_data.get('0-category', 1)
cs = Characteristic.objects.all().filter(category__id=cg)
for c in cs:
form.fields['Characteristic-'+str(c.id)] = forms.CharField(label = c.name)
g=form.fields
#debug()
if step == 2:
debug()
return super(EquipmentCreateWizard, self).render(form, request, step, context=None)
def get_template(self, step):
return 'equipment/wizard_%s.html' % step
EquipmentCreateWizard其实也可以放在views.py中,而且我觉得更合理一点.
在EquipmentCreateWizard 中,我试着修改过process_step 函数,但是得不到正确的结果,后来修改了get_form,都是想从django的formtools的wizard.py中复制过来再进行修改的.
get_form的修改也没有得到正确的结果.后来就修改render函数,在第2步的时候,我将动态参数个数显示出来了.但是到最后结束done的环节,取得的formdata中,第二个form没有数据,就是一个空的{},
于是我又重新修改get_form函数,无非就是判断是不是第二步,然后给第二个form动态添加几个field:
[python] view plain copy
if step == 1:
cg = old_data.get('0-category', 1)
cs = Characteristic.objects.all().filter(category__id=cg)
for c in cs:
form.fields['Characteristic-'+str(c.id)] = forms.CharField(label = c.name)
g=form.fields
#debug()
这段代码在get_form和 render中都有,都是判断是不是第2步,然后就根据第1步中选择的设备的分类来查询到具体的分类,再根据分类来获取该种分类的设备有哪些参数,然后根据参数个数修改form的参数field的个数.
'Characteristic-'+str(c.id)是用来以后保存数据的时候,split这个字符串,得到参数的id,并在参数值表中保存Characteristic-1,Characteristic-2...的value.
g=form.fields
#debug()
用来断点查看参数field有多少个,是否修改成功.
菜鸟求助。django中我想建一个用户表(名,密码),和一个个人信息表(名,头像,出生年月等)。
class User(models.Model):
username = models.CharField(max_length=50,blank=False)
password = models.CharField(max_length=50,blank=False)
class UserInfo(models.Model):
user= models.ForeignKey(User)
address = models.CharField(max_length=50,blank=False)
email = models.CharField(max_length=50,blank=False)
直接通过外键ForeignKey关联
django有几种建表方式
做之前你们需要一个好一点的设计框架,如果要做自己的app,理论上是app中分别建表。最好是保证每个app可以单独使用,不依赖其他的app,既然又有两表联系,那么设计里面应该需要的一个叫做common的模块,将需要共享的数据独立出来供大家调用。
结语:以上就是首席CTO笔记为大家介绍的关于django如何手动建表和django 建表的全部内容了,希望对大家有所帮助,如果你还想了解更多这方面的信息,记得收藏关注本站。