multiple Id arg django - django

I have an issue with my web-app django.
In example, user can add an artist, and with this artist, he can (list, delete, play) music.
When the user click on the artist, the URL is 'music/1/' where the artist ID is 1, and music is listed.
When user want delete a music, the URL is 'delmusic/1/' where the music ID is 1.
delmusic function works, but returns an error PageNotFound with this http URL :
'http://host.local/appli/delmusic/1/webgui.views.music'
My urls.py :
url(r'^music/(\d+)/$', 'webgui.views.music'),
url(r'^delmusic/(\d+)/$','webgui.views.delmusic'),
My music template :
<a href="{% url 'webgui.views.delmusic' music.id %}"style="margin-bottom: 3px" type="button">
My view :
def music(request, id):
listmusic = Music.objects.filter(artist=id)
return render(request, 'music.html', {'listmusic': listmusic})
def delmusic(request, id):
music = Music.objects.get(id=id)
music.delete()
return redirect('webgui.views.music')
I think there is confusion with music.id and arist.id, but I don't know..
Maybe you will have an idea ?

You have a slight issue with your urls.py - the 2nd argument points to the views function, but is not used as a reference in the templates, for that you need to do:
url(r'^music/(\d+)/$', 'webgui.views.music', name='music'),
url(r'^delmusic/(\d+)/$','webgui.views.delmusic', name='delmusic'),
and then in the template
<a href="{% url 'delmusic' music.id %}" style="margin-bottom: 3px" type="button">
or if you had a namespace defined for your app in django_settings/urls.py:
<a href="{% url '<APPNAMESPACE>:delmusic' music.id %}" style="margin-bottom: 3px" type="button">
and then at then in views.py do
from django.core.urlresolvers import reverse
def delmusic(request, id):
music = Music.objects.get(id=id)
artist_id = music.artist.id
music.delete()
return redirect(reverse('music', args=[artist_id]))

Related

trouble converting Python regex to path with django

I am working on a project which uses regex urls. The way it is currently designed is you have to manually type the url as a model field which then gets passed to the urls/views as an argument? (I don't fully understand this part yes, still learning). These are the views, urls, and the templates which I think are the issue here. I am trying to automatize the process of adding the slug and that part is working. However, I can't seem to find a way around getting it to work with the way urls are configured currently.
the views sections:
class QuizDetailView(DetailView):
model = Quiz
slug_field = 'url'
template_name = 'exam/quiz_detail.html'
another section of the view where I think the url from the above snippet is turned into a variable which then gets used in url:
class QuizTake(FormView):
form_class = QuestionForm
template_name = 'exam/question.html'
def dispatch(self, request, *args, **kwargs):
self.quiz = get_object_or_404(Quiz, url=self.kwargs['quiz_name'])
if self.quiz.draft and not request.user.has_perm('quiz.change_quiz'):
raise PermissionDenied
The urls:
#passes variable 'quiz_name' to quiz_take view
url(regex=r'^(?P<slug>[\w-]+)/$',
view=QuizDetailView.as_view(),
name='quiz_start_page'),
url(regex=r'^(?P<quiz_name>[\w-]+)/take/$',
view=QuizTake.as_view(),
name='quiz_question'),
and finally the template snippets, this is a detail view of the model/quiz:
<a href="{% url 'quiz_start_page' quiz.url %}">
this one displays the model (which is a quiz users take):
<a href="{% url 'quiz_question' quiz_name=quiz.url %}">
What I have tried so far:
first, since I have the slug field:
class QuizDetailView(DetailView):
model = Quiz
slug_field = 'url' ---this was commented out
template_name = 'exam/quiz_detail.html'
next, I changed the urls from:
url(regex=r'^(?P<slug>[\w-]+)/$',
view=QuizDetailView.as_view(),
name='quiz_start_page'),
url(regex=r'^(?P<quiz_name>[\w-]+)/take/$',
view=QuizTake.as_view(),
name='quiz_question'),
to:
path('<slug:slug>/', QuizDetailView.as_view(), name='quiz_start_page'),
path('<slug:slug>', QuizTake.as_view(), name='quiz_question'),
Then I changed the temlates from:
<a href="{% url 'quiz_start_page' quiz.url %}">
<a href="{% url 'quiz_question' quiz_name=quiz.url %}">
To:
<a href="{% url 'quiz_start_page' quiz.slug %}">
<a href="{% url 'quiz_question' quiz.slug %}">
When I click on the listview for the model/quiz, the url is displayed correctly on browser which I think means the automatic slug is working. However, once I click the link I see this error:
Reverse for 'quiz_question' with keyword arguments '{'quiz_name': ''}' not found. 1 pattern(s) tried: ['(?P<slug>[-a-zA-Z0-9_]+)$']
Really appreciate any help/pointers
Just figured it out myself, I realized I left out the argument which links the Quiz to the TakeQuiz model above.
path('<quiz_name>', QuizTake.as_view(), name='quiz_question'),
Above, instead of the slug I passed the argument <quiz_name> and changed the templates too:
{% url 'quiz_question' quiz_name=quiz.slug %}
That worked.

RedirectView to external site. How to append parameters?

I would like to redirect from my page to external site. This external site address is defined and never changes... And I can implement it... The challenge comes from:
I have a form, which posts Q into my view function, which gives final string of parameters to pass into the pattern of url supposedly attached to the main address of this external web site after the ? mark... I just cannot find the information how to pass and attach this string to a given url. Somehow it's difficult for me, please don't judge too harsh. Parameter is only one, it is a string, which formed in view function.
I use RedirectView in urls.py:
path('do_request/found/', RedirectView.as_view(url='https://docs.djangoproject.com/'), name='found_objects'),
In views.py (there are probably some mistakes, but it's just for the purpose of the question):
class UserFoundRequestView(TemplateView):
model=ForQuery
template_name='found_objects.html'
def get_results(self, request):
our_queries = ForQuery.objects.all()
query=self.request.GET.get("q")
if query:
our_object=ForQuery.objects.filter(query_id__iexact=query)
for x in our_queries:
if x.query_id == our_object.query_id:
name = x.dep_station
#context = {
# 'name' : name,
#}
return name
def get_string(request):
base_url = 'https://docs.djangoproject.com/'
query_name = get_results()
query_string = urlencode(query_name)
url = '{}?{}'.format(base_url, query_string)
return redirect(url)
Either to append to url or just bring formed url to patterns->path...
Thank you for the help!
my template:
{% extends "base_generic.html" %}
{% block content %}
<div>
<p>Paste value to the field</p>
<form method="get" action="{% url 'found_objects' %}">
<input type="text" name="q" placeholder="search by value" class="m-1 p-1"><button class=" btn btn-outline-primary m-1 p-1" type="Submit">Search</button>
</form>
</div>
{% endblock %}
You have to trigger the view by submitting the form and the view itself will return the according redirect. Between is the url mapping that links the form submit to the according view like so:
urls.py
from your_app.views import redirect_view
path('do_request/found/', redirect_view, name='found_objects'),
views.py
def redirect_view(request):
our_queries = ForQuery.objects.all()
query = request.GET.get("q")
if query:
our_object=ForQuery.objects.filter(query_id__iexact=query)
for x in our_queries:
if x.query_id == our_object.query_id:
name = x.dep_station
base_url = 'https://docs.djangoproject.com/'
query_string = urlencode(name)
url = '{}?{}'.format(base_url, query_string)
return redirect(url)

django pass data using anchor tag

I am trying to pass data using anchor tag to django views.
My html file:
<div class="card-body dropdown">
<button class="dropbtn">Pay</button>
<div class="dropdown-content">
Payments Wallet
Payments Credit card
Payments Debitcard
Payments Bitcoin
</div>
</div>
</div>
My urls.py file
urlpatterns = [
path('payments/<str:data>',views.payments,name="payments"),
] + static(settings.MEDIA_URL,document_root = settings.MEDIA_ROOT)
my views.py file
def payments(request):
query = request.GET.get('data')
print(query)
return render(request, '403.html')
Error : Reverse for 'payments' with no arguments not found. 1 pattern(s) tried: ['customerspayments\/(?P[^/]+)$']
Please help.
Because you are passing parameter to url, you have to add that argument to function too. So, either change your views.py only, just by adding a parameter inside function
1. Best way
# Edit
# Pass parameter like this, if it works or not, for all 4 anchors
Payments Wallet
# Add data to the side of reqeust
def payments(request, data):
# If you getting query like this, then you don't have to pass parameter to url
# query = request.GET.get('data')
query = data
print(query)
return render(request, '403.html')
Or, if you want to get parameter from get method, then change url. So, ether you take from get method like:
2. Another way
# urls.py
urlpatterns = [
# removed data
path('payments',views.payments,name="payments"),
] + static(settings.MEDIA_URL,document_root = settings.MEDIA_ROOT)
# Your template where, your anchor is
<div class="card-body dropdown">
<button class="dropbtn">Pay</button>
<div class="dropdown-content">
Payments Wallet
Payments Credit card
Payments Debitcard
Payments Bitcoin
</div>
</div>
</div>
# views.py
# your views.py
def payments(request):
query = request.GET.get('data')
print(query)
return render(request, '403.html')

Selenium .click() on link doesn't give the right address

I'm testing a page.
I'm writing a functional test and I want to click on a link using Selenium 3.141 .
The link is working (if I click on it by myself).
The address should be http://127.0.0.1:8000/lists/addname/ but when selenium click on it go to http://localhost:63286/lists/addname/lists/addname/ and ofcourse it doesn't find the page (63286 is a number always different but shouldn't be the problem, if I click on the link before it does (using time.sleep, for example) I go to the page http://localhost:63286/lists/addname and it works).
I'm not expert so maybe it's a trivial error and I don't know what code can be relevant, so tell me if you have to know more.
Edit: probabily is something related to load time /Edit
My functional_tests.py:
class NewVisitorTest(LiveServerTestCase):
def setUp(self):
self.browser = webdriver.Firefox()
def tearDown(self):
self.browser.quit()
def test_can_add_name_and_read_it_after(self):
# Bob go to the homepage
self.browser.get(self.live_server_url)
# He notice the title in header is Home
self.assertIn('Home', self.browser.title)
# He finds and clicks the link on the sidebar for the addname page
element = self.browser.find_element_by_link_text('Add Name')
# element = self.browser.find_element_by_xpath('/html/body/div/div[1]/nav/div/ul/li[2]/a') # this gives the same problem
time.sleep(1)
element.click()
In my template.html the link appear two time but that shouldn't be the problem:
<div class="navbar">
<a class="nav-link" href="{% url 'lists:addname' %}">{% trans "Add Name" %}</a>
</div>
[...]
<div class="sidebar">
<a class="nav-link" href="{% url 'lists:addname' %}">{% trans "Add Name" %}</a>
</div>
My main url.py:
urlpatterns = [
path('lists/', include('lists.urls')),
]
and my lists url.py:
urlpatterns = [
path('addname/', views.addname, name='addname'),
]
My views.py:
def addname(request):
if request.method == 'POST':
Item.objects.create(text=request.POST['item_text'])
return redirect('lists/addname/')
items = Item.objects.all()
return render(request, 'addname.html', {'items': items})
Thank you!

Django - reverse not working and I don't know why

I've used reverse before and it's been fine. But now, I don't know why it's not working. It might be because I'm trying to reverse to a class based view and I've never done that before.
Here's my code -- where am I messing it up?
views.py:
class DocumentRequestDetail(NavMixin, TitleMixin, SelectedBrokerage, DetailView):
model = DocumentRequest
mod_nav = 'brokerage_nav.html'
context_object_name = 'doc'
subtitle = 'Document Request Details'
def MarkDocRequestComplete(request, bpk, pk):
d = DocumentRequest.objects.get(pk= pk)
d.is_complete = True
d.save()
return reverse('doc_request_detail', args=[bpk, pk]) #<--- the offending line
urls.py
from django.conf.urls import include, url
from django.views.generic.list import ListView
from brokerage.views import *
urlpatterns = [
url(r'^(?P<pk>[0-9]+)/detail/$', BrokerageDetail.as_view(), name="brokerage_detail"),
url(r'^(?P<pk>[0-9]+)/edit/$', BrokerageEdit.as_view(), name="brokerage_edit"),
url(r'^(?P<bpk>[0-9]+)/doc-request/all/$', DocumentRequestList.as_view(), name="doc_request_list"),
url(r'^(?P<bpk>[0-9]+)/doc-request/(?P<pk>[0-9]+)/$', DocumentRequestDetail.as_view(), name="doc_request_detail"),
url(r'^(?P<bpk>[0-9]+)/mark-doc-request-complete/(?P<pk>[0-9]+)/$', MarkDocRequestComplete, name="mark_doc_request_complete"),
]
HTML Link that calls MarkDocRequestComplete:
<a href="{% url 'brokerage:mark_doc_request_complete' brokerage.pk doc.pk %}" class='btn btn-lg btn-wide btn-success'>
<i class='ti-check'></i>
Mark Complete
</a>
Error When Clicking HTML Link:
Reverse for 'doc_request_detail' with arguments '(u'1', u'19')' and keyword arguments '{}' not found. 0 pattern(s) tried: []
I don't get it... what am I doing wrong?
Edit I should say that, in the error, the 1 and 19 are the correct values for bpk and pk.
Edit 2 Added full URLs.py
The reason your url tag isn't working, is because you are namespacing it by adding brokerage: to it), when there is no namespace setup in your urls. See the documentation on how to properly setup namespaces.
The correct tag should be:
{% url 'mark_doc_request_complete' bpk=brokerage.pk pk=doc.pk %}
You have to change:
return reverse('doc_request_detail', args=[bpk, pk])
to
return reverse('doc_request_detail', kwargs={'bpk': bpk, 'pk': pk})
You must also change your template tag from:
<a href="{% url 'brokerage:mark_doc_request_complete' brokerage.pk doc.pk %}" class='btn btn-lg btn-wide btn-success'>
to:
<a href="{% url 'brokerage:mark_doc_request_complete' bpk=brokerage.pk pk=doc.pk %}" class='btn btn-lg btn-wide btn-success'>
The reason for these changes is because you have names in your regular expression groups.