NoReverseMatch arguments django - django

Why does this return a NoReverseMatch error?
view:
def browse(request):
thing_list = Thing.objects.all()
if request.method == 'POST':
form = BrowseForm(request.POST)
if form.is_valid():
make = Make.objects.all()
return HttpResponseRedirect(reverse('browse_makes', args=[make]))
else:
form = BrowseForm()
return render(request, 'browse.html', {'form':form, 'thing_list':thing_list})
def makes(request, make):
ad_list = Thing.objects.filter(make=make)
return render(request, 'browse-makes.html', {'thing_list':thing_list})
url:
url(r'^browse/$', 'axlepost.views.browse.browse', name='browse'),
url(r'^browse/(?P<make>[\w-]+)/$', 'axlepost.views.browse.makes', name='browse_makes'),
form:
class BrowseForm(forms.Form):
make = forms.ModelChoiceField(queryset=Make.objects.all())
model:
class Make(models.Model):
make = models.CharField(max_length=20)
class Thing(models.Model):
make = models.ForeignKey(Make)
Returns Reverse for 'browse_makes' with arguments '([<Make: Samsung>],)' and keyword arguments '{}' not found.
Thanks for your ideas on how to solve this error!

You are handing reverse() a QuerySet rather than 1 value. Also its an .all() query so it may well have multiple objects and it's not related to the form result.
make = Make.objects.all() # QuerySet = ([<Make: Samsung>], [<Make: Sony>], [<Make: Apple>], etc)
return HttpResponseRedirect(reverse('browse_makes', args=[make])) # Expects 1 value
Assuming you want to redirect to the Make selected in the form then you'll need something like:
if form.is_valid():
# Get the valid form data
cd = form.cleaned_data
# Get the selected Make
make = cd.get('make')
# Redirect - note 'make.make'. You want to pass the value not the object
return HttpResponseRedirect(reverse('browse_makes', kwargs={'make': make.make}))

I think there are couple of issues
Your urls does not correspond to appropriate view
change this line
url(r'^browse/(?P<make>[\w-]+)/$', 'axlepost.views.browse.makes', name='browse_makes'),
to
url(r'^browse/(?P<make>[\w-]+)/$', 'axlepost.views.browse', name='browse_makes'),
Change your view definition to take make parameter
def browse(request, make):
...
#change your local variable 'make' to something else

Related

Flask Passing Form argument to a function

I am new to Flask and I am just trying to pass 4 arguments that I got from my form to another python function. When I submit my form, I am getting this error : "TypeError: search() missing 4 required positional arguments: 'keywords', 'starting_date', 'ending_date', and 'country'"
I verified and all of my variables have data from the form, so they are not empty
`
#app.route('/')
#app.route('/index', methods=["GET", "POST"])
def index():
if request.method == "POST":
keywords = request.form.get('keywords')
starting_date = request.form.get('starting_date')
ending_date = request.form.get('ending_date')
country = request.form.get('country')
return redirect(url_for("search", keywords=keywords, starting_date=starting_date, ending_date=ending_date, country=country))
else:
return render_template("index.html")
#app.route('/search', methods=["GET"])
def search(keywords, starting_date, ending_date, country ):
return render_template('result.html', title='Result')
You'll need to define your search route as
#app.route('/search/<keywords>/<starting_date>/<ending_date>/<country>', methods=["GET"])
to get your current implementation to work, see Variable Rules section in Flask's doc.
This is, however, problematic. For one, you probably don't want such a messy URL.
A better approach is to ask Flask to send your data to search as query parameters and retrieve it through request.args. Redefine search as
#app.route('/search', methods=["GET"])
def search():
keywords = request.args['keywords']
starting_date = request.args['starting_date']
ending_date = request.args['ending_date']
country = request.args['country']
# perform search
return render_template('result.html', title='Result')
Now url_for will generate a URL of the form /index?keywords=<value>&starting_date=<value>....
See this great SO answer for all the ways to get data from a request: https://stackoverflow.com/a/16664376/1661274
You need to render the template with your form parameters.
Try this:
#app.route('/index', methods=["GET", "POST"])
def index():
if request.method == "POST":
keywords = request.form.get('keywords')
starting_date = request.form.get('starting_date')
ending_date = request.form.get('ending_date')
country = request.form.get('country')
return render_template('result.html', keywords=keywords, starting_date=starting_date, ending_date=ending_date, country=country)
else:
return render_template("index.html")

DJANGO: Redirect to a page based on a submitted data form (HttpResponseRedirect)

I'm new with django and I'm trying to redirect to a page based on a submitted data form, but no luck. Is there a method with the HttpReponseRedirect I can pass or just the syntax is not right? I tried figuring it out but failed.
views.py
...
def select_bar(request):
if request.method == 'POST':
form = SelectBarForm(request.POST)
if form.is_valid():
bar = form.cleaned_data['bar']
bar_name = str(bar.name)
return HttpResponseRedirect('/bars/(?P<bar_name>\w+)/')
# return HttpResponseRedirect('/')
else:
form = SelectBarForm()
return render_to_response('bars_templates/bars.html', {'form': form}, RequestContext(request))
...
urls.py
...
urlpatterns += patterns('bars.views', (r'^bars/$', 'select_bar'),)
urlpatterns += patterns('songs.views', (r'^bars/(?P<bar_name>\w+)/$', 'songs'),) # capture the bar name from the url.
...
I'm not quite sure why you have used a regex there. You need to use an actual URL:
return HttpResponseRedirect('/bars/%s/' % bar_name)
or even better use the reverse function which accepts a view name and the relevant parameters
return HttpResponseRedirect(reverse('songs.views.songs', bar_name=bar_name))
or even better again, use the redirect function which does both the reversing and the redirecting:
return redirect('songs.views.songs', bar_name=bar_name)
You can use django.shorcuts.redirect
return redirect('songs.views.songs', bar_name=bar_name)
This will cause a redirect to your view function songs.views.songs passing bar_name as the keyword argument.

Get the id of an object after processing its form in views.py

I need to get the id of the object I just kept in order to pass it in the HttpResponseRedirect:
def pujar_track(request):
if request.method=='POST':
formulari = TrackForm(request.POST, request.FILES)
if formulari.is_valid():
formulari.save()
# code to get the track_id ???
return HttpResponseRedirect('/track/pujar/acoplar',track_id)
else:
formulari = TrackForm()
return render(request,'principal/trackForm.html',
{'formulari':formulari})
Thanks in advance!
Assuming TrackForm extends ModelForm:
formulari = formulari.save()
return HttpResponseRedirect('/track/pujar/acoplar',formulari.id)
Without knowing how you're accepting the variable, I can't tell you how best to pass the argument. However, I would encourage you to use reverse instead of hard coding the url, which would look like:
return HttpResponseRedirect(reverse('view_name', args=(),
kwargs={'track_id': formulai.id}))
assuming your view accepts a keyword argument of track_id

Editing the form in Django

I have created a form in my app where I can take details of a suer. Now I want to create a form which can allow me to edit a form.
My urls.py:
url(r'^home/editform/(?P<userpk>[^/]+)/$', 'lexuseditform', name='lexuseditform'),)
My view.py:
#login_required
def lexuseditform(request,userpk):
if int(userpk) != request.user.pk:
return HttpResponseForbidden()
else:
form = AdultForm()
if request.method == 'POST': # If the form has been submitted...
form = AdultForm(request.POST) # A form bound to the POST data
if form.is_valid(): # All validation rules pass
form.save()
redirect_url = reverse('lexus/lexusedited.html')
return HttpResponseRedirect(redirect_url) # Redirect after POST
else:
form = AdultForm() # An unbound form
return render('lexus/lexuseditform.html', {'form': form})
My models.py:
class AdultForm(ModelForm):
"""
Edit Profile Information
"""
class Meta:
model = Adult
fields = ('user', 'email','fullname','created')
But i am getting an error msg:
No ReverseMatch: Reverse for 'lexuseditform' with arguments '()' and keyword arguments '{}' not found
Can't seem to solve this error. Need some help...
In you POST handling, reverse should be passed URL name not the pattern. So correct it whatever name you have given to that url.
redirect_url = reverse('lexus/lexusedited.html') <----- Incorrect.
If your urlname is 'lexusedited'
redirect_url = reverse('lexusedited')
Tip: you can directly do:
return HttpResponseRedirect(reverse('lexusedited'))

int() argument must be a string or a number, not 'QueryDict'

I'm rendering out 3 multiple select boxes on my form.
I'm filtering each box out to have a seperate type of day.
When I submit my form I get this error.
int() argument must be a string or a number, not 'QueryDict'
What must I do to save my form?
This is what i'm doing on my forms.py file to get the different filtering for each select box.
class ContractForm(forms.ModelForm):
def __init__(self, project_id, *args, **kwargs):
super(ContractForm, self).__init__(*args, **kwargs)
self.fields['shoot_day'].queryset = Day.objects.filter(type=SHOOT, project__id=project_id)
self.fields['travel_day'].queryset = Day.objects.filter(type=TRAVEL, project__id=project_id)
self.fields['additional_day'].queryset = Day.objects.filter(type=ADDITIONAL, project__id=project_id)
I'm getting my project_id like so:
def editcontract(request, contract_id, slug):
context_dict = {}
contract = get_object_or_404(Contract, pk=contract_id)
if request.method == 'POST':
form = ContractForm(request.POST, instance=contract)
if form.is_valid():
form.save()
TvUsageForm = TvUsageFormSet(request.POST, instance=contract)
AdditionalMediaUsageForm = AdditionalMediaUsageFormSet(request.POST, instance=contract)
TvUsageForm.save()
AdditionalMediaUsageForm.save()
return HttpResponseRedirect(reverse('contract_list', kwargs={'slug':slug}))
else:
form = ContractForm(instance=contract, project_id=contract.project_id)
TvUsageForm = TvUsageFormSet(instance=contract)
AdditionalMediaUsageForm = AdditionalMediaUsageFormSet(instance=contract)
project = get_object_or_404(Project, slug=slug)
context_dict = { 'form': form,
'tvusage_form':TvUsageForm,
'additional_form':AdditionalMediaUsageForm,
'project':project
}
return render_to_response('contracts/edit_contract.html', context_dict, RequestContext(request))
You have a confusion with the argument list and keyword arguments:
Instead of:
ContractForm(instance=contract, project_id=contract.project_id)
You want:
ContractForm(contract.project_id, instance=contract)
To elaborate: Your constructor accepts the project id as first argument not as keyword argument. Thus you need to give it as first argument. Simple confusion, eh?
Maybe this help you: Adding data to many-to-many field of a modelform within a view