sorry for all the code given but i have tried so hard for a day still ending up with a problem when passing stage_id as a parameter in the form action url
I have a class Rapports that holds a file (i prefer pdf files) and have a 1to1 relationship with an other class from an other application, i'm sending the stage.id from a html page in Stages app and it's working the id is passed and i can pass it to an other html page but when i write the code i need and passe the same url pattern in the action attribute of the template i want to show(rapport/test.html down below) it return NoReverseMatch and i can't figure out why. Is it because i'm trying to upload a file or is it something else? (1st time working with files)
{% block rpt %}
<li class="nav-item">
<a class="nav-link" href="{% url 'rapport:depo' stages.id %}">
déposer le rapport
</a>
</li>
{% endblock rpt %}
rapport.Rapports
from django.db import models
from satges.models import Stages
class Rapports(models.Model):
stage=models.OneToOneField(
Stages,
on_delete=models.CASCADE,
primary_key=True,
)
src=models.FileField(
("rapport"),
upload_to='rapports/',
max_length=100
)
r_soummit=models.DateTimeField(
auto_now=False,
auto_now_add=False,
)
satges.Stages
class Stages(models.Model):
#Stages attrs that are saved so i think no need to show them here
def est_ete(self):
# comment: this fn returns true if it's a summer intership
if(self.deb.month in[6,7,8]):
return True
# end def
def get_absolute_url(self):
return reverse("satges:det_stg", kwargs={"pk": self.pk})
#saving Stages to database with CreateView is working
def __str__(self):
return self.etd + ' ' + self.nature + " - " + self.au
rapport.forms.py
from django import forms
from .models import Rapports
class RapportsForm(forms.ModelForm):
class Meta:
model = Rapports
fields = ['src']
widgets = {
'src': forms.FileInput(),
}
rapport.views
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, render
from django.views.generic import CreateView
from satges.models import Stages
from .models import Rapports
from .forms import RapportsForm
# Create your views here.
def afficher(request, stage_id):
# comment:
#return HttpResponse('stage: %s'% stage_id)
if request.method == 'POST':
form = RapportsForm(request.POST, request.FILES)
else:
form=RapportsForm()
return render(request, 'rapport/test.html', {'form': form})
class RapportCreateView(CreateView):
model = Rapports
form_class=RapportsForm
template_name = "rapport/test.html"
# end def
'''
def afficher_depo(request, stage_id):
form=RapportsForm()
print(stage_id)
return render(request,'rapport/depo.html', {'form': form})
def depo(request, stage_id):
if request.method == 'POST':
form = RapportsForm(request.POST)
stage=get_object_or_404(Stages, pk=stage_id)
src = form.cleaned_data['src']
rpt=Rapports(stage=stage,src=src)
rpt.save()
else:
return HttpResponse('rapport isn\'t saved')
return render(request,'rapport/depo.html', {'form':form})
'''
the project url conf
from django.contrib import admin
from django.urls import include, path
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('satges.urls')),
path('journal/', include('journaux.urls')),
path('rapport/<int:pk>', include('rapport.urls')),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
rapport.urls.py
from django.urls import path, re_path
from . import views
app_name = 'rapport'
urlpatterns = [
path('',views.RapportCreateView.as_view(), name='depo'),
]
test.html (this file is just for testing the main file is called depo.html and it extends otthe page and have the same behavior when i remove the url in action the form appears)
<html>
<head>
<title>test</title>
</head>
<body>
<form method="post" enctype="multipart/form-data" action="{% url 'rapport:depo' satge_id %}">
<!--when i remove the url tag the input form appears and i can choose a file but i ofc can't send it without the action-->
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="déposer votre rapport" name="depo">
</form>
</body>
</html>
this should be all the code related to the problem, i have tried googling, youtube, django doc and with the changes i made along the day the errors differed but the one i couldn't get through is NoReverseMatch
error
Error during template rendering
In template /home/ssoya/Documents/pfe/new/pages/templates/rapport/test.html, error at line 6
Reverse for 'depo' with arguments '('',)' not found. 1 pattern(s) tried: ['rapport/(?P<pk>[0-9]+)\\Z']
after the 1st answer my view became like this but no matter i change it still no use
class RapportsCreateView(CreateView):
model = Rapports
form_class=RapportsForm
template_name = "rapport/depo.html"
def get_context_data(self, **kwargs):
context=super(RapportsCreateView, self).get_context_data(**kwargs)
#stage=Stages.objects.get(pk=self.kwargs.get('pk'))
context['stages'] = Stages.objects.filter(pk=self.kwargs.get('pk'))
return context
then i tried something else: I replaced stage.id with 1 then 13 to see what happens. It raised IntegrityError
NOT NULL constraint failed: rapport_rapports.stage_id
The above exception (NOT NULL constraint failed: rapport_rapports.stage_id) was the direct cause of the following exception:
response = get_response(request)
i'm willing to restructure the question once i found a soloution or understand it more
it's because of stage_id as it's not defined so url will not be found as it needs the parameter stage_id, check the view that rendering your template it is not retuning the stage_id variable
add this to your create view
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# context is a dict so
#update it with your stage id
return context
in this function add the stage_id so it get passed to the template
i can say it is 90% Solved
the problem i had in this question was related to the context in my view and after the answer of #mohamed and some googling and tries i made the view ended up working and saving the file to the server and the database and putting the id of the Satges object as the id of rapport as the attribute satge_id then redirects the user to an other page
here are the modifications i made
views.py
class RapportsCreateView(CreateView):
model = Rapports
form_class = RapportsForm
template_name = "rapport/depo.html"
def form_valid(self, form):
self.stage_id = self.kwargs['pk']
stage = Stages.objects.get(id=self.stage_id)
form.instance.stage_id = stage.id
form.instance.r_soummit = timezone.now()
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
stage = Stages.objects.get(pk=self.kwargs.get('pk'))
context['stage'] = stage
context['stage_id'] = stage.id
return context
models.Rapports
def get_absolute_url(self):
return reverse("rapport:det_rpt", kwargs={"pk": self.pk})
def __str__(self):
return self.src
Related
I created an app called "jobs", basically I'd like to create new "jobs" from the admin console and be able to post it on the jobs.html page.
I created the model and views but I think there is something wrong with the views that doesn't allow me to print the "jobs" on the html template.
Can you please tell me if the error is in views.py?
jobs/models.py
from django.db import models
# Create your models here.
class post_job(models.Model):
posizione= models.TextField(max_length=20)
descrizione= models.TextField(max_length=20)
requisiti= models.TextField(max_length=20)
def __str__(self):
"""String for representing the MyModelName object (in Admin site etc.)."""
return self.posizione
jobs/admin.py
from django.contrib import admin
from .models import post_job
# Register your models here.
admin.site.register(post_job)
jobs/views.py
from django.shortcuts import render
from .models import post_job
# Create your views here.
def viz_job(request):
posizione = post_job.posizione
print(posizione)
return render(request,'jobs/jobs.html',{'posizione':posizione})
Proper answer:
In your views:
from django.shortcuts import render
from .models import PostJob # proper naming
def viz_job(request):
jobs = PostJob.objects.all()
return render(request,'jobs/jobs.html',{'jobs': jobs})
in your template:
<ul>
{% for job in jobs %}
<li>
<h3>{{ job.posizione }}</h3>
<div>
{{ job.descrizione }}
</div>
</li>
{% endfor %}
</ul>
Note that all this is documented.
NB: if you're only interested in those two fields and don't need any of the model's methods, related objects or whatever, you can optimize the query a bit by using a values queryset that will yield dicts with the selected fields instead of full model instances:
jobs = PostJob.objects.values("posizione", "descrizione")
Everything else remains the same.
You have to know what do you want to return for the template, for example in the views.py :
from django.shortcuts import render
from .models import post_job
# Create your views here.
def viz_job(request):
jobs = []
descriziones = []
posizione = Job.objects.all()
for pos in posizione:
jobs.append(pos.posizione)
descriziones.append(pos.descrizione)
context = {
'posizione': jobs,
'descrizione': descriziones
}
return render(request, 'jobs/jobs.html',
context=context) # this will return context dictonary to the template
You can filter and get to fetch specific data from your database
I'm very new to Python and am building a basic blog in django. I am trying to enable editing of individual blog posts. I have to 'get' these individual blog posts so I can edit them. So far, the system isn't liking my '.get' method and shows me a ValueError. I have tried changing the value type to int, str, float, even complex. It all either returns the same or says it doesn't like 'id' or even 'pk' if I change it to that.
Here is the code.
views.py
from django.shortcuts import render
from blogs.models import BlogPost
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from .forms import PostForm
def index(request):
"""The home page for blogs"""
blogposts = BlogPost.objects.order_by('date_added')
context = {'blogposts': blogposts}
return render(request, 'blogs/index.html', context)
def blogpost(request, blogpost_id):
"""Show a single post"""
postings = BlogPost.objects.get(id=blogpost_id)
context = {'postings': postings}
return render(request, 'blogs/blogpost.html', context)
def new_post(request):
"""Writ a new post to the blog"""
if request.method != 'POST':
# No data submitted; create a blank form.
form = PostForm()
else:
# POST data submitted; process data
form = PostForm(data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('blogs:index'))
context = {'form': form}
return render(request, 'blogs/new_post.html', context)
def edit_entry(request, entry_id):
"""Edit an existing entry"""
entry = BlogPost.objects.get(id=entry_id)
if request.method != 'POST':
# Initial request; pre-fill form with the current entry
form = PostForm(instance=entry)
else:
# POST data submitted; process data
form = PostForm(instance=entry, data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('blogs:blogpost', args[entry_id]))
context = {'entry': entry, 'form': form}
return render(request, 'blogs/edit_entry.html', context)
If you'll notice, under def blogpost(request, blogpost_id):, I was able to employ the .get method in the same exact way and it was successful. What's more, the .get should work as an int anyway since the link is a whole number.
models.py
from django.db import models
class BlogPost(models.Model):
"""A blog post"""
title = models.CharField(max_length=200)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
"""Return a string rep of model"""
return (str(self.title + " : " + self.text))
urls.py
"""URL Configs for app blogs"""
from django.conf.urls import url
from blogs import views
urlpatterns = [
#Home page
url(r'^$', views.index, name='index'),
#Individual Postings Pages
url(r'^(?P<blogpost_id>\d+)/$', views.blogpost, name='blogpost'),
#New Post Page
url(r'^new_post$', views.new_post, name='new_post'),
#Page for editing a post
url(r'^edit_entry/(?P<entry_id>)/$', views.edit_entry, name='edit_entry'),
]
For the
(?P<entry_id>)/$', I did take out the portion,\d+ , because the system read the '\' back as '\\' so I took it out.
forms.py
from django import forms
from .models import BlogPost
class PostForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['text']
labels = {'text':''}
widgets = {'text': forms.Textarea(attrs={'cols':80})}
What can I do to isolate and get the specific posts to edit them?
Thanks to anyone who answers this, in advance.
========================================================================
#Alasdair
I did add \d+ to the url and this is what I received...
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/edit_entry//
Using the URLconf defined in blog.urls, Django tried these URL patterns, in this order:
^admin/
^ ^$ [name='index']
^ ^(?P<blogpost_id>\d+)/$ [name='blogpost']
^ ^new_post$ [name='new_post']
^ ^edit_entry/(?P<entry_id>\d+)/$ [name='edit_entry']
The current URL, edit_entry//, didn't match any of these.
You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.
Also, when I do that, it changes the behavior of the individual blog post. I get this response of the detailed view of the original post:
Exception Type: NoReverseMatch
Reverse for 'edit_entry' with arguments '('',)' and keyword arguments '{}' not found. 1 pattern(s) tried: ['edit_entry/(?P<entry_id>\\d+)/$']
{% block content %}
<p>This is supposed to be for one post</p>
<p>{{ postings }}</p>
<p>Edit entry:</p>
edit entry
{% endblock content %}
The exception message you get is because you are trying to parse the empty string as an integer int(""). That operation makes no sense. The id pattern in the url should be at least one character.
(?P<entry_id>) is a completely useless pattern, since it contains no characters. It will always match an empty string '' and pass that to your view function.
(?P<entry_id>)/$, I did take out the portion,\d+ , because the system read the \ back as \\ so I took it out.
That's how it's supposed to work. There's no reason to take anything out.
I am trying to have a simple form that once filled, will direct to a different webpage or remain on the same page if invalid. The page should have a text box and submit form and once a user enters anything it should direct you to a separate page.
My directory structure is as follows:
appName/
app/
forms.py
urls.py
views.py
templates/
app/
goodbye.html
name.html
library.html
thanks.html
appName/
settings.py
urls.py
My app/urls.py is as follows:
from django.conf.urls import url
from . import views
app_name = 'app'
urlpatterns = [
url(r'^$', views.index2, name = 'index'),
url(r'^hello/$', views.hello, name = 'hello'),
url(r'^goodbye/$', views.goodbye, name = 'goodbye'),
#url(r'^library$', views.library, name = 'library'),
url(r'^library/$', views.library, name = 'library'),
url(r'^library/(?P<book_id>[0-9]+)/$', views.book, name = 'book'),
url(r'^getname/$', views.get_name, name = 'get_name'),
url(r'^your-name/$',views.get_name, name='get_name'),
url(r'^thanks/$',views.say_thanks,name='thanks'),
#url(r'^thanks/(?P<name_id>[a-zA-Z]+)/$', views.say_thanks,name='thanks'),
]
My forms.py is :
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label = 'Your name', max_length=100)
My app/views.py is:
from django.http import HttpResponse
from django.template import loader
from django.shortcuts import render
from django.http import HttpResponseRedirect
#forms
from .forms import NameForm
# Create your views here.
def index2(request):
return HttpResponse("hello world")
def hello(request):
text = """<h1>Welcome to my app! </h1>"""
return HttpResponse(text)
def goodbye(request):
template = loader.get_template("app/goodbye.html")
context = {
'output' : 'This is output from goodby views.py request handler'
}
return HttpResponse(template.render(context,request))
def library(request):
template = loader.get_template("app/library.html")
context = {
'output' : 'Welcome to the libary!!'
}
return HttpResponse(template.render(context, request))
def book(request, book_id):
return HttpResponse("You're looking at book %s. " % book_id)
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
#process the data in form.cleaned_data as required
locationGo = "/thanks/"
template = loader.get_template("app/thanks.html")
return HttpResponse(template.render({'name':'name'},request))
else:
form = NameForm()
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
def say_thanks(request):
template = loader.get_template("app/thanks.html")
return HttpResponse(template.render({'name': 'name'},request))
My templates include:
name.html :
<form action = "/getname/" method = "post">
{% csrf_token %}
{{ form }}
<input type = "submit" value = "Submit" />
</form>
goodbye.html
<h1>Goodbye to Template Romance</h1>
Go Back
thanks.html
Thanks {{name}}!
What I would like is for:
A user to visit to : website.com/getname/ to show the name.html file (which it does)
If a user hits submit to stay on the same page (website.com/getname/) (which it doesn't - it gives: ValueError at /getname/ ->The view app.views.get_name didn't return an HttpResponse object. It returned None instead.
If a user enters in the submit field, to be redirected to website.com/thanks/ (which it sort of does. It currently loads the thanks.html template, but the URL stays on website.com/getname/)
Inside the get_name(request): function, the POST and GET if...else doesn't seem to be firing based on the Submit button, and it doesn't seem to be loading the correct page, OR change the current URL address once it gets processed. I have tried using HttpRedirect() which works, however, I would also like to pass the forms data (which is another issue).
Any suggestions would be a big help!
Your first problem is that you are not returning a response when the request method is post and the form is invalid. You can fix that by changing the indentation of your view, so that you always return a response at the end of your view.
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
...
else:
form = NameForm()
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
If you want to redirect to the /thanks/ view, then you can use the redirect shortcut.
if form.is_valid():
return redirect('thanks')
Note that it isn't possible to redirect and pass the form data (see this question for an explanation). You should do any processing you want with the data before redirecting. You could use the messages framework to create a message 'Thanks <name>' before redirecting.
This works because you have name='thanks' in your url pattern.
You can simplify your views by using the render shortcut. Instead of
template = loader.get_template("app/name.html")
context = {'form': form}
return HttpResponse(template.render(context, request))
you can simply do:
return render(request, "app/name.html", context)
Remember to add the imports for the shortcuts:
from django.shortcuts import redirect, render
I am new to Django. I am trying to make a simple web app which contains some name of stocks then you have to click on one then next window will be of what data you want like "Get percentage change" and then it will show the percentage change in that stock. I know some part of code should be better but I am just trying different parts of Django. I am getting problem in second part, after selecting stock, I am getting error and I have tried my best but not able to remove it.
This is my urls.py file:
# project/stocks.urls.py
from django.conf.urls import patterns, url
from stocks import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
url(r'^(?P<stocks_id>\d+)/$', views.choice, name='choice'),
url(r'^(?P<stocks_id>\d+)/(?P<choice_id>\d+)/$', views.data, name='data')
)
This is my views file:
# project/stocks.views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.template import RequestContext, loader
from stocks.models import Stocks, DataChoice
from NewStock_API import Get_Quote, Get_percent_change
from django.views import generic
def index(request):
latest_stocks = Stocks.objects.all()
context = {'latest_stocks': latest_stocks}
return render(request, 'stocks/index.html', context)
def choice(request, stocks_id):
total_choice = DataChoice.objects.all()
context = {'total_choice': total_choice}
return render(request, 'stocks/choice.html', context)
def data(request, stocks_id, choice_id):
selected_stock = Stocks.objects.get(id=stocks_id)
selected_symbol = selected_stock.symbol
stocks = Get_Quote(selected_symbol)
return render(request, 'stocks/data.html', {'stocks': stocks})
This is my models file:
# project/stocks.models.py
from django.db import models
class Stocks(models.Model):
symbol = models.CharField(max_length=20)
def __unicode__(self):
return self.symbol
class DataChoice(models.Model):
choice_text = models.CharField(max_length=20)
def __unicode__(self):
return self.choice_text
The error I am getting is:
Error during template rendering
In template /home/mukesh/markets/stocks/templates/stocks/choice.html, error at line 3
Reverse for 'data' with arguments '(1,)' and keyword arguments '{}' not found. 1 pattern(s) tried:
[u'stocks/(?P<stocks_id>\\d+)/(?P<choice_id>\\d+)/$']
My choice.html file is:
<ul>
{% for choice in total_choice %}
<li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>
Your data url pattern takes two arguments a stock id and a choice id; you are only supplying one.
You need to supply both, like this:
{% url 'stocks:data' stocks_id=stocks.id choice_id=choice.id %}
I am trying to pass the id through reverse. But it's not working. I'm getting this error
Reverse for 'reg.views.thanks' with arguments '(20,)' and keyword arguments '{}' not found.
Here is my views.py:
from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.core.urlresolvers import reverse
from reg.models import registration, registrationform
from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext
def registration(request):
if request.method == 'POST':
form = registrationform(request.POST)
if form.is_valid():
data = form.save()
id = data.id
return thanks(request,id)
else:
form = registrationform()
return render_to_response('registration.html', {'form' : form}, context_instance=RequestContext(request))
def thanks(request, id):
p = get_object_or_404(registration, pk=id)
return render_to_response('thanks.html', {'reg' : p})
Here is my urls.py:
from django.conf.urls import patterns, include, url
url(r'^registration/$', 'reg.views.registration'),
url(r'^thanks/$', 'reg.views.thanks'),
url(r'^$','django.views.generic.simple.direct_to_template', {'template' : 'index.html'}),
)
Here is thanks.html:
<html>
<body>
<p>Thank you for registration mr.{{reg.username}}</p>
</body>
</html>
and I'm also showing my models.py:
from django.db import models
from django.forms import ModelForm
class registration(models.Model):
username = models.CharField(max_length=100)
password = models.CharField(max_length=100)
def __unicode__(self):
return self.name
class registrationform(ModelForm):
class Meta:
model = registration
Thanks.
from this links (django tutorial):
https://docs.djangoproject.com/en/dev/topics/http/urls/#django.core.urlresolvers.reverse
example:
def myview(request):
return HttpResponseRedirect(reverse('arch-summary', args=[1945]))
so your code goes to:
in urls.py:
url(r'^thanks/(?P<id>\d+)$', 'reg.views.thanks', name='my_thanks_url')
in your function:
return HttpResponseRedirect(reverse('my_thanks_url', args=[id]))
This line
return HttpResponseRedirect(reverse('reg.views.thanks', args=(id,)))
Is trying to construct a url to your view reg.views.thanks, with the id variable used as a parameter.
This line in urls.py
url(r'^thanks/$', 'reg.views.thanks'),
Does not have anywhere for that parameter to go.
The first thing that you need to figure out is whether you actually want to send an HTTP redirect to the browser to tell it to go to the 'thanks' page. If you really do, then you need a way to send that id in the URL. You can do it as part of the URL path itself, as #moguzalp suggests, or you can put it in the query string, like
/thanks/?id=12345
Or you can do other things, like stashing the id in the user's session, and pulling it out when they request the thanks page. That's a bit more complicated, though.
If you don't actually need to issue an HTTP redirect, then there's nothing stopping you from just calling the thanks() function from inside your view function, like this:
def registration(request):
if request.method == 'POST':
form = registrationform(request.POST)
if form.is_valid():
data = form.save()
id = data.id
return thanks(request, id)
else:
form = registrationform()
return render_to_response('registration.html', {'form' : form}, context_instance=RequestContext(request))
The URL won't change in the browser, but the correct ID will be used, and doesn't need to appear anywhere else, in the URL, the query parameters, or the session