My project is here github Project
I'm getting this error.
ValueError at /salesapp/add/ashton-aged-maduro/
The view salesapp.views.add_CartItem didn't return an HttpResponse object. It returned None instead.
I get this error when I click the 'Add to Cart' button on my singleproduct.html template which calls the ProductAddToCart form. The view is add_CartItem.
I also get the error Field is required when I don't initially set the form values. I'm just stuck now.
This is models.py
class Product(models.Model):
itemid = models.CharField(max_length=128, unique=True)
itemname = models.CharField(max_length=128)
brand = models.CharField(max_length=128)
image = models.ImageField(upload_to='static/images/')
notes = models.CharField(max_length=250)
price = models.IntegerField()
slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.itemname)
super(Product, self).save(*args, **kwargs)
def __str__(self):
return self.itemname
class CartItem(models.Model):
cart_id = models.CharField(max_length=50)
date_added = models.DateTimeField(auto_now_add=True)
quantity = models.IntegerField(default=1)
itemid = models.ForeignKey('Product', unique=False)
class Meta:
db_table = 'cart_items'
ordering = ['date_added']
def name(self):
return self.product.name
My forms.py
class ProductAddToCartForm(forms.ModelForm):
cart_id = forms.CharField(max_length=50)
date_added = forms.DateTimeField()
quantity = forms.IntegerField()
slug = forms.CharField(widget=forms.HiddenInput(), required=False)
#itemid = models.ForeignKey('Product', unique=False)
class Meta:
model = CartItem
fields = ('cart_id', 'date_added', 'quantity', 'slug', 'itemid', )
My views.py
def add_CartItem(request, product_name_slug):
print('In add_CartItem --------------------')
form = ProductAddToCartForm(request.POST)
p = Product.objects.get(slug=product_name_slug)
form = ProductAddToCartForm(initial={'cart_id': 123, 'date_added':date.date.today(), 'quantity': 1, 'slug':p.slug, 'id':p.id, 'itemid':p.itemid})
form.save(commit=False)
print(form)
print(p.slug)
print(p.id)
print(p.itemid)
if form.is_valid():
print(p)
print('In form.is_valid()--------------------------------')
ci = CartItem.objects.create(cart_id=1, date_added=date.date.today(), quantity=1, itemid=p)
form.save(commit=True)
return index(request)
else:
print(form.errors) #return render(request, 'salesapp/errors.html', {'form': form})
My urls.py
from django.conf.urls import url
from salesapp import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'about/', views.about, name='about'),
url(r'customers/', views.customers, name='customers'),
url(r'products/', views.products, name='products'),
url(r'^add_product/$', views.add_product, name='add_product'),
url(r'^add_customer/$', views.add_customer, name='add_customer'),
url(r'items/(?P<product_name_slug>[\w\-]+)/$', views.show_product, name='show_product'),
url(r'^add/(?P<product_name_slug>[\w\-]+)/$', views.add_CartItem, name='add_CartItem'),
#url(r'^cart/$', views.show_cart, name='show_cart'),
#url(r'^register/$', views.register, name='register'),
#url(r'^login/$', views.user_login, name='login'),
#url(r'^logout/$', views.user_logout, name='logout'),
#url(r'^restricted/', views.restricted, name='restricted'),
]
and my template where I want to display the ProductAddToCartForm but add a product to the CartItem table.
<!DOCTYPE html>
{% extends 'salesapp/base.html' %}
{% load staticfiles %}
{% block title_block %}
{{ product.itemname }}
{% endblock %}
{% block body_block %}
<div>
<div>
<ul style="list-style:none; text-align:center;">
<li style="float:left; width:25%; margin:20px;">
<img src="/{{ product.image }}"/>
<div>
<b>{{ product.itemname }}</b><br/>
Price per cigar:<br/>
<b>${{ product.price }}</b>
<p>{{ product.notes }}</p>
</div>
<form method="post" action="/salesapp/add/{{ product.slug }}/" class="cart">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
{{ field.errors }}
{{ field.help_text }}
{{ field }}
{% endfor %}
<br />
<input type="submit" value="Add To Cart" name="submit" alt="Add To Cart" />
</form>
<div class="cb"></div>
</li>
</ul>
</div>
<!-- More code -->
</div>
{% endblock %}
A view function in django should either return a json or a dict or can return a Webpage
You can either do one of following
1) return a json or dict
return {"value1":"value","value2":"value"}
2)redirect to a web page
return redirect('/some/url/')
3)return Http response
return HttpResponse(status=<status code>,content="some content")
4)render a template
t = loader.get_template('myapp/index.html')
c = {'foo': 'bar'}
return HttpResponse(t.render(c, request),
content_type='application/xhtml+xml')
Because you did not return any response to the view,
According to the docs
A view function is simply a Python function that
takes a Web request and returns a Web response.
You need to return to use render method for initial rendering of form and for redirection to another view you can use redirect method of Django.
A view function must return an HttpResponse. For example, if the process was successfull and you dont want to return anything, you can return HttpResponse(status=200)
When a view handles forms, you have to split GET and POST requests. In the GET part you need to instantiate the form without data. In the POST part you fill the form with request.POST data. And this data must have ALL mandatory fields. A typical view function scheme to handle a form is the folowing:
def view(request):
if request.method == "GET":
form = MyForm()
return ...
if request.method == "POST":
form = MyForm(request.POST)
form.save()
return ...
In your template, you have to show all form fields. Then, all form fields will be passed with the request. If you dont, you need to fill the form fields in the view.
first delete the prints, almost when you make a question, are useless in Django
def add_CartItem(request, product_name_slug):
form = ProductAddToCartForm(request.POST)
if request.method == 'POST':
if form.is_valid():
ci = CartItem.objects.create(cart_id=1, date_added=date.date.today(), quantity=1, itemid=p)
ci.save()#you save your model changes, not your form
return HttpResponseRedirect(reverse('your:url'))#your return the success url or the same
else:
#here error, if form isn't valid
else:
form = ProductAddToCartForm(request.POST)
return render(request, 'your/template.html', {'form': form})
That is the correct way to work with forms in Django, first you must make a if statement asking to the browser if is a post request or a normal request, if is post request, take the data from the forms and are adding to the database, if not, Django return a empty template form.
Let me know if you problem solve
Related
I have been having a problem working with formsets in my project and I've been trying to get to the bottom of this. While doing so, a couple of different errors have been appearing. Generally, what I want to do is create an object of entity A (workout) and get redirected to a template/url that lets me "fill" it with objects of entity B, which I will be making at that point dynamically using model formsets. The problem seems to be revolving around the form, more specifically: if I write the fields one by one, as in :
CycleFormSet = modelformset_factory(
Cycle, fields=('reps', 'place_in_workout', 'exercise', 'number_of_times', 'break_inbetween'), extra=1
)
Then, I get the error: Unknown field(s) (place_in_workout, break_inbetween, reps, number_of_times) when I attempt to run the server. If I use exclude for some field, or do fields = 'all' , then I don't get an error at this point. However, I get the error : ['ManagementForm data is missing or has been tampered with'] when I try to post the data of the workout object. Me code:
models.py
class Exercise(models.Model):
name = models.CharField(max_length=150)
description = models.TextField(max_length=500)
def __str__(self):
return self.name
class Workout(models.Model):
name = models.CharField(max_length=150, null=True)
created_by_user = models.ForeignKey(User, null=True, on_delete=models.RESTRICT)
description = models.TextField(max_length=1000, null=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Cycle(models.Model):
place_in_workout = models.IntegerField
exercise = models.ManyToManyField(Exercise)
number_of_times = models.IntegerField
reps = models.IntegerField
break_inbetween = models.IntegerField
workout = models.ManyToManyField(Workout)
class WorkoutCompleted(models.Model):
datetime = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(User, on_delete=models.RESTRICT)
forms.py
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class WorkoutForm(forms.ModelForm):
class Meta:
model = Workout
fields = ['name', 'description']
class ExerciseForm(forms.ModelForm):
class Meta:
model = Exercise
fields = ['name', 'description']
CycleFormSet = modelformset_factory(
Cycle, fields='__all__', extra=1
)
urls.py
urlpatterns = [
path('register/', views.register_page, name='register'),
path('login/', views.login_page, name='login'),
path('logout', views.logout_page, name='logout'),
path('', views.index, name='index'),
path('browse/', views.browse, name='browse'),
path('workouts/<str:user_id>/', views.workouts, name='workouts'),
path('add_exercise/', views.add_exercise, name='add_exercise'),
path('create_workout/<str:user_id>/', views.fill_workout, name='fill_workout')
]
views.py
#login_required(login_url='login')
def workouts(request, user_id):
context = {}
if request.method == 'POST':
form = WorkoutForm(request.POST)
if form.is_valid():
workout = form.save(commit=False)
workout.created_by_user = request.user
workout.save()
workout_id = workout.id
context = {'workout_id': workout_id}
return render(request, 'Trainmate/fill_workout.html', context)
else:
form = WorkoutForm()
workout_programs = Workout.objects.all()
user_workouts = workout_programs.filter(created_by_user=user_id)
context = {'user_workouts': user_workouts, 'form': form}
return render(request, 'Trainmate/workouts.html', context)
#login_required(login_url='login')
def fill_workout(request, user_id):
if request.method == 'POST':
# workouts = Workout.objects.filter(created_by_user__exact=request.user).order_by('-created_at')
# current_workout = workouts[0]
# pk_workout = current_workout.id
pk_workout = 1
formset = CycleFormSet(request.POST)
if formset.is_valid():
for form in formset:
cycle = form.save(commit=False)
cycle.workout = Workout.objects.get(pk=pk_workout)
cycle.save()
context = {}
return render(request, 'Trainmate/home.html', context)
else:
formset = CycleFormSet(queryset=Cycle.objects.none())
context = {'formset': formset}
return render(request, 'Trainmate/fill_workout_with_sets', context)
(there are more views, I didn't include some views about login/logout, if asked, I will, I didn't want to make the post even bigger than it's already going to be). Also, I have run the views with the commented section, I believe I am doing some mistake with queryset, therefore I gave the pk_workout=1 so that the fault in the query set is not relevant. There is at least a workout object in the database at all times.
workouts.html
{% extends 'Trainmate/main.html' %}
{% block content %}
<h1>My Workouts</h1>
<div>
{% for workout in user_workouts %}
<tr>
<td>{{ workout.name }}</td>
<td><a class="btn btn-sm btn-info" href="">Update</a></td>
<td><a class="btn btn-sm btn-info" href="">Delete</a></td><br>
</tr>
{% endfor %}
</div>
<h1>Create new Workout</h1>
<form method="POST" action="{% url 'fill_workout' request.user.id %}">
{% csrf_token %}
{{ form }}
<input type="submit" value="Create Workout">
</form>
{% endblock %}
fill_workout.html
{% extends 'Trainmate/main.html' %}
{% block content %}
<h1>Fill workout with sets</h1>
<form id="form_container" method="POST" action="">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<div class="set_form">
{{ form.as_p }}
</div>
{% endfor %}
<button id="add-form" type="button">Add another set</button>
<button type="submit"> Create Cycle</button>
</form>
let set_form = document.querySelectorAll(".set_form")
let container = document.querySelector("#form_container")
let add_button = document.querySelector("#add_form")
let total_forms = document.querySelector("#id_form-TOTAL-FORMS")
let form_num = set_form.length -1
add_button.addEventListener('click',add_form)
function add_form(e){
e.preventDefault()
let new_form = set_form[0].cloneNode(true)
let form_regex = RegExp(`form-(\\d){1}-`,'g')
form_num ++
new_form.innerHTML = new_form.innerHTML.replace(form_regex, `form-${form_num}-`)
container.insertBefore(new_form, add_button)
total_forms.setAttribute('value', `${form_num + 1}`)
}
{% endblock %}
I tried to run the server and complete the form with the name and description of the workout object without the javascript part of the template above, I still get the same error.
Sorry for the long post and the , I have been trying to narrow down my problem as much as I can before posting, but it seems I get nowhere.
You need to initialise the fields when you define them in your models, you are missing the parenthesis () from your model fields in the Cycle model
class Cycle(models.Model):
place_in_workout = models.IntegerField()
exercise = models.ManyToManyField(Exercise)
number_of_times = models.IntegerField()
reps = models.IntegerField()
break_inbetween = models.IntegerField()
workout = models.ManyToManyField(Workout)
So I want to let a user message another user. I want the 'sender' field automatically to be 'request.user' and the receiver field to be the user whom the sender clicked on through their profile page. How would I go about passing those into the form?
matches.html
<div class="container">
<p>Username: {{ profile }}</p>
<h5>Your Matches:</h5>
{% for item in match %}
<br>
<p>Username: <br>{{ item.username}}</p>
<img src="{{ item.photo.url }}" width="300">
<p>Bio: <br>{{ item.description }}</p>
<br>
{% endfor %}
</div>
forms.py/InstantMessageForm
class InstantMessageForm(forms.ModelForm):
class Meta:
model = InstantMessage
fields = ('receiver','sender','message')
def save(self, commit=True):
user = super(InstantMessageForm, self).save(commit=False)
user.receiver = cleaned_data['receiver']
user.sender = cleaned_data['sender']
user.message = cleaned_data['message']
if commit:
user.save()
return user
views.py/instant_message
def instant_message(request):
if request.method == 'POST':
form = InstantMessageForm(request.POST)
if form.is_valid():
form.save()
return redirect('dating_app:home')
else:
form = InstantMessageForm()
context = {'form':form}
return render(request, 'dating_app/instant_message_form.html',context)
models.py
class InstantMessage(models.Model):
receiver = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
sender = models.ForeignKey(settings.AUTH_USER_MODEL, related_name= 'sender',on_delete=models.CASCADE )
message = models.TextField()
class InstantMessage(models.Model):
receiver = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
sender = models.ForeignKey(settings.AUTH_USER_MODEL, related_name= 'sender',on_delete=models.CASCADE )
message = models.TextField()
instant_message_form.py
{% extends "dating_app/base.html" %}
{% load bootstrap4 %}
{% block content %}
<h1>Start chatting now!</h1>
<div class='container'>
<form method="post" action="{% url 'dating_app:instant_message' %}" >
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Register</button>
</form>
</div>
{% endblock content %}
You can create a form without the sender field:
class InstantMessageForm(forms.ModelForm):
class Meta:
model = InstantMessage
fields = ('receiver', 'message')
Then in the view, you can inject the request.user as the .sender of .instance wrapped in the form:
from django.contrib.auth.decorators import login_required
#login_required
def instant_message(request):
if request.method == 'POST':
form = InstantMessageForm(request.POST)
if form.is_valid():
form.instance.sender = request.user
form.save()
return redirect('dating_app:home')
else:
form = InstantMessageForm()
context = {'form':form}
return render(request, 'dating_app/instant_message_form.html',context)
Note: You can limit views to a view to authenticated users with the
#login_required decorator [Django-doc].
In order to set the receiver, your url should for example contain the a primary key of the receiver. You can then remove the receiver from the form as well, and thus use:
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404
#login_required
def instant_message(request, receiver_id):
if request.method == 'POST':
form = InstantMessageForm(request.POST)
if form.is_valid():
form.instance.sender = request.user
form.instance.receiver = get_object_or_404(get_user_mode(), pk=receiver_id)
form.save()
return redirect('dating_app:home')
else:
form = InstantMessageForm()
context = {'form':form}
return render(request, 'dating_app/instant_message_form.html',context)
You of course need then to alter the urls.py accordingly and the action url, such that it includes the primary key of the receiver.
I have created a OnetoOne model for some user preference checkboxes. This is mapped to the User, and using signals I create it when the user is created. Here is what I have so far:
Model:
class DateRegexes(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
prefix_1 = models.NullBooleanField()
prefix_2 = models.NullBooleanField()
prefix_3 = models.NullBooleanField()
prefix_4 = models.NullBooleanField()
prefix_5 = models.NullBooleanField()
prefix_6 = models.NullBooleanField()
prefix_7 = models.NullBooleanField()
prefix_8 = models.NullBooleanField()
prefix_9 = models.NullBooleanField()
#receiver(post_save, sender=User)
def create_date_regexes(sender, instance, created, **kwargs):
if created:
DateRegexes.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_date_regexes(sender, instance, **kwargs):
instance.date_prefs.save()
Form:
class DatePreferenceForm(forms.ModelForm):
class Meta:
model = DateRegexes`
View:
#login_required
def set_date_preferences(request):
if request.method == 'POST':
form = DatePreferenceForm(request.POST)
if form.is_valid():
form.save()
else:
date_prefs = get_object_or_404(DateRegexes, user=request.user)
form = DatePreferenceForm(instance = request.user.date_prefs)
return render(request, 'set_date.html', {'form': form})
Template:
{% extends 'base.html' %}
{% block title %}Date Preferences{% endblock %}
{% block content %}
{% if user.is_authenticated %}
<p>logout</p>
<form method="post">
{% csrf_token %}
{% for field in form.visible_fields %}
<div>here {{ field }}</div>
{% endfor %}
<button type="submit">Set</button>
</form>
</div>
{% else %}
<p>You are not logged in</p>
login
{% endif %}
{% endblock %}
When I execute this, the first thing that happens is that the expected checkboxes that are filled in according to their previously selected preferences, I get a bunch of dropboxes that each say:
"Unknown", "Yes", "No".
1) How can I get it show html checkboxes instead of the dropboxes?
2) When I submit the form I get:
IntegrityError at /db/set_date_preferences/
NOT NULL constraint failed: db_dateregexes.user_id
Which I understand that it is having trouble associating my form to the logged in user, but I'm not sure what the right way to associate this should be
You're using a NullBooleanField which can have 3 values: None, True or False. So the default widget to render such a field is a dropdown. If you want a checkbox you should decide what you want None to map to and override the fields in the DatePreferenceForm to be a BooleanField.
Second, since every user already has prefs you should initialise your form with the correct instance, even in the POST case. I don't really understand how your form can be valid since user is a required field (you should really exclude it from the form).
class DatePreferenceForm(forms.ModelForm):
class Meta:
model = DateRegexes
exclude = ['user']
# View
def set_date_preferences(request):
if request.method == 'POST':
form = DatePreferenceForm(request.POST, instance=request.user.date_prefs)
if form.is_valid():
form.save()
# would be good practice to redirect to a success page here
else:
date_prefs = get_object_or_404(DateRegexes, user=request.user)
form = DatePreferenceForm(instance = request.user.date_prefs)
return render(request, 'set_date.html', {'form': form})
I have a DetailView, in which I show contents of a post and as well I wanted to add comments functionality to that view. I found 2 ways to do it: combine a DetailView and FormView or make a custom view with mixins. Since I am new to Djanfgo, I went on the 1st way, guided by this answer: Django combine DetailView and FormView but i have only a submit button and no fields to fill on a page.
Here is a necessary code:
#urls.py
from . import views
app_name = 'bankofideas'
urlpatterns = [
path('<int:pk>/', views.DetailView.as_view(), name='idea'),
path('<int:idea_id>/vote', views.vote, name='vote'),
path('<formview', views.MyFormView.as_view(), name='myform')
]
#views.py
class DetailView(generic.DetailView):
model = Idea
template_name = 'bankofideas/detail.html'
context_object_name = 'latest_question_list'
def get_queryset(self):
return Idea.objects.filter(pub_date__lte=timezone.now())
def get_context_data(self, **kwargs): # передача формы
context = super(DetailView, self).get_context_data(**kwargs)
context['comment_form'] = CommentForm#(initial={'post':
self.object.pk})
return context
class MyFormView(generic.FormView):
template_name = 'bankofideas/detail.html'
form_class = CommentForm
success_url = 'bankofideas:home'
def get_success_url(self):
post = self.request.POST['post']
Comment.objects.create()
return '/'
def form_valid(self, form):
return super().form_valid(form)
#models.py
class Idea(models.Model):
main_text = models.CharField(max_length=9001, default='')
likes = models.IntegerField(default=0)
pub_date = models.DateTimeField('date published',
default=timezone.now)
def __str__(self):
return self.main_text
def save(self, *args, **kwargs):
''' On save, update timestamps '''
if not self.id:
self.pub_date = timezone.now()
#self.modified = timezone.now()
return super(Idea, self).save(*args, **kwargs)
class Comment(models.Model):
post = models.ForeignKey(Idea, on_delete=models.PROTECT) #
related_name='comments',
user = models.CharField(max_length=250)
body = models.TextField(default=' ')
created = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.body
def get_absolute_url(self):
return reverse('post_detail', args=[self.post.pk])
#forms.py
from .models import Idea, Comment
from django import forms
class IdeaForm(forms.ModelForm):
class Meta:
model = Idea
fields = ('main_text',)
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
exclude = ['post', 'datetime']
#detail.html
{% extends 'base.html' %}
{% load bootstrap3 %}
{% block body %}
<div class="container">
<p>{{ idea.main_text }} {{ idea.likes }} like(s)</p>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'bankofideas:vote' idea.id %}" method="post">
{% csrf_token %}
<input type="submit" name="likes" id="idea.id" value="{{ idea.likes }}" />
</form>
{% for comment in idea.comment_set.all %}
<p>{{comment.body}}</p>
{% empty %}
<p>No comments</p>
{% endfor %}
<form action="{% url "bankofideas:myform" %}" method="post">
{% csrf_token %}
{{ myform. }}
<input type='submit' value="Отправить" class="btn btn-default"/>
</form>
</div>
{% endblock %}
As a result, I have an ability to see post, read all comments, like it, but cannot leave a comment. I tried to rename the form both in view and template, but it didn't work.
The question is: What should i do to bring comment form on the page?
I'm trying to allow users to create category and post(that will be tagged to some category) I think I wrote the code right, but I'm getting 404 error with No Post matches the given query.
Here is my code.
this is my form
class CategoryForm(forms.ModelForm):
name = forms.CharField(max_length=128, help_text="aa")
likes = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
slug = forms.CharField(widget=forms.HiddenInput, required=False)
class Meta:
model = Category
fields =('name',)
class PostForm(forms.ModelForm):
title = forms.CharField(max_length=128, help_text="bb")
views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
class Meta:
model = Post
fields = ['title', 'content', 'image', 'views', 'category']
this is my view
#for adding category
def add_category(request):
if request.method == 'POST':
form = CategoryForm(request.POST)
if form.is_valid():
form.save(commit=True)
return index(request)
else:
print form.errors
else:
form = CategoryForm()
return render(request, 'main/add_category.html', {'form':form})
#for adding post/see diff style :)
def add_post(request):
context = RequestContext(request)
if request.method == "POST":
form = PostForm(request.POST, request.FILES)
if form.is_valid():
form.save(commit=True)
return redirect(index)
else:
print form.errors
else:
form = PostForm()
return render_to_response('main/add_post.html', {'form':form}, context)
And this is my url
url(r'^add_post/', views.add_post, name='add_post'),
url(r'^add_category/$', views.add_category, name='add_category'),
]
And finally my templates
{
% extends 'base.html' %}
{% block content %}
<form id="post_form" method="post" action="/main/add_post/" enctype="multipart/form-data">
{% csrf_token %}
{{form}}
<input type="submit" name="submit" value="Create Post">
</form>
{% endblock %}
You should use action="{% url 'main:add_post' %}" instead of action="/main/add_post/".
Also check that in your projects's urls.py main app's urls included with namespace like
url(r'^main/', include('main.urls', namespace="main"))
If you don't use namespace, than change to action="{% url 'add_post' %}".
If error reoccurs, please provide more information.
Which ulr exactly you enter in browser to get this error?
Your template makes the form post to main/add_post/ while your url for the view is add_post/. You should make them consistent.