Im new to Django, and im trying to understand, why my code instead of redirect to :
http://127.0.0.1:8000/object/2/
redirect me to:
http://127.0.0.1:8000/object/2/?c=14
Where is the code, that adds this parameters?
Template:
{% if user.is_authenticated %}
{% get_comment_form for object as comment_form %}
<form action="{% comment_form_target %}" method="POST">
{% csrf_token %}
{{ comment_form.comment }}
{{ comment_form.content_type }}
{{ comment_form.object_pk }}
{{ comment_form.timestamp }}
{{ comment_form.security_hash }}
<input type="hidden" name="next" value="{{ object.get_absolute_url }}" />
<input type="submit" value="post comment" />
</form>
{% else %}
<p>Please log in to leave a comment.</p>
{% endif %}
views.py:
class realiz_photo_view(DetailView):
template_name = 'realization/realiz_photo.html'
model = realiz_photo
def get_context_data(self, **kwargs):
context = super(realiz_photo_view, self).get_context_data(**kwargs)
context["form"] = RealizationForm()
return context
urls.py:
url(r"^comments/", include("django.contrib.comments.urls")),
url(r'^object/', include('realization.urls')),
realization/urls.py:
urlpatterns = patterns('',
url(r'^(?P<pk>\d+)/$', realiz_photo_view.as_view()),
)
See my solution here: Django: Redirect to current article after comment post
It basically uses a view that's triggered by the comment post url which redirects back to the original referrer page.
Related
I have a form that is based on a ModelForm in my forms.py. I initially get the blank form as expected, however when filling out the form and hitting submit nothing happens. I am not sure where I am going wrong.
views.py
def add_customer(request):
# print(customer_form)
# print(customer_form.errors)
print(request.method)
print(request.POST)
customer_form = CustomerForm(request.POST or None)
if customer_form.is_valid() and request.method == 'POST':
form = CustomerForm(request.POST)
form.save()
return redirect('AdminPortal:customers')
print('posted')
else:
print('failing')
context = {'customer_form': customer_form,}
return render(request, 'add_customer.html', context=context)
urls.py
path("customers/", views.customers, name="customers"),
path("customers/customer/<int:id>/", views.customer, name="customer"),
path("add_customer/", views.add_customer, name="add_customer"),
forms.py
class CustomerForm(forms.ModelForm):
class Meta:
model = AppCustomerCst
fields = ('is_active_cst', 'name_cst', 'address_1_cst', 'address_2_cst', 'address_3_cst',
'city_cst', 'state_cst', 'zip_cst', 'country_cst', 'salesrep_cst', 'type_cst',
'is_allowed_flat_cst', 'iddef_cst', 'balance_notify_cst', 'receive_emails_cst',
'contact_domain_cst'
)
add_customer.py [form portion]
<form method="post" action='AdminPortal:add_customer'>
{% csrf_token %}
{{ customer_form }}
<button type="button" value="submit">Submit</button>
<button type="button" value="cancel">Cancel</button>
</form>
It looks like the form doesn't know where to post.
You need to turn it into a django url template tag. So I'd do something like this for your form;
<form method="post" action='{% url "AdminPortal:add_customer" %}'>
{% csrf_token %}
{% if form.non_field_errors %}
{{ form.non_field_errors }}
{% endif %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
<button type="button" value="submit">Submit</button>
<button type="button" value="cancel">Cancel</button>
</form>
To find what's happening in your view I'd recommend simplifying the logic somewhat so that it's more inline with the docs here; https://docs.djangoproject.com/en/3.1/topics/class-based-views/intro/#handling-forms-with-class-based-views
Because you're doubling up the check for post & valid, I suspect you're never seeing the validation errors because they'd only come from that block of code. So change your view to be something like this and if you updated your template as above you should see some errors;
def add_customer(request):
if request.method == 'POST':
form = CustomerForm(request.POST)
if form.is_valid():
form.save()
return redirect('AdminPortal:customers')
else:
form = CustomerForm()
return render(request, 'add_customer.html', {'customer_form': form})
I found my error in the HTML Template.
I had:
<button type="button" value="submit">Submit</button>
<button type="button" value="cancel">Cancel</button>
Once Updated to:
<input type="submit" value="submit">Submit</input>
<input type="submit" value="cancel">Cancel</input>
The form posted properly as expected.
I have been trying to implement a way to post a project post where the user can upload multiple images. The multiple image upload works but posting the post itself does not work.
I am not sure what to do with the project_form.
It is not valid even tho the fields have correct values.
My code is:
views.py
class CreateProjectsView(View):
def get(self, request):
p_photos = P_Images.objects.all()
#project_form = ProjectsForm(initial=self.initial)
project_form = ProjectsForm
context = {
'p_photos': p_photos,
'project_form': project_form,
}
return render(self.request, 'projects/forms.html', context)
def post(self, request):
project_form = ProjectsForm(request.POST or None, request.FILES or None)
p_formset = P_ImageForm(request.POST, request.FILES)
# Checks if the project_form is valid before save
if project_form.is_valid():
instance = project_form.save(commit=False)
instance.user = request.user
instance.save()
# Checks if multiple image upload is valid before save
if p_formset.is_valid():
#if project_form.is_valid() and p_formset.is_valid():
#instance = project_form.save(commit=False)
#instance.user = request.user
#instance.save()
images = p_formset.save(commit=False)
images.save()
data = {
'is_valid': True,
'name': images.p_file.name,
'url': images.p_file.url
}
else:
data = {
'is_valid': False,
}
return JsonResponse(data)
forms.html
<form action="{% url 'create_post:retrieve_projects' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{% for hidden in project_form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in project_form %}
{{ field.errors }}
{{ field }} <br />
{% endfor %}
<input type="submit" value="OK">
</form>
If the form is not valid, you should provide a way for the user to correct their errors and resubmit the form. Perhaps something like this:
if project_form.is_valid():
instance = project_form.save(commit=False)
instance.user = request.user
instance.save()
else:
return render(request, 'project_form.html', {'form': project_form})
So I actually found a fix for this.
The issue is in the forms.html
I changed the "create_post:retrieve_projects" to "create_post:create_projects" in my form section.
forms.html
<form action="{% url 'create_post:create_projects' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{% for hidden in project_form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in project_form %}
{{ field.errors }}
{{ field }} <br />
{% endfor %}
<input type="submit" value="OK">
</form>
I keep getting NoReverseMatch at /music/2/ error, and it's pointing me to the parent template that i'm inheriting from, base.html, but i can't find anything wrong with it. I know it's probably annoying when someone asks you to search for errors, but maybe someone can easily see what i'm unable to see
{% extends "music/base.html" %}
{% block content %}
<p> Album : {{one_album}} </p>
<p> Song list : </p>
{% if somethings_wrong %}
<p> {{ somethings_wrong }} </p>
{% endif %}
<form action = "{% url 'music:favorite' album.id %}" method="post" >
{% csrf_token %}
{% for song in album_entries %}
<input type="radio" id="song{{forloop.counter}}" name="song" value="{{ song.id }}">
<label for="song{{ forloop.counter }}">
{{ song.song_title }}
{% if song.is_favorite %} #afterwards, set this explicitly to true, for learning purposes
<img src="https://i.imgur.com/olM72b8.png"/> #check if this slash is necessary later
{% endif %}
</label><br>
{% endfor %}
<input type="submit" value="Favorite">
</form>
{% endblock content %}
Here's the base.html
<p>
Link to the homepage
</p>
{% block content %}
{% endblock content %}
Here's the Views.py :
from django.shortcuts import render
from django.http import HttpResponse
from .models import Album, Song
def index(request):
albums = Album.objects.all()
context = {'albums': albums}
return render(request, 'music/index.html', context)
def detail(request, album_id):
# show album and every entry in that album.
one_album = Album.objects.get(id=album_id)
album_entries = one_album.song_set.all()
context = {'one_album' : one_album, 'album_entries' : album_entries}
return render(request, "music/album.html", context)
# Create your views here.
def favorite(request, album_id):
one_album = Album.objects.get(id=album_id)
try:
context = {'one_album' : one_album}
selected_song = one_album.song_set.get(id=request.POST["song"])
except(KeyError, Song.DoesNotExist):
somethings_wrong = "Something's not right with your choice"
context = {'one_album' : one_album, 'somethings_wrong' : somethings_wrong}
return render(request, "music/album.html", context)
else:
selected_song.is_favorite = True
selected_song.save()
return render(request, "music/album.html", context)
i think error is somewhere here, urls.py and models.py are pretty simple. I've added is_favorite booleanfield to Song class, which is False by default, and urls.py is pretty straightforward
path('<int:album_id>/favorite', views.favorite, name='favorite')
variable that you want to refer to is one_album
but you are calling it album.
change
<form action = "{% url 'music:favorite' album.id %}" method="post" >
to
<form action = "{% url 'music:favorite' one_album.id %}" method="post" >
My apologies if the question is stupid, I am a newbie to this. I am creating a django web application. I have created a form inside it. When I submit the form, it says 'url' not found even though the same URL loads fine for the first time when opening the form. This is whats confusing me. Here is my code:
#forms.py
class Recipe_ruleForm(forms.ModelForm):
class Meta:
model = Recipe_rule
fields = ('content',)
#urls.py
url(r"^create_recipe_rule/(?P<recipe_pk>[0-9]+)/$",views.create_recipe_rule, name="create_recipe_rule"),
#views.py
def create_recipe_rule(request, recipe_pk):
form = Knowledgebase_ruleForm
selected_recipe = Recipe.objects.get(pk = recipe_pk)
if request.method == 'POST':
form = Recipe_ruleForm(request.POST)
if form.is_valid():
#current_user = request.user
data = form.cleaned_data
recipe_rule_data=Recipe_rule.objects.create(recipe=selected_recipe, content=data['content'])
recipe_rule_data.save()
recipe_rule = Recipe_rule.objects.get(pk = recipe_rule_data.pk)
recipe=selected_recipe
recipe = Recipe.objects.get(pk = recipe.pk)
return redirect('recipe_detail', pk=recipe.pk)
else:
messages.error(request, "Error")
return render(request, 'create_recipe_rule.html' , {'form': form})
Here is the error when I submit the form:
Page not found (404) Request Method: POST Request
URL: http://[ip_adress]:[port]/create_recipe_rule/
UPDATE:
Here is my template:
{% extends "account/base.html" %}
{% load i18n %}
{% load bootstrap %}
{% block body_class %}applications{% endblock %}
{% block head_title %}{% trans "Create recipe" %}{% endblock %}
{% block body %}
<form action="/create_recipe_rule/" method="post">
{% csrf_token %}
<div class="form-group">
<label for="{{ form.content.label }}">{{ form.content.label }}:</label>
<textarea type="{{ form.content.type }}" name="{{ form.content.name }}" max_length="500" class="form-control" id="{{ form.content.id }}"></textarea>
</div>
<input class="btn btn-default" type="submit" value="submit">
</form>
{% endblock %}
You have action="/create_recipe_rule/", which is missing the recipe id.
One option is to simply remove the action from the form, then your browser will submit the request to the current url.
<form method="post">
If you do want to include the form action, then first you need to update your view so that it includes the recipe id in the template context.
return render(request, 'create_recipe_rule.html' , {'form': form, recipe_id: recipe_id })
Then you can update the form action to include the recipe id.
action="/create_recipe_rule/{{ recipe_id }}"
It's good practice to use the {% url %} tag, so that you are not hardcoding urls in the template:
action="{% url 'create_recipe_rule' recipe_id %}"
Django 1.3 documentation on class based views is seeming like a treasure hunt. How to write the class is clear enough... but what kind of template code matches each generic class? Would someone provide a complete example soup to nuts? Here's what I have so far:
urls.py
(r'^brand_create2$', BrandCreate.as_view()),
views.py
from django.views.generic import CreateView
#login_required
class BrandCreate(CreateView):
template_name = 'generic_form_popup.html'
context_object_name = "brand_thingie"
#queryset = models.Brand.objects.all()
success_url = '/'
generic_form_popup.html
????
In this case I'm exploring if it is worth learning the new style, given the older style still works:
urls.py
url(r'^brand_create1$', 'coat.views.brand_create'),
views.py
class formBrand(forms.ModelForm):
class Meta:
model = models.Brand
exclude = ('')
#login_required
def brand_create(request):
form = formBrand
if request.method == 'POST':
form = formBrand(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/')
passed = dict(
form=form,
MEDIA_URL = settings.MEDIA_URL,
STATIC_URL = settings.STATIC_URL)
return render_to_response('generic_form_popup.html',
passed, context_instance=RequestContext(request))
generic_form_popup.html
{% extends 'head-plain.html' %}
{% block title %}{% endblock %}
{% block headstuff %}{% endblock %}
{% block content %}
<form action="{{ action }}" method="post">
{% csrf_token %}{{ form.as_p }}
<input type="submit" value="Submit" /> </form>
{% endblock %}
CreateView inherits from ModelFormMixin, which in turn inherits from FormMixin and SingleObjectMixin.
SingleObjectMixin provides the object template context variable, which is probably not going to be any use in the case of CreateView:
object: The object that this view is displaying. If context_object_name is specified, that variable will also be set in the context, with the same value as object.
But FormMixin provides the form context variable:
form: The form instance that was generated for the view.
Thus, you can refer to the documentation to display a form with a template:
<form action="/contact/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Which means that the very template you posted should almost work with the class based view:
{% extends 'head-plain.html' %}
{% block title %}{% endblock %}
{% block headstuff %}{% endblock %}
{% block content %}
<form action="" method="post">
{% csrf_token %}{{ form.as_p }}
<input type="submit" value="Submit" /> </form>
{% endblock %}
I removed {{ action }} because it is not part of the context, neither in the old-style view, neither with the class based view, so it doesn't make any sense. You should know that if action="" then the browser will submit to the current url. You can force the action to the current url with action="{{ request.path }}" or you can specify another url with the url template tag.
Suppose apply the best practice of naming url patterns, by changing:
(r'^brand_create2$', BrandCreate.as_view()),
to:
(r'^brand_create2$', BrandCreate.as_view(), name='band_create'),
Then you can use: action="{% url band_create %}".
You can also customize further:
<form action="/contact/" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="fieldWrapper">
{{ form.subject.errors }}
<label for="id_subject">Email subject:</label>
{{ form.subject }}
</div>
<div class="fieldWrapper">
{{ form.message.errors }}
<label for="id_message">Your message:</label>
{{ form.message }}
</div>
<div class="fieldWrapper">
{{ form.sender.errors }}
<label for="id_sender">Your email address:</label>
{{ form.sender }}
</div>
<div class="fieldWrapper">
{{ form.cc_myself.errors }}
<label for="id_cc_myself">CC yourself?</label>
{{ form.cc_myself }}
</div>
<p><input type="submit" value="Send message" /></p>
</form>
Of course, the fields available in the form depend on your Model.