Установка значения поля формы в view.py - PullRequest
0 голосов
/ 11 марта 2020

Мой django веб-сайт хотел бы разрешить зарегистрированным пользователям публиковать рецепт. Модель рецепта связана с моделью пользователя и поэтому требует допустимого экземпляра пользователя. Я хотел бы, чтобы форма «Рецепт» автоматически назначала поле postsby экземпляру вошедшего в систему пользователя.

До сих пор я пытался передать словарь с именем пользователя в экземпляр формы. как показано в представлении Однако метод конструктора не получает данные и отображает форму, но при неудачной попытке отправки.

Я не могу сохранить данные без поля postsby, имеющего действительный экземпляр, поскольку модель выдает следующую ошибку:

Значение исключения: запрос на сопоставление UserProfile не существует.

Я также попытался сделать следующее в views.py;

@login_required
def add_recipe(request): 
    form = RecipeForm()
    form.fields['postedby'] = UserProfile.objects.get(user=User.objects.get(username=request.user.__str__()))
    context_dict = {'form':form}
    if request.method == 'POST': 
        ...

Однако это перезаписывает представление формы в форме сообщения, которое будет отображаться, и вызывает ошибки.

views.py

@login_required
def add_recipe(request): 
    form = RecipeForm({'user':request.user})
    context_dict = {}


    #print(form.fields['postedby'].queryset)

    if request.method == 'POST': 
        form = RecipeForm(request.POST)        
        if form.is_valid(): 
            form.save(commit=True)
            return redirect(reverse('spatula:index'))
        else: 
            print(form.errors)
    context_dict['form'] = form

    return render(request, 'spatula/add_recipe.html', context=context_dict)

RecipeForm выглядит следующим образом:

class RecipeForm(forms.ModelForm):

    def __init__(self,*args,**kwargs):
        print(kwargs) 
        super(RecipeForm, self).__init__(*args, **kwargs)

    #input fields for recipe form
    method = forms.CharField(max_length=512, widget=forms.Textarea(attrs={'placeholder':'Method'}))
    name = forms.CharField(max_length=128, widget=forms.TextInput(attrs={'placeholder':'Recipe Name'}))
    ingredients = forms.CharField(max_length=512, widget=forms.Textarea(attrs={'placeholder':'Ingredients'}))

    category = NameChoiceField(widget=forms.Select(), queryset =Category.objects.all(), initial = 0)

    toolsreq = forms.CharField(max_length=512, widget=forms.TextInput(attrs={'placeholder':'Tools Required'}))
    difficulty = forms.IntegerField(widget=forms.NumberInput(attrs={'type':'range', 'step':'1', 'min':'1','max':'3'}), help_text = 'Difficulty: ')
    cost = forms.IntegerField(widget=forms.NumberInput(attrs={'type':'range', 'step':'1', 'min':'1','max':'3'}), help_text = 'Cost: ')
    diettype = forms.IntegerField(widget=forms.RadioSelect(choices=DIET_CHOICES))

    # not required as its not stored in DB
    #description = forms.CharField(widget=forms.Textarea(attrs={'placeholder':'Description'})) 


    #hidden fields
    rating = forms.FloatField(widget=forms.HiddenInput(), initial=0, required=False)
    slug = forms.SlugField(widget=forms.HiddenInput(),required=False)
    postedby = forms.SlugField(widget=forms.HiddenInput(),required=False)

    #Order in which inputs get rendered
    field_order = ['name', 'category', 'toolsreq', 'difficulty', 'cost', 'diettype', 'ingredients', 'method']

    class Meta: 
        model = Recipe
        exclude = ('id',)

наконец, вот модель рецепта:

class Recipe(models.Model):

    DIET_CHOICES = (
                (1,"Meat"),
                (2,"Vegetarian"),
                (3,"Vegan"),
    )
    DIFFICULTY_CHOICES   = (
                (1,1),
                (2,2),
                (3,3),
    )
    COST_CHOICES        = (
                (1,1),
                (2,2),
                (3,3),
    )

    name                   = models.CharField(max_length=NAME_MAX_LENGTH)
    ingredients            = models.TextField(max_length=MAX_TEXT_LENGTH)
    toolsreq               = models.TextField(max_length=MAX_TEXT_LENGTH)
    method                 = models.TextField()

    # make sure the form views for difficulty, 
    # cost and diettype datatypes restrict the 
    # users selection to the CHOICES above
    difficulty             = models.PositiveSmallIntegerField(choices=DIFFICULTY_CHOICES)
    cost                   = models.PositiveSmallIntegerField(choices=COST_CHOICES)
    diettype               = models.PositiveSmallIntegerField(choices=DIET_CHOICES)

    postedby               = models.ForeignKey(UserProfile, on_delete=models.CASCADE, default=0)

    #  - Following fields are hidden when creating a new recipe
    #       ratings are out of 5, to 1 decimal place.
    #  - Need a script to update rating everytime
    #       a new rating for the recipe is posted.
    rating                 = models.DecimalField(decimal_places=1,max_digits=3, default=0)
    category               = models.ForeignKey(Category,to_field="name", on_delete=models.CASCADE)

    # recipes rating is calculated when the recipe is requested, no value to be stored

    def __str__(self):
        return self.name

    # used for recipe mappings
    def save(self,*args, **kwargs):
        self.slug = slugify(str(self.name)+str(self.postedby))
        super(Recipe,self).save(*args, **kwargs)

Ответы [ 2 ]

1 голос
/ 11 марта 2020

Поскольку вы не хотите, чтобы ваш пользователь go редактировал это поле, полностью удалите его из формы:

exclude = ['id', 'postedby']

Затем, на ваш взгляд, установите значение в instance перед сохранением:

# ...
if request.method == 'POST': 
    form = RecipeForm(request.POST)        
    if form.is_valid(): 
        recipe = form.save(commit=False)
        recipe.postedby = UserProfile.objects.get(user=request.user)
        recipe.save()
        return redirect(reverse('spatula:index'))
# ...
0 голосов
/ 11 марта 2020

В сообщении об ошибке указано: Значение исключения: запрос сопоставления UserProfile не существует. Это означает, что для этого нет объекта UserProfile.

Возможно, вы захотите:

try:
    profile = UserProfile.objects.get(user=request.user)
except UserProfile.DoesNotExist
    # your logic

Или если вы хотите автоматически создать UserProfile объект для запрашиваемого пользователя. Вы можете использовать get_or_create :

p, created = UserProfile.objects.get_or_create(user=request.user)

Объяснение: Все аргументы ключевого слова, переданные в get_or_create() - кроме необязательного, называемого defaults - будет использоваться в get() вызове. Если объект найден, get_or_create() возвращает кортеж этого объекта и False.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...