1.一对一表的查询操作(OneToOneField)
上篇中记录了一对一表,card和cardInfo表的创建关联,使用inlines内联显示。
Django框架除了在views.py中操作models外,还可以从shell模式下进行数据库的操作。
进入shell模式,在manage.py目录下执行
python3 manage.py shell
>>> from hello.models import Card,CardDetail
>>> c = Card.objects.create(card_id='5555',card_user='hanlei')
>>> c.save()
>>> d = CardDetail.objects.create(card=c,tel='110',mail='1@qqq.com',city='上海',address='松江')
>>> d.save()
新增一个card和carddetail表数据
数据查询:1.根据c和d对象查询属性信息:
>>> c.card_id
'5555'
>>> c.card_user
'hanlei'
>>> d.city
'上海'
>>> d.address
'松江'
2.根据card查询carddetail和根据carddetail查询card信息
>>> c.carddetail.mail
'1@qqq.com'
>>> d.card.card_user
'hanlei'
>>>
另外如果想让card表界面显示carddetail信息,需要自己修改list_display列表
@admin.register(models.Card)
class ControlCard(admin.ModelAdmin):
list_display = ["card_id", "card_user", "add_time","phone","city"]#增加phone和city两个字段
# 在Card页面显示更多信息CardDetail
inlines = [MoreInfo]
#新增方法,可以在card界面显示carddetail中phone字段信息
def phone(self, obj):
return obj.carddetail.tel
# 新增方法,可以在card界面显示carddetail中city字段信息
def city(self, obj):
return obj.carddetail.city
2.一对多表查询操作(ForignKey)
新增一条bank和cardinfo信息,可以根据card_info查询对应的bank信息,但是不能直接根据bank查询cardinfo信息
因为cardinfo中关联了info,而bank中没有关联card_info,这也是不能进行关联的,因为一个银行下可以有多个银行卡
>>>from hello.models import Bank,CardInfo
>>> b = Bank.objects.create(bank_name='招商银行',city='北京',point='海淀')
>>> b.save
<bound method Model.save of <Bank: 招商银行>>
>>> card_info =CardInfo.objects.create(card_id='88888',card_name='小强',info=b)
>>> card_info.save
<bound method Model.save of <CardInfo: 88888>>
>>> b.city
'北京'
>>> card_info.card_name
'小强'
>>> card_info.info.bank_name
'招商银行'
>>> card_info.info.city
'北京'
>>>
反向查询当ForeignKey没设置related_name参数,默认是通过关联表的名称加_set去查询
>>> b.cardinfo_set.all()[0].card_id
'88888'
>>>
当CardInfo表的外键(ForeignKey)只有一个时,可以通过_set去查询到,当有多个外键时,就无法查询具体哪个外键了,这时候就需要加个related_name参数。
class CardInfo(models.Model):
'''卡信息'''
card_id = models.CharField(max_length=30, verbose_name="卡号")
card_name = models.CharField(max_length=10, verbose_name="姓名")
# 增加外键,新增related_name参数related_name参数相当于给这个外键取了个别名,方便多个外键时候去识别
info = models.ForeignKey(Bank, on_delete=models.CASCADE, verbose_name="选择银行",related_name='card_bank')
class Meta:
verbose_name_plural = '卡号信息'
def __str__(self):
return self.card_id
E:\Django_project\helloword>python3 manage.py shell
Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:06:47) [MSC v.1914 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
>>> from hello.models import Bank,CardInfo
>>> b = Bank.objects.all()
>>> b
<QuerySet [<Bank: 中国工商银行>, <Bank: 中国农业银行>, <Bank: 招商银行>]>
>>> b[2].card_bank.all()[0].card_id
'88888'
>>>
3.多对多表查询(ManyToManyField)
多对多表的查跟一对多表的查询一致
作者表与书籍表的对应于多对多表
添加书籍表时,不能直接像如下添加
>>> from hello.models import Auther,Book
>>> a = Auther.objects.create(name='樊登',mail='aa.com',city='上海')
>>> a.save()
>>> a.save
<bound method Model.save of <Auther: 樊登>>
>>> b = Book.objects.create(book_name='看见',auth=a)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "C:\Python\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Python\lib\site-packages\django\db\models\query.py", line 420, in create
obj = self.model(**kwargs)
File "C:\Python\lib\site-packages\django\db\models\base.py", line 496, in __init__
_setattr(self, prop, kwargs[prop])
File "C:\Python\lib\site-packages\django\db\models\fields\related_descriptors.py", line 538, in __set__
% self._get_set_deprecation_msg_params(),
TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use auth.set() instead.
可以先添加一个不包含auth字段的book对象,然后通过book.auth.add()方法添加
>>> b = Book.objects.create(book_name='看见')
>>> b.save()
>>> b.auth.add(a)
或者知道auth对应id可以添加id
b.auth.add(1),1为a在表中的id,add方法可以添加多个id或对象,b.auth.add(1,2),b.auth.add(a1,a2),a1,a2为auther对象
查询时候,b.auth.all()返回的是一个qureyset,可遍历取出每一个Auther
通过Auther查询book时,与一对多的反向查询一致,auther.book_set.all()或根据related_name进行查询
auther.book_auth.all()