首页 > 解决方案 > 将父对象传递给子对象的 CreateView

问题描述

我正在创建一个仪表板来编辑旅游应用程序。

每次旅行我都有一个子记录,我在其中定义步骤。2 个模型如下所示:

模型.py

class Tour(models.Model):
    tour_id = models.CharField(primary_key=True,unique=True, max_length=10)
    country = models.ForeignKey(Countries, models.DO_NOTHING, db_column='country')
    language = models.ForeignKey(Language, models.DO_NOTHING, db_column='language')
    lastupddtm = models.DateTimeField(default=timezone.now)
    productid = models.CharField(max_length=50)
    title = models.CharField(max_length=50)
    description = models.CharField(max_length=100)
    descrlong = models.CharField(max_length=1000)
    live = models.CharField(max_length=1)
    image = models.ImageField(upload_to=upload_tour_image, storage=OverwriteStorage(), blank=True, null=True)

    class Meta:
        db_table = 'tour'
        verbose_name_plural = "tour"


    def get_language_flag(self):
        return self.language.flag.url

    def __str__(self):
        return str(self.tour_id) + ' - ' + str(self.title) + ' - ' + str(self.description)



class Toursteps(models.Model):
    # tour_id = models.OneToOneField(Tour, models.DO_NOTHING, db_column='tour_id')
    tour = models.ForeignKey(Tour, related_name='toursteps', on_delete=models.CASCADE)
    step = models.IntegerField(unique=True)
    title = models.CharField(max_length=50)
    description = models.CharField(max_length=100)
    descrlong = models.CharField(max_length=1000)
    audiotext = models.TextField()
    latitude = models.FloatField()
    longitude = models.FloatField()
    radius = models.FloatField()
    image = models.ImageField(upload_to=upload_tour_step_image, blank=True, null=True)

    class Meta:
        db_table = 'tourSteps'
        verbose_name_plural = "tourSteps"

    def __str__(self):
        return str(self.tour) + "|" + str(self.step)

创建游览后,我转到详细信息页面。从那里,我可以单击一个链接来为此游览添加一个步骤。这就是问题所在。我将 tour_id 作为变量传递到 url,但我找不到在步骤的 CreateView 中获取它的方法。

网址.py

urlpatterns = [
    path('tour/<str:pk>/detail', views.TourDetailView.as_view(), name='tour_detail'),
    path('tour/<str:pk>/edit', views.UpdateTourView.as_view(), name='tour_edit'),
    path('tour/<str:pk>/remove', views.DeleteTourView.as_view(), name='tour_remove'),
    path('tour/<str:tour_id>/step/new', views.CreateTourStepView.as_view(), name='tour_step_new')
]

游览详情视图

 <p><a href="{% url 'tour_step_new' tour_id=tour.pk %}"><span class="glyphicon glyphicon-plus"></span></a></p>

视图.py

class CreateTourStepView(LoginRequiredMixin,CreateView):
    login_url = '/login/'
    redirect_field_name = 'tour_admin/tour_list.html'
    success_url = '/'
    form_class = TourStepForm
    model = Toursteps

    def get_context_data(self, **kwargs):
        context = super(CreateTourStepView, self).get_context_data(**kwargs)
        print(context['tour_id'])
        return context

表格.py

class TourStepForm(forms.ModelForm):

    class Meta():
        model = Toursteps
        #fields = '__all__'
        exclude = ('tour',)

    def form_valid(self, form):
        if form.is_valid():
            form.instance.tour_id = self.request.GET("tour_id")

            form.instance.save()

            return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        return reverse('tour_detail', kwargs={'pk':form.instance.tour_id})

标签: djangodjango-modelsdjango-formsdjango-viewsdjango-templates

解决方案


首先,您的form_valid()get_success_url()方法属于您的视图,而不是您的表单。

其次,tour_id传递给视图的kwargs,它不是查询参数,因此不在self.request.GET. 你可以在self.kwargs.

第三,您需要实际从数据库中获取Tour,而不仅仅是分配tour_id. 如果我愿意,我可以发布到任何人tour_id,并且不能保证tour_id属于实际Tour对象。如果游览不存在,则返回 404。如果存在,请将其分配给游览步骤。

最后,您不应该分配到和保存form.instance. 您应该使用 获取实例step = form.save(commit=False),然后分配给step并保存step


推荐阅读