Мой 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)