首页 > 解决方案 > 在 Django 中,如何让 CreateView 只显示当前用户创建的对象?

问题描述

“食物”字段在我的模型中是多对多字段。目前,如果用户想要创建新餐点,他们选择的要添加的食物是数据库中的每个食物。有没有办法让创建表单只允许选择只添加当前用户制作的食物?我的所有 ManytoMany 字段都有这个问题。

视图.py

class MealCreateView(LoginRequiredMixin, CreateView):
    model = Meal
    success_url = '/dashboard/'
    fields = ['name', 'foods']

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)

在meal_form.html

<div class="content-section">
    <form method="POST">
        {% csrf_token %}
        <fieldset class="">
            <legend class="border-bottom mb-4">New Meal</legend>
            {{ form|crispy }}
        </fieldset>
        <div class="">
            <button class="btn btn-outline-info" type="submit">Add Meal</button>
        </div>
    </form>
</div>

在模型.py

class Food(models.Model):
    name = models.CharField(max_length=100, default="")
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    serving_size_g = models.DecimalField(default=100, max_digits=5, decimal_places=1)
    protein = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    total_fats = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    saturated_fats = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    mono_unsaturated_fats = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    poly_unsaturated_fats = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    total_carbohydrates = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    energy = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    sugars = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    fiber = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    calcium = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    iron = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    magnesium = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    potassium = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    sodium = models.DecimalField(default=0, max_digits=5, decimal_places=1)
    vitamin_c = models.DecimalField(default=0, max_digits=5, decimal_places=1)


    class Meta:
        '''Limits the user from making duplicates of food'''
        unique_together = ('name', 'user', 'protein', 'total_fats', 'total_carbohydrates', 'energy', 'sugars', 'fiber', 'calcium', 
                           'iron', 'magnesium', 'potassium', 'sodium', 'vitamin_c', 'saturated_fats', 'mono_unsaturated_fats', 'poly_unsaturated_fats')



class Meal(models.Model):
    name = models.CharField(max_length=20)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    foods = models.ManyToManyField(Food)

标签: djangodjango-modelsdjango-forms

解决方案


是的,您可以定义一个ModelForm来处理这个问题:

# app/forms.py

from django import forms
from app.models import Food, Meal

class MealForm(forms.ModelForm):

    def __init__(self, *args, user=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['foods'].queryset = Food.objects.filter(user=user)

    class Meta:
        model = Meal
        fields = ['name', 'foods']

现在在 中CreateView,我们可以使用这种形式,并为user参数传递一个值:

# app/views.py

from app.forms import MealForm

class MealCreateView(LoginRequiredMixin, CreateView):
    model = Meal
    success_url = '/dashboard/'
    form_class = MealForm
    
    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)

推荐阅读