将父对象传递给子对象的CreateView

时间:2020-04-03 15:17:05

标签: django django-models django-forms django-views django-templates

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

每次游览我都有一个子记录,其中定义了步骤。这两个模型如下所示:

models.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中找不到找到它的方法。

urls.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>

views.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

forms.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})

1 个答案:

答案 0 :(得分:1)

首先,您的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