【问题标题】:Does Django allow one to define different set of fields for each document in MongoDB?Django 是否允许为 MongoDB 中的每个文档定义不同的字段集?
【发布时间】:2018-04-11 10:56:36
【问题描述】:

Django 和 MongoDB

支持different set of fields for each document in a collection 是 MongoDB 的功能之一。它允许您在同一个集合中存储相似的数据,但具有不同的属性。

例如:

{
        _id: ObjectId("51156a1e056d6f966f268f81"),
        type: "Article",
        author: "Derick Rethans",
        title: "Introduction to Document Databases with MongoDB",
        date: ISODate("2013-04-24T16:26:31.911Z"),
        body: "This arti…"
},
{
        _id: ObjectId("51156a1e056d6f966f268f82"),
        type: "Book",
        author: "Derick Rethans",
        title: "php|architect's Guide to Date and Time Programming with PHP",
        isbn: "978-0-9738621-5-7"
}

默认情况下,Django 不支持像 mongodb 这样的非关系数据库,但有一些 lib 用于此目的。例如Django MongoDB Engine 是 Django 的 MongoDB 后端。

MongoDB 允许为集合中的每个文档使用不同的字段集,但在 django 中您必须定义 models.py:

from django.db import models

from djangotoolbox.fields import ListField


class Post(models.Model):
    title = models.CharField()
    text = models.TextField()
    tags = ListField()
    comments = ListField()

问题是:在使用 Django 时,有什么方法可以为 MongoDB 集合中的每个文档定义不同的字段集?

【问题讨论】:

    标签: python django mongodb


    【解决方案1】:

    另一种选择

    我喜欢使用django-mongoengine,因为它在处理 MongoDB 模型时更清楚。

    例如,您可以创建将要转换为模型的结构化 Documents 或将在现有模型中使用的结构化文档 EmbeddedDocument 。

    from django_mongoengine import Document, EmbeddedDocument, fields
    
    class Comment(EmbeddedDocument):
        created_at = fields.DateTimeField(
            default=datetime.datetime.now, editable=False,
        )
        author = fields.StringField(verbose_name="Name", max_length=255)
        email  = fields.EmailField(verbose_name="Email")
        body = fields.StringField(verbose_name="Comment")
    
    class Post(Document):
        created_at = fields.DateTimeField(
            default=datetime.datetime.now, editable=False,
        )
        title = fields.StringField(max_length=255)
        slug = fields.StringField(max_length=255, primary_key=True)
        comments = fields.ListField(
            fields.EmbeddedDocumentField('Comment'), blank=True,
        )
    

    答案

    因此,对于您的情况,您需要使用 Dynamic document schemas,它的工作方式与 Document 相同,但也将保存为它们设置的任何数据/属性。

    class Page(DynamicDocument):
        title = StringField(max_length=200, required=True)
    
    # Create a new page and add tags
    >>> page = Page(title='Using MongoEngine')
    >>> page.tags = ['mongodb', 'mongoengine']
    >>> page.save()
    
    >>> Page.objects(tags='mongoengine').count()
    >>> 1
    

    【讨论】:

      【解决方案2】:

      我在用户个人资料页面中遇到了这个问题。这是我的解决方案。

      model.py

      from django.contrib.auth.models import User
      from django.db import models
      from django.core.validators import RegexValidator
      
      # Create your models here.
      class Profile(models.Model): 
      
      
          
          user = models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True,related_name="user_profile")
          fullname = models.CharField(max_length=100,verbose_name="full name")     
          about = models.CharField(max_length=300,blank=True,null=True)
          hobies = models.CharField(max_length=200,blank=True)
          recent_aktivity = models.CharField(max_length=150,verbose_name="recent activity",null=True)
          photo = models.ImageField(blank=True,null=True,upload_to="images/")
          recent_badges = models.CharField(max_length=100,verbose_name="recent badges",null=True)
          phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
          phone_number = models.CharField(validators=[phone_regex], max_length=17, blank=True,null=True,verbose_name="phone number") 
          website_url = models.URLField(blank=True,null=True,verbose_name="company website")
          projects =models.CharField(max_length=200,blank=True,null=True)
          bio = models.CharField(max_length=300,blank=True,null=True)
          
          
          
          def __str__(self):
              return f'{self.user.username}-ProfileModel'
      

      signals.py

      from django.db.models.signals import post_save
      from django.dispatch import receiver
      from django.contrib.auth.models import User
      from .models import Profile
      
      @receiver(post_save,sender=User)
      def update_user_profile(sender,instance,created,**kwargs):
          if created:
              profile = Profile.objects.create(user =instance)
      

      app.py

      from django.apps import AppConfig
      
      
      class ProfileConfig(AppConfig):
          default_auto_field = 'django.db.models.BigAutoField'
          name = 'Profile'
      
          def ready(self):
              import Profile.signals
      

      forms.py

      from django import forms
      from.models import Profile
      
      
      
      class ProfileForm(forms.ModelForm):   
              
          
            class Meta:
                model = Profile
                fields = '__all__'
                exclude = ['user']
      

      views.py

       from django.contrib import messages
          from django.contrib.auth.decorators import login_required
          from django.http import HttpResponseRedirect
          from django.urls.base import reverse
          from .forms import ProfileForm
          from .models import Profile
          from django.shortcuts import redirect, render,get_object_or_404
          from django.contrib.auth import update_session_auth_hash
          from django.contrib.auth.forms import PasswordChangeForm
          
          login_required(login_url="user:login")
          def dashboard(request):
              return render(request,"dashboard.html")
          
          
          @login_required(login_url="user:login")
          def get_profile(request):    
              
              profile = get_object_or_404(Profile,user=request.user)
              
          return render(request,"profile.html",{"profile":profile})
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-21
        • 2016-04-23
        • 2014-10-12
        • 1970-01-01
        • 2011-12-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多