如何使用包含 FK 和 M2M 关系的模型创建 DjangoModel 表单

问题描述 投票:0回答:1

我看过单独讨论此场景的帖子,但它们似乎很旧,使用旧文档。我在这里想知道是否有新的修复。另外,我对 django 还比较陌生,而且它们非常令人困惑。


我想创建一个包含相关信息的表单,以便能够创建停车位对象。

这是Forms.py

    class AddParkingSpace(forms.ModelForm):
        class Meta:
            model = ParkingSpace
            fields = [ "__all__"]
            exclude = ["reviews","seller_account"]

            # widgets to include all the fields like fields not in the specified model above (explained below)
            widgets = {


            }

我已排除评论,因为这些评论将在提交评论时添加到停车位对象中。 seller_account将被添加到视图(后端)的停车位中。


使用此表单,我希望能够使用模板中的 Django 语法

{{formname.fieldname}}
单独访问每个字段。这样我就可以按照自己的意愿设计/定位它


我 模型.py

class ParkingSpace(models.Model):
    name = models.CharField(max_length=50,blank=False) # name of a parking space
    description = models.TextField(blank=False)# the description of a parking space
    image = models.ImageField(null=True,upload_to="images/parking_spaces") #The image of a parking space
    price = models.ForeignKey('Price',on_delete=models.CASCADE,null=True,blank=False) #Foreign key to prices of a parking space
    opening_hours = models.ForeignKey('OpeningHours',on_delete=models.CASCADE,null=True,blank=False) #Foreign key to the Opening hours of a parking space
    location = models.OneToOneField('Location',on_delete=models.CASCADE,null=True,blank=False) #Foreign key to the location of a parking space
    size = models.ForeignKey('Size',on_delete=models.CASCADE,null=True,blank=False) #Foreign key to the Size of the parking space
    type = models.ForeignKey('Type',on_delete=models.CASCADE,null=True,blank=False) #Foreign key to the Type of parking space (Street, Private, Car Park)
    features = models.ManyToManyField('Features',blank=False,db_table='ParkingSpaceFeatures') # features of a parking space
    reviews  = models.ManyToManyField('Review',blank=False,db_table='ParkingSpaceReviews') # reviews added to a parking space
    contact_information = models.ForeignKey('ContactInformation',on_delete=models.CASCADE,null=True,blank=False) #Foreign key to the contact information of a parking space
    seller_account = models.ForeignKey('Account',on_delete=models.CASCADE,null=True,blank=False) # Foreign key to the account information of the parking space owner 

我正在努力解决表格的 4 个要素:

1。当您要添加到表单的字段是外键字段并且与之相关的模型有自己的多个字段需要在表单中填写时。

这就像营业时间字段:

开放时间型号:

class OpeningHours(models.Model):

    # Opening and closing times of every day in the week
    monday_open = models.TimeField(null=True,blank=False)
    monday_close = models.TimeField(null=True,blank=False)

    tuesday_open = models.TimeField(null=True,blank=False)
    tuesday_close = models.TimeField(null=True,blank=False)

    wednesday_open = models.TimeField(null=True,blank=False)
    wednesday_close = models.TimeField(null=True,blank=False)

    thursday_open = models.TimeField(null=True,blank=False)
    thursday_close = models.TimeField(null=True,blank=False)

    friday_open = models.TimeField(null=True,blank=False)
    friday_close = models.TimeField(null=True,blank=False)

    saturday_open = models.TimeField(null=True,blank=False)
    saturday_close = models.TimeField(null=True,blank=False)

    sunday_open = models.TimeField(null=True,blank=False)
    sunday_close = models.TimeField(null=True,blank=False)

2。当您要添加到表单中的字段是 OnetoOne 字段并且关联的模型有自己的多个字段需要填写到表单中时。

这就像位置字段:

Location Model: 

    class Location(models.Model):
    address_number = models.CharField(max_length=10,blank=False) #the building number and  of the parking space("2a")
    address_street = models.CharField(max_length=100,blank=False)# the road/street of a parking space ("Bark Street")
    city = models.CharField(max_length=50,blank=False)# the city of the parking space ("London")
    county = models.CharField(max_length=100,blank=False)# the county of the parking space ("Greater London")
    postcode = models.CharField(max_length=20,blank=False)# the postcode of the parking space ("SW1W 0NY")
    country = models.CharField(max_length=100,blank=False)# the country the parking space is in ("United Kingdom")
    latitude= models.DecimalField(max_digits=18,decimal_places=15,blank=True,null=True,unique=True) # the latitude of the location of a parking space
    longitude= models.DecimalField(max_digits=18,decimal_places=15,blank=True,null=True,unique=True) #the longitude of the location of a parking space

3.当您要添加到表单的字段是外键字段并且与之相关的模型有 1 个要输入的字段时,这是一个选择。

这就像尺寸字段:

型号尺寸:

class Size(models.Model):

    COMPACT = "CP" # parking space sizing for compact vehicles and motocycles  
    STANDARD = "SD" # parking space sizing for most vehicles
    OVERSIZED = "OS" # parking space sizing for large vehicles and machines
    SIZE_CATEGORY_CHOICES  = [ 
                    (COMPACT,"Compact"), 
                    (STANDARD,"Standard"), 
                    (OVERSIZED,"Oversized")
                    ]

    size_category = models.CharField(max_length = 2, choices= SIZE_CATEGORY_CHOICES, default=STANDARD, blank=False, null=True)

4。当您要添加的字段是多对多字段并且与其相关的模型有 1 个字段是一个选择时

这就像功能字段:

特点型号: 类特征(模型.模型):

EVCHARGING = "EVC" # Parking space has electric charging capabaility
DISABLEDACCESS = "DBA" #Parking space has disabled access
HEIGHTRESTRICTION ="HRS" # Parking space has height restrictions
NOHEIGHTRESTRICTION = "NHR" # Parking space has NO height restrictions 
LIGHTING = "LIT" # Parking space is in lighted area
SECUREGATE = "SGE" # Parking space is securely gated 
COVEREDPARKING ="CVP" # Parking space is covered from weather
VIDEOSURVEILLANCE = "CTV" # Parking space has CCTV 

FEATURE_NAME_CHOICES = [
                (EVCHARGING,"EV Charging"),
                (DISABLEDACCESS,"Disabled Access"),
                (HEIGHTRESTRICTION,"Height Restriction"),
                (NOHEIGHTRESTRICTION,"No Height Restriction"),
                (LIGHTING,"Lighting"),   
                (SECUREGATE,"Securely Gated"),
                (COVEREDPARKING,"Covered Parking"),
                (VIDEOSURVEILLANCE,"CCTV")
]

feature_name = models.CharField(max_length=3,choices=FEATURE_NAME_CHOICES,blank=False,null=True)

另外,请触摸对简单视图的任何更改,这对于实现我想要的解决方案是必要的 视图.py:

def upload_parking_space(request):

    add_parking_space_form = AddParkingSpace()

    if request.method == 'POST':

        parking_space_form= AddParkingSpace(request.POST)

        if parking_space.is_valid():
                
            # Create and save parking space
            parking_space = add_parking_space.save(commit=False)
            parking_space.seller_account = request.user
            parking_space.save()

            redirect(home)

    data = {
        'add_parking_space_form ': add_parking_space ,
    }

    return render(request, "add parking space.html", data)

我可以单独问所有这些问题,但由于它是一种形式,我认为最好将它们结合起来。

非常感谢。

python django django-forms foreign-keys many-to-many
1个回答
0
投票

我认为你的问题不在于ForeignKeys等,而在于仅以一种形式包含相关模型。一种简单的方法是从 django-betterforms 创建一个 MultiModelForm 对象。

这里有一些提示,针对您的观点 1。首先,为每个类 ParkingSpace 和 OpeningHours 创建一个 ModelForm;由于您将为 OpeningHours 对象创建一个 ModelForm,因此无需在 ParkingSpace ModelForm 中包含该字段:

# forms.py
class ParkingSpaceForm(forms.ModelForm):
    class Meta:
        model = ParkingSpace
        fields = [ "__all__" ]
        exclude = ["opening_hours", "reviews", "seller_account"]

class OpeningHoursForm(forms.ModelForm):
    class Meta:
        model = OpeningHours
        fields = ["__all__"]

然后,创建一个 MultiModelForm 来组合这两个(或更多!)表单:

# forms.py
class CompleteForm(MultiModelForm):
    form_classes = {
        "parking_space" : ParkingSpaceForm,
        "opening_hours" : OpeningHoursForm
    }

在您看来,您需要使用 CompleteForm 而不是特定于模型的表单。您可以使用

form['parking_space'].cleaned_data['name']
等方式引用每个表单的字段。由于您的 ParkingSpace 取决于您的 OpeningHours,因此您需要在 ParkingSpace 对象之前创建并保存 OpeningHours 对象。像这样的东西: ... if form.is_valid() : oh = OpeningHours() oh.monday_open = forms["opening_hours"].cleaned_data["monday_open"] ... oh.save() ps = ParkingSpace() ps.opening_hours = oh ... ps.save() ...

最后,在您的模板中,您可以通过这种方式非常简单地包含每个模型表单的每个字段:

{{ form.parking_space.name }} ... {{ form.opening_hours.monday_open }}

© www.soinside.com 2019 - 2024. All rights reserved.