为复杂的 Django 视图添加值

Nic*_*k B 1 python django view django-models

我正在尝试从Photographer模型中获取值字典以显示在我的表单中。之后,用户将选择一个Photographer,提交表单(以及其他信息),然后A将创建一个以Photographer为属性的模型实例。虽然我知道 ModelForms 可以更友好,但在这种情况下我必须使用 BaseForm:

@login_required
def create_in(request, slug):
    element = get_object_or_404(Element, slug=slug)
    a = A.objects.create(element=element, user=request.user)
    a.save()
    return redirect('CreationEditView', pk=a.pk)
Run Code Online (Sandbox Code Playgroud)

urlconf发送用户create_in,,其中用户选择 element然后被重定向到CreationEditView,其使用BaseUpdateView从Django的通用视图来操纵对象:

class EditView(BaseUpdateView):
    model = A
    form_class = AForm
    context_object_name = 'a'
    page = 'edit.html'

    def get_element(self):
        return self.object.element

    def render_to_response(self, context, **response_kwargs):
        element = self.get_element()
        return render_page(self.request, element,
                           self.page, context)

    def get_success_url(self):
        return reverse('view_all')

    def get_context_data(self, **kwargs):
        context = super(EditView, self).get_context_data(**kwargs)
        return context

    def get_queryset(self):
        qs = super(EditView, self).get_queryset()
        return qs.filter(active=True, user=self.request.user)

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super(EditView, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super(EditView, self).post(request, *args, **kwargs)

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super(EditView, self).dispatch(request, *args, **kwargs)

class CreationEditView(EditView):
    def get_queryset(self):
        qs = super(EditView, self).get_queryset()
        return qs.filter(active=False, user=self.request.user)

    def get_success_url(self):
        return reverse('create_finished',
                       kwargs=dict(pk=self.object.pk))

    def get_context_data(self, **kwargs):
        context = super(CreationEditView, self).get_context_data(**kwargs)
        context['create'] = True
        return context
Run Code Online (Sandbox Code Playgroud)

然后通过 呈现页面render_page,如下所示:

def render_page(request, element, page, context):
    template_name = element_template_name(element, page)
    try:
        template = get_template(template_name)
    except TemplateDoesNotExist:
        template = get_template('template_location/%s' % page)
    context = RequestContext(request, context)
    return HttpResponse(template.render(context))
Run Code Online (Sandbox Code Playgroud)

如果我的模型是这样的:

class Photographer(models.Model):
    name = models.CharField(max_length=20)
    models = models.ManyToManyField('Model')

class Model(models.Model):
    model = models.CharField(max_length=20, blank=False)
    series = models.ForeignKey('Series', null=True, blank=True)

class A(models.Model):
    user = models.ForeignKey(User)
    photographer = models.ForeignKey('Photographer', blank=True, null=True)
    model = models.ForeignKey('Model', blank=True, null=True)
Run Code Online (Sandbox Code Playgroud)

您将如何将值Photographer正确集成到视图代码中,以便稍后在模板中使用?这些值将是用户将从中选择的下拉表单的一部分。使用示例将非常有帮助。

感谢您的任何想法。

编辑(添加表单)


class AForm(BaseForm):
    def __init__(self, data=None, files=None, instance=None, auto_id='id_%s',
                 prefix=None, initial=None, error_class=ErrorList,
                 label_suffix=':', empty_permitted=False):

        if not instance:
            raise NotImplementedError("Instance must be provided")

        self.instance = instance
        object_data = self.instance.fields_dict()
        self.declared_fields = SortedDict()
        self.base_fields = fields_for_a(self.instance)

        # if initial was provided, it should override the values from instance
        if initial is not None:
            object_data.update(initial)

        BaseForm.__init__(self, data, files, auto_id, prefix, object_data,
                          error_class, label_suffix, empty_permitted)

        cleaned_data = self.cleaned_data

        # save fieldvalues for self.instance
        fields = field_list(self.instance)

        for field in fields:
            if field.enable_wysiwyg:
                value = unicode(strip(cleaned_data[field.name]))
            else:
                value = unicode(cleaned_data[field.name])

        return self.instance
Run Code Online (Sandbox Code Playgroud)

Rob*_*rne 5

我认为您错过了 Django 编程的一个基本方面,即 Django 形式。您应该创建一个表单,如:

class AForm(forms.Form):
    model = forms.ModelChoiceField(queryset=Model.objects.all())
    photographer = forms.ModelChoiceField(queryset=Photographer.objects.all())

    class Meta:
        model = A
        fields = ('model', 'photographer', )
Run Code Online (Sandbox Code Playgroud)

然后你的创建视图看起来像:

@login_required
def create_in(request, slug):
    if request.method == 'POST':
        form = AForm(request.POST)
        if form.is_valid():
            instance = form.save(commit=False)
            instance.user = request.user
            return HttpResponseRedirect("/somewhere/")
    else:
        form = AForm()
    return render_to_response('create_in.html', { 'form': form }, context_instance=context)
Run Code Online (Sandbox Code Playgroud)

很难弄清楚你想要做什么,我认为你变得过于棘手,因为我从来不需要扩展 BaseForm 并且我已经做了很多带有特殊过滤器的表单选择。通常这些是这样做的:

class AForm(forms.Form): 
   def __init__(self, profile, *args, **kwargs):
       super(AForm, self).__init__(*args, **kwargs)
       self.fields['photographer'].queryset = models.Photographer.objects.filter(profilephotographer__profile=profile)
Run Code Online (Sandbox Code Playgroud)