Django model relationship field

Django 的 ORM 有多种关系:一对一,多对一,多对多。

各自定义的方式为 :
       一对一: OneToOneField
       多对一: ForeignKey
       多对多: ManyToManyField
  • OneToOneField:

    用来定义一对一关系。笼统地讲,它与声明了 unique=True 的 ForeignKey 非常相似,不同的是使用反向关联的时候,得到的不是一个对象列表,而是一个单独的对象。

    在某个 model 扩展自另一个 model 时,这个字段是非常有用的;例如: 多表继承 (Multi-table inheritance) 就是通过在子 model 中添加一个指向父 model 的一对一关联而实现的。

    必须给该字段一个参数:被关联的 model 类。工作方式和 ForeignKey 一样,连 递归关联 (recursive) 和 延后关联 (lazy) 都一样。

    此外,OneToOneField 接受 ForeignKey 可接受的参数,只有一个参数是 OnetoOneField 专有的:

    OneToOneField.parent_link

    如果为 True ,并且作用于继承自某个父 model 的子 model 上(这里不能是延后继承,父 model 必须真实存在),那么该字段就会变成指向父类实例的引用(或者叫链接),而不是象其他 OneToOneField 那样用于扩展父类并继承父类属性。

  • ForeignKey:

    这是一个多对一关系。必须为它提供一个位置参数:被关联的 model 类。

    要创建递归关联时–与对象自己做多对一关系,那就使用 models.ForeignKey('self') 。

    如果你要与某个尚未定义的 model 建立关联 ,就使用 model 的名称,而不是使用 model 对象本身:

    class Car(models.Model):
        manufacturer = models.ForeignKey('Manufacturer')
        # ...
    
    class Manufacturer(models.Model):
        # ...

    要与其他应用中的 model 相关联,你要用完整的应用标签来显式地定义关联。例如,如果上面的 Manufacturer model 定义在另外一个名为 production 的应用中,你只要用:

    class Car(models.Model):
        manufacturer = models.ForeignKey('production.Manufacturer')

    在解决两个应用双向依赖时,这种引用方法非常有用。

  • ManyToManyField:

OneToOneField和ForeignKey的差别:

举个例子:

有两个配件表,一个是车轮表,另一个是引擎表。两个表都有一个car字段,表示该配件对应的车。
对于车轮来说,多个对应一个car的情况很正常,所以car字段应该用ForeignKey来表示。
对于引擎来说,一个引擎只可能对应一个car,所以必须用OneToOneField。


OneToOneField(someModel) 可以理解为 ForeignKey(SomeModel, unique=True)。

Model Code

from django.db import models

class Engine(models.Model):
    name = models.CharField(max_length=25)

    def __unicode__(self):
        return self.name

class Car(models.Model):
    name = models.CharField(max_length=25)
    engine = models.OneToOneField(Engine)

    def __unicode__(self):
        return self.name

class Engine2(models.Model):
    name = models.CharField(max_length=25)

    def __unicode__(self):
        return self.name

class Car2(models.Model):
    name = models.CharField(max_length=25)
    engine = models.ForeignKey(Engine2, unique=True)

    def __unicode__(self):
        return self.name

  

OneToOneField Example

>>> from testapp.models import Car, Engine
>>> c = Car.objects.get(name='Audi')
>>> e = Engine.objects.get(name='Diesel')
>>> e.car  #engine 的model 定义中并没有car,这个是自动生成的,用关联表的类名小写直接访问
<Car: Audi>  # 注意返回内容的不同

  

ForeignKey with unique=True Example

>>> from testapp.models import Car2, Engine2
>>> c2 = Car2.objects.get(name='Mazda')
>>> e2 = Engine2.objects.get(name='Wankel')
>>> e2.car2_set.all()   # 在未定义的model中用关联表类名小写加"_set"来访问,多对多也一样
[<Car2: Mazda>]   #注意返回内容的不同,这里是一个QuerySet

 以上摘自:http://blog.chinaunix.net/uid-21633169-id-4322473.html

     http://blog.163.com/soyking@126/blog/static/162125251201310211148544/

     http://www.redicecn.com/html/blog/Django/2011/0503/271.html  

另:model中FileField字段

FileField

class FileField(upload_to=None[, max_length=100, **options])

文件上传字段

注意

该字段不支持 primary_key 和 unique 参数,否则会抛出 TypeError 异常。

它有一个必须的参数:

FileField.upload_to 用于保存文件的本地文件系统。它根据 MEDIA_ROOT 设置确定该文件的 url 属性。该路径可以包含 时间格式串 (strftime formatting),可以在上传文件的时候替换成当时日期/时间(这样,就不会出现在上传文件把某个目录塞满的情况了)。该参数也可以是一个可调用项,比如是一个函式,可以调用函式获得包含文件名的上传路径。这个可调用项必须要接受两个参数,并且返回一个保存文件用的 Unix-Style 的路径(用 / 斜杠)。两个参数分别是:

参数描述
instance 定义了当前 FileField 的 model 实例。更准确地说,就是以该文件为附件的 model 实例。大多数情况下,在保存该文件时, model 实例对象还并没有保存到数据库,这是因为它很有可能使用默认的AutoField,而此时它还没有从数据库中获得主键值。(用法见oteam的http://oteam.cn/2008/10/4/dynamic-upload-paths-in-django/)
filename 上传文件的原始名称。在生成最终路径的时候,有可能会用到它。

还有一个可选的参数:

FileField.storage 负责保存和获取文件的对象。详见 Managing files。

Django 管理后台使用 <input type="file"> (一个文件上传的部件) 来表示这个对象。

在 model 中使用 FileField 或 ImageField (稍后会提到) 要按照以下的步骤:

  1. 在项目配置文件中,你要定义 MEDIA_ROOT ,将它的值设为用来存放上传文件的目录的完整路径。(基于性能的考虑,Django 没有将文件保存在数据库中。) ,然后定义 MEDIA_URL ,将它的值设为表示该目录的网址。要确保 web 服务器所用的帐号拥有对该目录的写权限。
  2. 在 model 里面添加 FileField 或 ImageField ,并且确认已定义了 upload_to 项,让 Django 知道应该用 MEDIA_ROOT 的哪个子目录来保存文件。
  3. 存储在数据库当中的仅仅只是文件的路径(而且是相对于 MEDIA_ROOT 的相对路径)。你可能已经想到利用 Django 提供的 url 这个方便的函式。举个例子,如果你的ImageField 名称是 mug_shot,那么你可以在模板中使用 {{ object.mug_shot.url }} ,就能得到图片的完整网址。

例如,假设你的 MEDIA_ROOT 被设为 '/home/media',upload_to 被设为 'photos/%Y/%m/%d'。 upload_to 中的 '%Y/%m/%d' 是一个 时间格式字符串 (strftime formatting); '%Y'是四位的年分,'%m' 是两位的月分, '%d' 是两位的日子。如果你在2007年01月15号上传了一个文件,那么这个文件就保存在 /home/media/photos/2007/01/15 目录下。

如果你想得到上传文件的本地文件名称,文件网址,或是文件的大小,你可以使用 name, url 和 size 属性;详见 管理文件 (Managing files)。

注意:在上传文件时,要警惕保存文件的位置和文件的类型,这么做的原因是为了避免安全漏洞。对每一个上传文件都要验证,这样你才能确保上传的文件是你想要的文件。举个例子,如果你盲目地让别人上传文件,而没有对上传文件进行验证,如果保存文件的目录处于 web 服务器的根目录下,万一有人上传了一个 CGI 或是 PHP 脚本,然后通过访问脚本网址来运行上传的脚本,那可就太危险了。千万不要让这样的事情发生!

默认情况下,FileField 实例在数据库中的对应列是 varchar(100) ,和其他字段一样,你可以利用 max_length 参数改变字段的最大长度。

   摘自:http://blog.chinaunix.net/uid-21633169-id-4322473.html

原文地址:https://www.cnblogs.com/songbird/p/5198182.html