I am probably missing something very simple, because my model form is not shown at the template. The code is very simple:
models.py:
class Story(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
title = models.CharField(max_length=200)
content = models.TextField()
picture = models.ImageField(upload_to = 'images/post_images')
date = models.DateTimeField(auto_now_add=True)
forms.py:
class StoryForm(forms.ModelForm):
class Meta:
model = Story
views.py:
from sfv.forms import StoryForm
#login_required(redirect_field_name=None)
def restricted(request):
user = request.user
form = StoryForm()
#graph = get_persistent_graph(request)
return render(request, "restricted.html", {user : 'user', form : 'form',})
template:
<form method = 'POST' action = ''>
<table>
{{ form }}
<table>
</form>
I have also tried form.as_p, that didnt help.
Change your render method from
return render(request, "restricted.html", {user : 'user', form : 'form',})
to
return render(request, "restricted.html", { 'user' : user, 'form' : form})
The key and value in the context dictionary were interchanged. Hence the issue.
Related
I am facing the following error when trying to save the project after filling the form where i am choosing multiple tags for this project:
null value in column "tag_id" of relation "project_tags" violates not-null constraint
DETAIL: Failing row contains (10263, 10262, null). --> project_tags(id, project_id, tag_id)
The db model is simple: I have projects, and each project has tag(s). All is defined by the following models:
class Project(models.Model):
id = models.AutoField(primary_key=True)
client = models.ForeignKey(User, on_delete=models.CASCADE)
start_date = models.DateField()
end_date = models.DateField()
class Meta:
managed = False
db_table = 'project'
def get_absolute_url(self):
return reverse('project-detail', kwargs={'pk': self.pk})
class ProjectTag(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=30)
class Meta:
managed = False
db_table = 'project_tag'
def __str__(self):
return self.name
class ProjectTags(models.Model):
id = models.AutoField(primary_key=True)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
tag = models.ManyToManyField(ProjectTag)
class Meta:
managed = False
db_table = 'project_tags'
View is following:
#login_required
def add_project(request):
submitted = False
if request.method == "POST":
form1 = ProjectForm(request.POST)
form2 = ProjectTagsForm(request.POST)
if form1.is_valid() and form2.is_valid():
form1_part = form1.save(commit=False)
form1_part.client = request.user
form1_part.save()
project_id = Project.objects.get(id=form1_part.id)
form2_part = form2.save(commit=False)
form2_part.project = project_id
form2_part.save()
return HttpResponseRedirect('/project/new?submitted=True')
else:
form1 = ProjectForm
form2 = ProjectTagsForm
if 'submitted' in request.GET:
submitted = True
context = {'form1':form1
,'form2':form2
,'submitted':submitted
}
return render(request, 'home_page/add_project.html',context)
WIth following forms that are both in one template:
class ProjectForm(forms.ModelForm):
class Meta:
model = Project
fields = ('start_date', 'end_date')
def __init__(self, *args, **kwargs):
super(ProjectForm, self).__init__(*args, **kwargs)
class ProjectTagsForm(forms.ModelForm):
class Meta:
model = ProjectTags
fields = ('tag',)
widgets = {
'tag': forms.SelectMultiple(attrs={'class': 'form-control','size': 12})
}
{% if submitted %}
Your project was submitted successfully!
{% else %}
<form action="" method=POST>
{% csrf_token %}
{{ form1.as_p }}
{{ form2 }}
<input type="submit" value="submit me" class="btn btn-secondary">
I understand the problem that after submitting the form it is not able to convert the selected tag names into tag_ids to fill the records (id,project_id,tag_id) and insert them to db table (as the table doesnt allow nulls as tag_id), but I have no idea how to fix, especially when it is practically copy paste of this Codemy video and its script where it worked https://youtu.be/x99hW1N8Nug
Currently, the template is only generating the Submit button without any input fields.
Also, if I change fields = "all" to fields= ["email","name"] it tells me that these fields do not exist.
Model:
class NewsletterSubscriber(models.Model):
email = EmailField(required=True, label='Email')
name = CharField(required=True, label='Name')
Serializer:
class SubscribeForm(forms.ModelForm):
class Meta:
model = NewsletterSubscriber
fields = "__all__"
View:
def subscribe(request):
form = SubscribeForm()
if request.method == 'POST':
form = SubscribeForm(request.POST)
if form.is_valid():
form.save()
# redirect to a success page
return render(request, 'subscribe.html', {'subscribeForm': form})
Template:
<form action="{% url 'subscribe' %}" method="post">
{% csrf_token %}
{{ subscribeForm.as_p }}
<input type="submit" value="Subscribe">
</form>
Give this a try:
class NewsletterSubscriber(models.Model):
email = EmailField(required=True)
name = CharField(required=True)
class SubscribeForm(forms.ModelForm):
class Meta:
model = NewsletterSubscriber
fields = ['email', 'name']
labels = {'email': 'Email', 'name': 'Name'}
Instead of fields you could instead also go for exclude which would then obviously list the fields that you do not want to show up.
All these attributes you can put in the Meta class: Modelformfactory
Solved.
Wrong:
class NewsletterSubscriber(models.Model):
email = EmailField(required=True, label='Email')
name = CharField(required=True, label='Name')
Correct:
class NewsletterSubscriber(models.Model):
email = models.EmailField(required=True, label='Email')
name = models.CharField(required=True, label='Name')
I have four fields in a model, one of which is a foreign key field and the other three are m2m fields. The form is opened in the modal, but the data is not being saved, Error given below. I don't understand what I did wrong. I would be very grateful for a little help.
Model:
class ProductAttributes(models.Model):
product = models.ForeignKey('Product', blank=True, null=True, on_delete=models.SET_NULL)
size = models.ManyToManyField('ProductSize', blank=True)
colour = models.ManyToManyField('ProductColour', blank=True)
cupsize = models.ManyToManyField('ProductCupSize', blank=True)
def __str__(self):
return self.product
Form:
class ProductAttributesForm(forms.ModelForm):
product = forms.IntegerField(label=('ID'),required=True, disabled=True)
size = forms.ModelMultipleChoiceField(queryset=ProductSize.objects.all(),widget=Select2MultipleWidget, required=False)
colour = forms.ModelMultipleChoiceField(queryset=ProductColour.objects.all(),widget=Select2MultipleWidget, required=False)
cupsize = forms.ModelMultipleChoiceField(queryset=ProductCupSize.objects.all(),widget=Select2MultipleWidget, required=False)
class Meta:
model = ProductAttributes
fields = ['product','size','colour','cupsize']
Template:
{% load crispy_forms_tags %}
<form id="Form" method="post" action="{% url 'accpack:products_attributes_create' product %}" class="js-product-create-form col s12" >
{% csrf_token %}
{% crispy form form.helper %}
</form>
View:
def save_attribute_form(request, form, template_name, pk):
data = dict()
if request.method == 'POST':
if form.is_valid():
form.save()
data['form_is_valid'] = True
else:
data['form_is_valid'] = False
context = {'form': form, 'product':pk}
data['html_form'] = render_to_string(template_name, context, request=request)
return JsonResponse(data)
def attribute_create(request, pk):
if request.method == 'POST':
form = ProductAttributesForm(request.POST, initial={'product': pk})
else:
form = ProductAttributesForm(initial={'product': pk})
return save_attribute_form(request, form, 'main/products/partial_product_attribute_form.html', pk)
ajax:
var saveForm = function () {
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
$("#modal-product_attribute").modal("hide");
console.log(data.form_data);
}
else {
$("#modal-product_attribute .modal-content").html(data.html_form);
}
}
});
return false;
$("#modal-product_attribute").on("submit", ".js-product-create-form", saveForm);
error:
File "C:\ProgramData\Anaconda3\envs\djangoproject\lib\site-packages\django\db\models\fields\related_descriptors.py", line 220, in __set__
self.field.remote_field.model._meta.object_name,
ValueError: Cannot assign "111": "ProductAttributes.product" must be a "Product" instance.
You have an error in your forms.py.
class Meta:
model = ProductSize
fields = ['product','size','colour','cupsize']
Here, the model should be
model = ProductAttributes
Since the model you specified here ProductSize does exist, submitting form will just create another instance to ProductSize model without those specific fields and error messages. You can check your admin page.
EDIT ******
2. Based on what you added in the question and the error message, it looks like in attribute_create you are passing product's pk. Now in the attribute_create, you are passing initial dict {'product': pk}. This is wrong, because, in your ProductAttributesForm, the product field should be an instance rather than a pk.
You need to refer product as
product = Product.objects.filter(pk=pk)
initial = {'product':product}
The current error message will be gone, but you will have other errors.
I am trying to create "Edit" for my form.
urls.py
url(r'^app_1/(?P<id>[-\w]+)/edit/$',views.edit, name = 'edit'),
forms.py
class ClanakForma(forms.ModelForm):
class Meta:
model = Clanak
fields = '__all__'
models.py
class Clanak(models.Model):
naslov = models.CharField(null=False, blank=True, max_length=120)
datumObjave = models.DateField(null=False, blank=False)
autor = models.CharField(null=False, blank=True, max_length=50)
email = models.EmailField(max_length=75, null=True, blank=True)
def __str__(self):
return str(self.naslov) + ', ' + str(self.datumObjave) + ', ' + str(self.autor)
views.py
def edit(request, id):
data = get_object_or_404(Clanak, id = id)
if request.method == "POST":
form = ClanakForma(request.Clanak, instance=data)
if form.is_vaild():
data = form.save(commit=False)
data.naslov = request.user
data.datumObjave = request.user
data.autor = request.user
data.email = request.user
return redirect('readAllNew')
else:
form = ClanakForma(instance=data)
template = 'readAllNew.html'
context = {'form': form}
return render(request, template, context)
readAllNew.html
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<table border="1">
<tr>
<th>Naslov</th>
<th>Datum</th>
<th>Autor</th>
<th>Mail</th>
</tr>
{% for x in data %}
<tr>
<td>{{x.naslov}}</td>
<td>{{x.datumObjave}}</td>
<td>{{x.autor}}</td>
<td>{{x.email}}</td>
<td>delete</td>
<td>edit</td>
</tr>
{% endfor %}
</table>
</body>
</html>
So when I hit edit link at my "readAllNew.html" I get error:
TypeError at /app_1/5/edit/
init() got an unexpected keyword argument 'instance'
I think something is wrong with my view but I am not sure what.
-------------------------------UPDATE--------------------------------
As suggested I edited "forms.py" but now I am not seeing any form field so I can't edit nothing:
See screenshot
---------------- UPDATE 2 -------------------------
I created new html file as "edit.html"
I edited "views.py":
def edit(request, id):
data = get_object_or_404(Clanak, id = id)
if request.method == "POST":
form = ClanakForma(instance=data)
if form.is_vaild():
data = form.save(commit=False)
data.naslov = request.user
data.datumObjave = request.user
data.autor = request.user
data.email = request.user
return redirect('readAllNew.html')
else:
form = ClanakForma(instance=data)
template = 'edit.html'
context = {'form': form}
return render(request, template, context)
Now I see fields and informations in it properly, but when I change something and click on "SUBMIT" I get error:
AttributeError at /app_1/6/edit/
'ClanakForma' object has no attribute 'is_vaild'
Use forms.ModelForm instead of forms.Form
class Forma(forms.ModelForm):
naslov = forms.CharField(label='naslov')
datumObjave = forms.DateField(label='datumObjave')
autor = forms.CharField(label='autor')
email = forms.EmailField(label='email')
class Meta:
model = Clanak
fields = ('naslov', 'datumObjave', 'autor', 'email')
If you want to use all the fields of Model class in your form, you could specify the fields attribute of Meta class as fields = '__all__'
#example
class Forma(forms.ModelForm):
class Meta:
model = Clanak
fields = '__all__'
If you are using forms.ModelForm, you could avoid most of the implementation which makes things easier :)
Update
You need to render the form in your template.So, change your template as
<form method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
You can't pass instance to simple form - it has to be ModelForm. Use this:
class Forma(forms.ModelForm):
class Meta:
model = Clanak
fields = ['naslov', 'datumObjave', 'autor', 'email']
labels = {
'naslov': 'naslov',
'datumObjave': 'datumObjave',
'autor': 'autor',
'email': 'email'
}
I can't figure out how to store a simple form in the database. I think I'm quite close but there is probably something wrong in my views.py. Here is my code, any ideas what I'm doing wrong? (also on dpaste)
# models.py
class IngredienceCategory(models.Model):
name = models.CharField(max_length=30, unique=True)
user = models.ForeignKey(User, null=True, blank=True)
class Meta:
verbose_name_plural = "Ingredience Categories"
def __unicode__(self):
return self.name
# forms.py
class CategoryForm(forms.Form):
name = forms.CharField(max_length=30)
# views.py
#login_required
def newCategory(request):
if request.method == 'POST':
username = request.user.username
cform = CategoryForm(request.POST)
if cform.is_valid():
formInstance = cform.save(commit = False)
formInstance.user = username
formInstance.name = cform.cleaned_data['name']
formInstance = IngredienceCategory.objects.filter(name=formInstance.name, user=formInstance.user)
formInstance.save()
# return HttpResponseRedirect('new-category/')
else:
form = CategoryForm()
context = {'form': form}
return render_to_response('new-category.html', context, context_instance=RequestContext(request))
# new-category.html
<h3>Insert New Category</h3>
<form action="/" method="post" id="food-form">{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="foodForm" value="Save" />
</form>
The line below is not useful at it current position. That command will perform a database query and assign the result as a queryset, before you have saved the form data.
formInstance = IngredienceCategory.objects.filter(name=formInstance.name, user=formInstance.user)
This should work:
With cform as a normal Form:
if cform.is_valid():
formInstance = IngredienceCategory(user=request.user, cform.cleaned_data['name'])
formInstance.save()
If cform had been a ModelForm you could do:
if cform.is_valid():
formInstance = cform.save(commit=False)
formInstance.user = request.user
formInstance.save()
I do recommend you to check out ModelForms since it will build the cleaning functionality based on your model.
You should inherit from ModelForm
from django.forms import ModelForm
class CategoryForm(ModelForm):
class Meta:
model = IngredienceCategory
Refer to https://docs.djangoproject.com/en/dev/topics/forms/modelforms/ for how to render form and save it to database.