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

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!

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.

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')

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.

multiple Id arg 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]))

Paginating a Detail view in Django

I'm new to Django and for my first project I'm building a portfolio. And I need a little kick-start with pagination help. I have an "index" view with a list of projects and a detail view of each project. In the detail view, I want a feature to be able to paginate between each individual object. I've gone through the Pagination documenation and applied what I learned with my index view but when I try to do the same thing with my detail view I get a TypeError saying my "object of type 'Project' has no len().
Here's a sample of my views.py code for reference:
def index( request ):
all_projects = Project.objects.all().order_by( '-pub_date' )
paginator = Paginator( all_projects, 12 )
try:
page = int( request.GET.get( 'page','1' ))
except ValueError:
page = 1
try:
projects = paginator.page( page )
except (EmptyPage,InvalidPage):
projects = paginator.page( paginator.num_pages )
return render_to_response( 'portfolio/index.html', { 'all_projects':all_projects, 'projects':projects, 'MEDIA_URL':MEDIA_URL })
def detail( request, project_id ):
project = get_object_or_404( Project, id=project_id )
return render_to_response( 'portfolio/detail.html', { 'project':project, 'MEDIA_URL':MEDIA_URL } )
Apologies if I sound n00b-ish because I am, and gratitude in advance for any help. Also, I read this previous post but it didn't seem to apply to me because my views aren't Class-based.
Django has built-in get_next_by_FOO()/get_previous_by_FOO() methods which will return the next/previous object depeding on a datetime-field.
You could access them in the template by somethow like:
{{ project.get_next_by_pub_date.title }}
I would say that this is the preferred method over using pagination for that, as you will get a nice url you can define in your model's get_absolute_url for every item!
To paginate you need an instance of a QuerySet, not an object! So you should replace your get_object_or_404 call by a filter/all. So it would be basically the same as the list view, but just pass the number 1 to the paginator, as you already do!
I actually do not have that setup through Django's pagination. I used this code:
prev_issue = Issue.objects.filter(title=title).filter(number__lt=issue.number).order_by('-number')[:1]
next_issue = Issue.objects.filter(title=title).filter(number__gt=issue.number).order_by('number')[:1]
In your case, I would do something like this, but you would have to filter by something, too:
prev_project = Project.objects.order_by('-pub_date')[:1]
next_project = Project.objects.order_by('pub_date')[:1]
Then put the two in the context.
I also recommend django-pagination. I notice you probably want the pagination to stay on the index, correct? http://code.google.com/p/django-pagination/
You just have to mess with the template codes and it works great.
The great thing about Django is, that there is code for nearly every common programming problem, that you can download and use in your own project. (and most of the django packages are quiet well written too)
for pagination check out http://pypi.python.org/pypi/django-pagination
it's really easy to install and setup, so you do not have to think about pagination and focus on coding your software!
hope this helps, Anton
In my views.py
def ProjectDetail(request,pk):
context = {}
template = 'views/projectdetail.html'
project = ''
prev = Project.objects.filter(pk__lt=pk).order_by('-pk')[:1]
next = Project.objects.filter(pk__gt=pk).order_by('pk')[:1]
try:
print(prev[0].pk)
print(next[0].pk)
except:
pass
project = Project.objects.filter(pk=pk)
context['categories'] = ProjectCategory.objects.all()
paginator = Paginator(project, 1) # Show 25 contacts per page
page = request.GET.get('page')
try:
data = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
data = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
data = paginator.page(paginator.num_pages)
if prev:
context['prev'] = prev[0].pk
if next:
context['next'] = next[0].pk
context['data'] = data
return render_to_response(template, context,context_instance=RequestContext(request))
in my template i have
<div class="row">
<a {% if next %} href="{% url 'task:project-detail' next %}" class="btn btn-primary pull-right" {% else %} class="btn btn-primary pull-right disabled" {% endif %}>Next</a>
<a {% if prev %} href="{% url 'task:project-detail' prev %}" class="btn btn-primary pull-left" {% else %} class="btn btn-primary pull-left disabled" {% endif %} >Previous</a>
</div>