Django-保存嵌套记录

时间:2019-01-05 11:38:55

标签: python django

我想在Django中创建一个嵌套对象模型。 例如

学生:

{
  name: 'Tom',
  age: 18,
  contact: {
    phone_num: 12345678,
    email: tom12345678@gmail.com
  }
}

如何创建它?我尝试使用抽象模型,但这不是我的需要。

class Contact(models.Model):
   phone_num = models.IntegerField()
   email = models.TextField()
   class Meta:
     abstract = True

class Student(Contact):
  name = models.TextField()
  age = models.IntegerField()

当我另存为:

student = Student(name='Tom', age=18, phone_num=12345678, email=tom12345678@gmail.com)

它返回:

{
  name: 'Tom',
  age: 18,
  phone_num: 12345678,
  email: tom12345678@gmail.com
}

如何在联系人下放置phone_num和电子邮件?

2 个答案:

答案 0 :(得分:0)

对于框架来说,返回这样的结果是正常的,因为这是它与这类关联(使用抽象模型)一起工作的默认方式。当您从抽象(abstract = true)模型继承时,对于您的情况-Contact,子级会自动“获取”其所有属性。

如果您想在ContactStudent之间建立嵌套连接,则可能需要one to one relationship

class Contact(models.Model):
    phone_num = models.IntegerField()
    email = models.TextField()

    # Contact now stops being abstract
    # because we use it for relationship

class Student(models.Model):
    name = models.TextField()
    age = models.IntegerField()

    contact = models.OneToOneField(Contact)
    # ____________________^

考虑到这一点,您现在可以将模型另存为:

contact = Contact(phone_num=12345678, email='tom12345678@gmail.com')

student = Student(name='Tom', age=18, contact=contact)

最后,我们写的最后一行的结果将是您想要的结果:

{
  name: 'Tom',
  age: 18,
  contact: {
    phone_num: 12345678,
    email: 'tom12345678@gmail.com'
  }
}

编辑

使用 Django REST Framework

  1. 首先,通过PIP安装它:

pip install django-rest-framework

  1. 然后将其添加到settings.py

  2. 中的INSTALLED_APPS中
  3. serializers.py中创建序列化器:

    from rest_framework import serializers
    
    from .models import Contact, Student
    
    
    class ContactSerializer(serializers.ModelSerializer):
        class Meta:
            model = Contact
            fields = ('id', 'email', 'phone_num')
    
    
    class StudentSerializer(serializers.ModelSerializer):
        contact = ContactSerialiezr()
        # Here is where the magic happens
        # You use *nested serialization* to get the desired result
    
        class Meta:
            model = Student
            fields = ('id', 'name', 'age', 'contact') 
    
  4. 最后,将您的对象序列化为JSON:

    >>> contact = Contact(phone_num=12345678, email='tom12345678@gmail.com')
    
    >>> student = Student(name='Tom', age=18, contact=contact)
    
    >>> serializer = StudentSerialize(student)
    
    >>> serializer.data
    # {
    #     'id': 1,
    #     'name': 'Tom',
    #     'age': 18,
    #     'contact': {
    #         'id': 1,
    #         'email': 'tom12345678@gmail.com',
    #         'phone_num': 12345678
    #     }
    # }
    

有关嵌套序列化-here的更多信息。

答案 1 :(得分:0)

您的示例是一种称为Abstract class inheritance的继承。这样,您将创建一个包含来自父级和子级所有字段的模型。

如果需要两个不同的表,只需使用与Contactclass Student(Contact): name = models.TextField() age = models.IntegerField() contact = models.OneToOneField(Contact, on_delete=models.CASCADE) class Contact(models.Model): phone_num = models.IntegerField() email = models.TextField() 相关的ForeignKey。您有几种方法:

一名学生只有一位联系人。

class Student(Contact):
    name = models.TextField()
    age = models.IntegerField()
    contact = models.ForeignKey(Contact, on_delete=models.CASCADE)

class Contact(models.Model):
   phone_num = models.IntegerField()
   email = models.TextField()

一个学生只有一个联系人,该联系人可以重复使用。

class Student(Contact):
    name = models.TextField()
    age = models.IntegerField()
    contacts = models.ManyToManyField(Contact)

class Contact(models.Model):
   phone_num = models.IntegerField()
   email = models.TextField()

一个学生可以出于多个目的使用多个联系人,并且可以重复使用联系人表。

class Student(Contact):
    name = models.TextField()
    age = models.IntegerField()

class Contact(models.Model):
   phone_num = models.IntegerField()
   email = models.TextField()
   student = models.ForeignKey(Student, related_name="contacts")

一个学生可以有多个联系人,并且联系人表不能重复使用。

Future<int> addShoppingList(String listName) async {
    var dbClient = await db;
    String now = new DateTime.now().toString();
    await dbClient.transaction((txn) async {
      int res = await txn.rawInsert("insert into lists(list_name,list_created_at) values(\'$listName\',\'$now\')");
      print('result of adding a new shopping list: $res');
      return res;
    });
    List<Map> resList = await dbClient.rawQuery("select list_id from lists where list_name=\'$listName\'");
    if (resList.length > 0) {
      return resList[0]['list_id'];
    }
    return 0;
    //await dbClient.rawInsert("insert into lists(list_name,list_created_at) values(\'$listName\',\'$now\')");
  }

  Future<int> addShoppingListItems(int listId, Map<String,String> listItems) async {
    var dbClient = await db;
    int res = 0;

    listItems.forEach((itemName, quantity) async{
      int itemId = await getItemId(itemName);
      print('adding item $itemName with id $itemId');
      await dbClient.transaction((txn) async {
        res = await txn.rawInsert("insert into list_items values($listId,$itemId,\'$quantity\')");
        print('result of adding item in list_items: $res');
      });
      return res;
    });
    return 0;
  }

  Future<int> addItemsToShoppingList(String listName, Map<String,String> listItems) async {
    int listId = await getListId(listName);
    if (listId == 0) {
      listId = await addShoppingList(listName);
      print('got list id of $listId after adding new list');
    }
    print('in additemstoshoppinglist list id: $listId');
    print('in additemstoshoppinglist  ${listItems.toString()}');
    int res = await addShoppingListItems(listId, listItems);
    print('result after adding item in addItemsToShoppingList: $res');
    return res;
  }