【问题标题】:Django - How to save model objects in another model?Django - 如何将模型对象保存在另一个模型中?
【发布时间】:2022-10-14 02:43:17
【问题描述】:

假设我有这两个模型(在 models.py 文件中):

class FullName (models.Model):
    firstName = models.CharField(max_length=30,null=True,blank=False,unique=True)
    lastName = models.CharField(max_length=30,null=True,blank=False,unique=True)

class Address (models.Model):
    addressLine = models.CharField(max_length=30,null=True,blank=False)
    city = models.CharField(max_length=30,null=True,blank=False)
    state = models.CharField(max_length=30,null=True,blank=False)
    zipcode = models.CharField(max_length=30,null=True,blank=False)

如何将这两个模型合并到一个新模型中但具有相同的 ID?所以它变成:

class FullName (models.Model):
    firstName = models.CharField(max_length=30,null=True,blank=False,unique=True)
    lastName = models.CharField(max_length=30,null=True,blank=False,unique=True)

class Address (models.Model):
    addressLine = models.CharField(max_length=30,null=True,blank=False)
    city = models.CharField(max_length=30,null=True,blank=False)
    state = models.CharField(max_length=30,null=True,blank=False)
    zipcode = models.CharField(max_length=30,null=True,blank=False)

class AllInformation (models.Model):
    firstName = models.CharField(max_length=30,null=True,blank=False,unique=True)
    lastName = models.CharField(max_length=30,null=True,blank=False,unique=True)
    addressLine = models.CharField(max_length=30,null=True,blank=False)
    city = models.CharField(max_length=30,null=True,blank=False)
    state = models.CharField(max_length=30,null=True,blank=False)
    zipcode = models.CharField(max_length=30,null=True,blank=False)

    (all fields should be inherited from FullName and Address models)

PS:在我的 views.py 文件中,我调用了这样的保存方法:

fullNameData = FullName(request.POST)
fullNameData.save()
        and
AddressData = Address(request.POST)
AddressData.save()

在此先感谢,我真的很感谢谁回答了这个问题,因为我看到很多人都有同样的问题。我还从 django docs 中查看了 OneToOneField,但说实话我什么都不懂 xD

【问题讨论】:

    标签: python django


    【解决方案1】:

    一对一可能是要走的路,它只是一个外键,所以你在数据库中没有重复的数据

    你的模型看起来像这样

    class AllInformation(models.Model):
        fullname = models.OneToOneField(FullName, on_delete=models.CASCADE)
        address = models.OneToOneField(Address, on_delete=models.CASCADE)
    

    然后您在视图中的保存方法将如下所示:

    # save the full name
    fullNameData = FullName(request.POST)
    fullname = fullNameData.save()
    
    # save the address
    AddressData = Address(request.POST)
    address = AddressData.save()
    
    # create the information 'connector'
    informationObj = AllInformation.objects.create(fullname=fullname, address=address) 
    
    # example uses
    informationObj.fullname.firstName 
    informationObj.fullname.lastName 
    informationObj.address.city 
    

    就我个人而言,我只是将所有三个组合成一个单一的形式,例如:

    表格.py
    from django import forms
    # + import all 3 models
    
    # Note: NOT a model form, this is Custom Form so it can handle more than 1 model
    class InformationForm(forms.Form):
    
        # I Made some fields required so a form submit will always create both a FullName + Address Object
        # - else it's extra code to handle that + I assume you want both anyways
    
        firstName = forms.CharField(required=True)
        lastName = forms.CharField(required=True)
    
        addressLine = forms.CharField(required=True)
        city = forms.CharField()
        state = forms.CharField()
        zipcode = forms.CharField()
    
        def __init__(self,  *args, **kwargs):
            # Holds Obj if it's an Edit Form (needs to pop here as super() doesn't like it)
            self.instance = kwargs.pop('instance') if 'instance' in kwargs else None
    
            super(InformationForm, self).__init__(*args, **kwargs)
    
            if self.instance:
                # is an edit form, set initial fields
                self.initial = {
                    'firstName': instance.fullname.firstName, 
                    'lastName': instance.fullname.lastName, 
                    'addressLine': instance.address.addressLine,
                    'city': instance.address.city,
                    'state': instance.address.state,
                    'zipcode': instance.address.zipcode,
                }
    
            # Add HTML attributes / HTML Validation
            self.fields['firstName'].widget.attrs={'maxlength': '30'}
            self.fields['lastName'].widget.attrs={'maxlength': '30'}
    
            self.fields['addressLine'].widget.attrs={'maxlength': '30'}
            self.fields['city'].widget.attrs={'maxlength': '30'}
            self.fields['state'].widget.attrs={'maxlength': '30'}
            self.fields['zipcode'].widget.attrs={'maxlength': '30'}
    
        def is_valid(self):
            valid = super(InformationForm, self).is_valid()
    
            # Check for Duplicates!
    
            if FullName.objects.filter(firstName= self.cleaned_data.get('firstName'), lastName= self.cleaned_data.get('lastName')).first():
                self.add_error('firstName', 'FullName Already Exists')
                self.add_error('lastName', 'FullName Already Exists')
                valid = False
    
            if Address.objects.filter(
                addressLine = self.cleaned_data.get('addressLine'),
                city = self.cleaned_data.get('city'),
                state = self.cleaned_data.get('state'),
                zipcode = self.cleaned_data.get('zipcode')
                ).first():
                self.add_error('addressLine', 'Address Already Exists')
                self.add_error('city', 'Address Already Exists')
                self.add_error('state', 'Address Already Exists')
                self.add_error('zipcode', 'Address Already Exists')
                valid = False
            return valid
    
        def save(self):
            # There is no .save(commit=False) method with this form.
    
            if self.instance:
                # is an edit form
    
                self.instance.fullname.firstName = self.cleaned_data.get('firstName'),
                self.instance.fullname.lastName = self.cleaned_data.get('lastName'),
                self.instance.fullname.save()
    
                self.instance.address.addressLine = self.cleaned_data.get('addressLine'),
                self.instance.address.city = self.cleaned_data.get('city'),
                self.instance.address.state = self.cleaned_data.get('state'),
                self.instance.address.zipcode = self.cleaned_data.get('zipcode'),
                self.instance.address.save()
    
                return self.instance
            else:
                # is a new form
    
                fullNameObj = FullName.objects.create(
                    firstName = self.cleaned_data.get('firstName'),
                    lastName = self.cleaned_data.get('lastName'),
                )
                addressObj = Address.objects.create(
                    addressLine = self.cleaned_data.get('addressLine'),
                    city = self.cleaned_data.get('city'),
                    state = self.cleaned_data.get('state'),
                    zipcode = self.cleaned_data.get('zipcode'),
                )
    
                informationObj = AllInformation.objects.create(
                    fullname=fullNameObj, address=addressObj
                ) 
            return informationObj
    
    视图.py
    from django.shortcuts import render, redirect, get_object_or_404
    # + import form & AllInformation
    
    def informationFormView(request, pk=None):
    
        # This being None = New Form
        informationObj = None
    
        if pk:
            informationObj = get_object_or_404(AllInformation, pk=pk)
    
        infoform = InformationForm(data=request.POST or None, instance=informationObj)
    
        if request.method == 'POST':
            if infoform.is_valid():
                infoform.save()
    
                redirect('success')
    
            # on not valid it'll re-render the page with errors 
    
        data = {
            'obj': informationObj
            'form': infoform,
        }
        return render(request, 'informationForm.html', data)
    
    网址.py
    from django.urls import path
    from . import views
    
    urlpatterns = [
    
        # Two URLs -> 1 View
        path('informationform', views.informationFormView, name='informationFormView'),
        path('informationform/<int:pk>', views.informationFormView, name='informationFormView'),
    
        ]
    
    信息表格.html
    • 从文档中提取的基本表单,更改了操作以处理编辑
    <form action="{% if obj %}{% url 'informationFormView' pk=obj.pk %}{% else %}{% url 'informationFormView' %}{% endif %}" method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit" value="Submit">
    </form>
    

    【讨论】:

      【解决方案2】:

      解决方案:

      提交 FullName 表单时,我只是这样做:

      data = AllInformation(firstName = request.POST.get("firstname"), lastName = request.POST.get("lastname"))
      data.save()
      

      然后在提交地址表单时的第二个函数中,我只是这样做:

      AllInformation.objects.filter(firstName=the first name got from FullName Form).update(addressLine = value, city = value, ... )
      

      希望它可以帮助任何试图将两个(或更多)模型合并到另一个模型中的人,该模型应该包含所有以前的模型字段。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-18
        • 2015-02-27
        • 1970-01-01
        • 2019-06-23
        • 1970-01-01
        • 2021-03-26
        • 1970-01-01
        • 2021-03-24
        相关资源
        最近更新 更多