如何通过在非唯一列上将Django模型与其他模型连接来进行查询?

时间:2019-06-17 18:27:29

标签: django django-models orm

在django项目中的models.py文件中有以下模型

from django.contrib.auth.models import AbstractUser
from django.db import models
from django.conf import settings

class CustomUser(AbstractUser):
    pass
    # add additional fields in here

class PDFForm(models.Model):

    pdf_type=models.IntegerField(default=0)
    pdf_name=models.CharField(max_length=100,default='')
    file_path=models.FileField(default='')  

class FormField(models.Model):

    fk_pdf_id=models.ForeignKey('PDFForm', on_delete=models.CASCADE,default=0)
    field_type=models.IntegerField(default=0)
    field_page_number=models.IntegerField(default=0)
    field_x=models.DecimalField(max_digits=6,decimal_places=2,default=0)
    field_y=models.DecimalField(max_digits=6,decimal_places=2,default=0)
    field_x_increment=models.DecimalField(max_digits=6,decimal_places=2,default=0)
    class Meta:
        ordering= ("field_page_number", "field_type")

class UserData(models.Model):

    fk_user_id=models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,default=0)
    field_type=models.IntegerField(default=0)
    field_text=models.CharField(max_length=200,default='')
    field_date=models.DateField()

这是模型之间的关联方式

1)pdfform包含pdf表单和文件系统上的路径

2)pdfform中包含多个FormField。每个字段都有属性,正在讨论的具体字段是field_type

3)UserData模型具有用户的数据,因此一个用户可以在此表中具有多行。该模型还具有field_type列。

我要查询的是找出UserData模型中存在的所有行,这些行存在于FormField模型中(与field_type匹配)并且是特定的PDFForm。

鉴于Django模型中的多对多关系不可能在没有唯一字段的情况下发生,如何进行如下查询

select a.*, b.* from FormField a, UserData b where b.fk_user_id=1 and a.fk_pdf_id=3 and a.field_type=b.field_type

我一直在用细齿梳仔细阅读文档,但是显然缺少django如何创建联接。使上述sql语句发生的方式是什么,所以我得到了所需的数据集?

1 个答案:

答案 0 :(得分:2)

我认为UserData缺少与FormField的关系,但是如果您有此关系,则可以这样做:

  UserData.objects.filter(
    fk_user_id=1, # Rename this to user, Django wilt automicly create a user_id column
    form_field__in=FormField.objects.filter(
      fk_pdf_id=<your pdfid>  # same as fk_user_id 
    )
  )

编辑更新的模型

使用ForeignKey时,不必指定_id或default = 0,如果您不总是希望填写该字段,最好设置null=Trueblank=True

from django.contrib.auth.models import AbstractUser
from django.db import models
from django.conf import settings

class CustomUser(AbstractUser):
    pass
    # add additional fields in here

class FieldTypeMixin:
    TYPE_TEXT = 10
    TYPE_DATE = 20

    TYPE_CHOISES = [
        (TYPE_TEXT, 'Text'),
        (TYPE_DATE, 'Date'),
    ]

    field_type=models.IntegerField(default=TYPE_TEXT, choises=TYPE_CHOISES)

class PDFForm(models.Model):
    pdf_type = models.IntegerField(default=0)
    pdf_name = models.CharField(max_length=100,default='')
    file_path = models.FileField(default='')  

class FormField(models.Model, FieldTypeMixin):
    pdf_form = models.ForeignKey('PDFForm', on_delete=models.CASCADE)
    field_page_number = models.IntegerField(default=0)
    field_x = models.DecimalField(max_digits=6,decimal_places=2,default=0)
    field_y = models.DecimalField(max_digits=6,decimal_places=2,default=0)
    field_x_increment = models.DecimalField(max_digits=6,decimal_places=2,default=0)

    class Meta:
        ordering = ("field_page_number", "field_type")

class SubmittedForm(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, models.CASCADE)
    pdf_form = models.ForeignKey(PDFForm, models.CASCADE)

class SubmittedFormField(models.Model, FieldTypeMixin):
    submitted_form = models.ForeignKey(SubmittedForm, models.CASCADE)
    form_field = models.ForeignKey(FormField, models.CASCADE, related_name='fields')

    field_text = models.CharField(max_length=200,default='')
    field_date = models.DateField()

    class Meta:
        unique_together = [
            ['submitted_form', 'form_field']
        ]