如何使用ModelForm过滤Django 1.7表单中的值?

时间:2017-01-29 23:26:00

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

我正在尝试使用ModelForm来添加我的数据。它运行良好,但ForeignKey下拉列表显示所有值,我只希望它显示与登录用户相关的值。

这些是我的模特:

class productos(models.Model):
user        = models.ForeignKey(User)
secciones   = models.ForeignKey(secciones)
name        = models.CharField(max_length=50)
image       = models.ImageField(upload_to = 'productos')
precio      = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
descripcion = models.TextField(max_length=300, null=True,blank=True)

def save(self, *args, **kwargs):
    if not self.id:
        self.slug = slugify(self.name)
    super(productos, self).save(*args, **kwargs)

def __unicode__(self):
    return self.name
#####################################################################
class secciones(models.Model):
name = models.CharField(max_length=50)
user = models.ForeignKey(User)

def save(self, *args, **kwargs):
    if not self.id:
        self.slug = slugify(self.name)
    super(secciones, self).save(*args, **kwargs)

def __unicode__(self):
    return self.name

表单代码:

class AgregarProducto(forms.ModelForm):
class Meta:
    model   = productos

最后,查看代码:

def agregar_producto(request):
if request.method == "POST":
    modelform = AgregarProducto(request.POST,request.FILES,user=request.user)
    print modelform
    if modelform.is_valid():
        modelform.save()

        return redirect("/editar-perfil/")
else:
    modelform = AgregarProducto()
return render(request, "home/AgregarProducto.html", {"form":modelform})

如何让表单只显示secciones.user等于登录用户的secciones子集?

2 个答案:

答案 0 :(得分:0)

AgregarProductoNewProduct对吗?我希望你用英语告诉我们......

您需要secciones中的特定对象,示例如下图所示;

<强> 1。 yourapp/models.py

class Secciones(models.Model):
    user = models.ForeignKey(User)
    name = models.CharField(max_length=50)

    def save(self, *args, **kwargs):
        if not self.id:
            self.slug = slugify(self.name)
        super(Secciones, self).save(*args, **kwargs)

    def __unicode__(self):
        return self.name


class Productos(models.Model):
    user        = models.ForeignKey(User)
    secciones   = models.ForeignKey(Secciones)
    name        = models.CharField(max_length=50)
    image       = models.ImageField(upload_to = 'productos/%Y/%m/%d/')
    precio      = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
    descripcion = models.TextField(max_length=300, null=True,blank=True)

    def save(self, *args, **kwargs):
        if not self.id:
            self.slug = slugify(self.name)
        super(Productos, self).save(*args, **kwargs)

    def __unicode__(self):
        return self.name

<强> 2。 yourapp/forms.py

class AgregarProducto(forms.ModelForm):

  class Meta:
      model   = Productos
      fields = '__all__'
      exclude = ['user', 'secciones']

第3。 yourapp/views.py

from django.shortcuts import (render, redirect, get_object_or_404)
from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse

from yourapp.models import (Secciones, Productos)
from yourapp.forms import AgregarProducto


@login_required
def agregar_producto(request):
    """
    add new product view.
    """
    template_name = 'home/AgregarProducto.html'

    secciones = Secciones.objects.filter(user=request.user)
    if secciones.exists() == False:
        # do stuff, eg:
        return redirect('/error/page')

    if request.method == 'POST':
        form = AgregarProducto(request.POST, request.FILES)
        if form.is_valid():
            initial_object = form.save(commit=False)
            initial_object.user = request.user    # here you save current user logged in.

            # and also the `secciones` set single object,
            # because I see in your model is `ForeignKey`
            initial_object.secciones = secciones.first()
            initial_object.save()
            form.save()

            # you also can redirect to the saved object
            # an example;
            return redirect(reverse('edit_product_page', kwargs={'pk': initial_object.pk}))
        else:
            context = {'form': form, 'errors': form.errors}
            return render(request, template_name, context)
    else:
        form = AgregarProducto()
    return render(request, template_name, {'form': form})


@login_required
def edit_product(request, pk):
    """
    `productos` is from your model:productos
    I suggest you to use `uppercase` in your class name;
        eg: `Productors` but not `productos`

    :param `pk` is pk/id from instance object of `productos`
    """
    template_name = 'homee/edit_product.html'
    product = get_object_or_404(Productos, pk=pk)

    if request.method == 'POST':
        # instance the form from object of `product` above.
        form = AgregarProducto(request.POST, request.FILES, instance=product)
        if form.is_valid():
            initial_object = form.save(commit=False)
            initial_object.user = product.user # set from user creation
            initial_object.save()
            form.save()

            #do stuff

第3。 urls.py

from django.conf.urls import url

from yourapp.views import (agregar_producto, edit_product)

urlpatterns = [
    url(
        r'^product/new/$',
        agregar_producto, name='new_product_page'
    ),
    url(
        r'^product/(?P<pk>[-\d]+)/edit/$',
        edit_product, name='edit_product_page'
    ),
]

希望它有用......

答案 1 :(得分:0)

看起来你想要的是提供一组过滤的部分,这样你就可以在构建表单时使用初始参数:

def agregar_producto(request):
    if request.method == "POST":
    modelform = AgregarProducto(request.POST,request.FILES,user=request.user)
    print modelform
    if modelform.is_valid():
        modelform.save()

        return redirect("/editar-perfil/")
else:
    modelform = AgregarProducto(initial={'user':request.user}) #pass in the authenticated user
return render(request, "home/AgregarProducto.html", {"form":modelform})

然后以你的形式:

class AgregarProducto(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(AgregarProducto, self).__init__(*args, **kwargs)

        if kwargs.get('initial'):
            user = kwargs.get('initial').get('user')
            if user:
                sections = secciones.objects.filter(user_id=user.id)
                self.fields['secciones'].choices = [(s.id, s.name) for s in sections]
                self.fields['client'].choices = [('', '---------')]+self.fields['client'].choices #this adds an "empty" option

    class Meta:
        model   = productos

这只会在下拉列表中显示用户的部分,使用id作为值和名称作为显示。