I'm new to Django.
I made a URL shorter website like bitly for a test, and when users upload new URL, my program upload data to DB.
The problem is that Django doesn't reload urls.py. So if users upload their URL, data is saved in DB, but urls.py doesn't reload, so 404 shows because urls.py is not reloaded, because there are no data about new URL in urls.py.
I've searched in Google, I almost visited every website searched, but I couldn't find the answer.
How do I reload Django configurations without turning off and on the django server?
#root/url/urls.py
from django.urls import path
from django.http import HttpResponse #HttpResponse
from . import views
from . import models
urlpatterns = [
path("", views.Index),
path("urlprocess/", views.Process)
]
for i in models.Urllist.objects.all():
data = path(i.custom, lambda request: HttpResponse("<script>location.href = '{}'</script>".format(i.url)))
urlpatterns.append(data)
#views.py (Uploading Code)
def Process(request):
if request.method == "POST":
data = json.loads(request.body)
custom = data["custom"]
urllist = models.Urllist.objects.all()
for i in urllist:
if i.custom == custom:
return HttpResponse("customerror")
#upload
new = models.Urllist(url=data["url"], custom=custom)
new.save()
#reload(sys.modules[settings.ROOT_URLCONF])
return HttpResponse(custom)
else:
return HttpResponse(status="500")
Related
My views.py runs code fine when I press a button on my HTML page, views.py:
def start_or_end_fast(request):
#If starting fast, add a row to the db:
#fast_finished = False
#start_date_time using = current time
#end_date_time using = current time
if request.method == 'POST' and 'start_fast' in request.POST:
add_fast = logTimes(fast_finished=False,start_date_time=datetime.now(),end_date_time=datetime.now())
add_fast.save()
print(add_fast.start_date_time,add_fast.end_date_time)
print('Fast started')
#return render(request,'startandstoptimes/index.html')
return HttpResponseRedirect('startandstoptimes/index.html')
You can see my commented return line, this works but when I refresh the page I can resubmit the data, I want to avoid this. In researching my solution, I saw this could be solved using HttpResponseRedirect but I am not able to get this to work with my code, the more I change the more broken things become.
My application urls.py:
from turtle import home
from django.urls import path,include
from . import views
urlpatterns = [
path('', views.start_or_end_fast,name="start_or_end_fast")
]
My project urls.py:
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('startandstoptimes.urls'))
]
I believe it is related to the URLs, due to the 404 message I see:
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/startandstoptimes/index.html
Using the URLconf defined in myfastingsite.urls, Django tried these URL patterns, in this order:
admin/
[name='start_or_end_fast']
The current path, startandstoptimes/index.html, didn’t match any of these.
Am I going down the right route trying to use HttpResponseRedirect or is there a better solution?
class HttpResponseRedirect¶
The first argument to the constructor is required – the path to redirect to. This can be a fully qualified URL (e.g.
'https://www.yahoo.com/search/'), an absolute path with no domain
(e.g. '/search/'), or even a relative path (e.g. 'search/'). In that
last case, the client browser will reconstruct the full URL itself
according to the current path. See HttpResponse for other optional
constructor arguments. Note that this returns an HTTP status code 302.
See this link for more details: docs
As what the documentation says, HttpResponseRedirect accepts URL and not the path of your template. You should be doing it something like this:
from django.urls import reverse
return HttpResponseRedirect(reverse('start_or_end_fast'))
Background
OK, I have a library wagtail_references which, like many snippet libraries, uses wagtail hooks to add admin views into the wagtail CMS.
Say I have, in my wagtail_hooks.py
#hooks.register('register_admin_urls')
def register_admin_urls():
return [
url(r'^references/', include(admin_urls, namespace='wagtailreferences')),
]
And the views that get registered are in views/reference.py:
#permission_checker.require('add')
def add(request):
Reference = get_reference_model()
ReferenceForm = get_reference_form(Reference)
if request.method == 'POST':
# STUFF I WANT TO TEST BECAUSE IT DOESN'T WORK PROPERLY
else:
form = ReferenceForm(user=request.user)
return render(request, "wagtail_references/references/add.html", {'form': form})
So in my test_stuff.py file, I'd have:
class TestReferenceIndexView(TestCase, WagtailTestUtils):
def setUp(self):
self.login()
def post(self, params=None):
params = params if params else {}
return self.client.post(reverse('wagtailreferences:add'), params)
def test_simple(self):
response = self.post()
self.assertEqual(response.status_code, 201)
The Problem
But test_simple fails, because of course the urls for the view its testing are hooked in dynamically, not defined in urls.py. I get:
django.urls.exceptions.NoReverseMatch: 'wagtailreferences' is not a registered namespace
The question
How can I test endpoints whose URLs are registered by wagtail hooks?
I've tried
Registering the hooks manually in the test case, like:
class TestReferenceIndexView(TestCase, WagtailTestUtils):
def setUp(self):
self.register_hook('register_admin_urls', register_admin_urls)
DOH! I hadn't registered the admin urls in my test app.
tests/urls.py looked like this:
from django.conf.urls import include, url
from wagtail.core import urls as wagtail_urls
urlpatterns = [
url(r'', include(wagtail_urls)),
]
But now looks like this:
from django.conf.urls import include, url
from wagtail.admin import urls as wagtailadmin_urls
from wagtail.core import urls as wagtail_urls
urlpatterns = [
url(r'^admin/', include(wagtailadmin_urls)),
url(r'', include(wagtail_urls)),
]
Fixed. Sigh.
I developed a django project named "dms" and an app which name is "add_excel" last month. The app receieves excel files from web page and store the data into mysql database. Today I added another two apps, "add_struc" and "homepage", which should be another function app and the homepage app. But something odd shows up. After I clicked the "upload" button in "add_excel" app, instead of it's original functions, it redirects to "homepage" without doing anything to the database.
The VS Code shows:
[18/Apr/2019 11:08:00] "GET / HTTP/1.1" 200 317 # I opened the
homepage
[18/Apr/2019 11:08:02] "GET /addexcel/index/ HTTP/1.1" 200 1341 # I clicked to the "add_excel" app hyperlink
[18/Apr/2019 11:08:20] "POST /homepage/index/ HTTP/1.1" 200 317 #
I clicked "upload" but it redirected me to homepage again.
If I delete the homepage url in the urls.py for the whole project, and click the upload button again, it says:
Page not found (404) Request Method: POST Request
URL: http://127.0.0.1:8000/homepage/index/ Using the URLconf defined
in dms.urls, Django tried these URL patterns, in this order:
^admin/ ^$ [name='index'] ^addexcel/ ^addstruc/ The current path,
homepage/index/, didn't match any of these.
The urls.py in dms project:
from django.contrib import admin
from django.conf.urls import url, include
from homepage.views import index # default homepage
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', index, name='index'), # homepage
url(r'^addexcel/', include('add_excel.urls')),
url(r'^addstruc/', include('add_struc.urls')),
]
urls.py in add_excel app:
from django.conf.urls import url
from django.urls import path
from django.contrib import admin
from add_excel.views import IndexView
urlpatterns = [
url(r'index/', IndexView.as_view(), name ='index'),
]
urls.py in add_struc app:
from django.conf.urls import url
from django.urls import path
from django.contrib import admin
from add_struc.views import IndexView
urlpatterns = [
url(r'index/', IndexView.as_view(), name ='index'),
]
urls.py in homepage app:
from django.conf.urls import url
from django.urls import path
from django.contrib import admin
from homepage.views import index
urlpatterns = [
url(r'index/', index, name='index'),
]
views.py in add_excel app:
# -*- coding:utf-8 -*-
import os
import os.path
import sys
import datetime
from builtins import int
from django.db import models
from django.shortcuts import render
from django.views import View
import pymysql
import xlrd
from xlrd import xldate_as_tuple
# Create your views here.
class IndexView(View):
template_name = 'add_excel/index.html'
context={}
def get(self, request):
return render(request, 'add_excel/index.html', {})
def post(self, request):
# if request.method == 'POST' and 'excel_file' in request.POST:
if request.method == 'POST' and request.FILES["excel_file"]:
# do something
return render(request, 'add_excel/index.html', {"excel_data":excel_data})
You are using the name index in all of your url patterns which is causing a conflict. These should be properly namespaced (homepage-index, excel-index etc.) so when you refer to them throughout your application it is obvious to both developers and the program which URL should be chosen.
My theory is that there is some URL generation in your HTML Form that uses the name index and your Django site chooses the homepage for the URL so your IndexView is not run.
So my app works fine in the development server when Debug=True, however, when I switch it to False, my homepage is giving me back a 400 back. I have some endpoints which return json and they work fine regardless of the debug value.
I'm using Django 1.10.2
urls.py
from django.conf.urls import url
from django.contrib import admin
from fim_table import views
urlpatterns = [
url(r'^$', views.create_home),
url(r'^data/', views.data),
...
]
views.py
from django.shortcuts import render
from django.views.decorators.csrf import csrf_protect
from lockdown.decorators import lockdown
from .models import Fim, FimDeleted
from django.http import HttpResponse
from django.db.models.functions import Lower
from django.template.context_processors import csrf
import json
#csrf_protect
def create_home(request):
return render(request, 'table.html', {'csrf': csrf})
# returns all of the data, unfiltered/response is json
#csrf_protect
def data(request):
# show distinct names only
fims = Fim.objects.annotate(name_lower=Lower('crib_name')).order_by('name_lower').distinct('name_lower')
# fims need to be not a queryset but an array of dicts to be json
dictionaries = [ idToString(name.as_dict()) for name in fims ]
mydata = {"aaData": dictionaries}
return HttpResponse(json.dumps(mydata), content_type='application/json')
settings.py
DEBUG = False
ALLOWED_HOSTS = ["*"]
update
I implemented some logging, and got:
The joined path (/DataTables/datatables.min.css) is located outside of the base path component (/Users/me/development/my_project/myapp/staticfiles).
I'm thinking this is a whitenoise issue, even though I set up my settings.py exactly like it is in their docs
Try adding hostnames in the allowed hosts section.
For Ex: ALLOWED_HOSTS = ['localhost', 'localhost_projectname', 'server_hostname']
You can find more details about how to add 404 and 500 pages in your site in the given blog post,
https://micropyramid.com/blog/handling-custom-error-pages-in-django/
I am in a way of making a module for my project that can be reused later also.
Lets say I have an django app named "demo" and I have included it in root url like url(r'demo/',include("demo.urls")),
Now inside "demo.urls" I want to redirect admin url to custom url.
/admin/auth/group/add/
should be redirected to any url that is of demo.urls
define a view function that redirects to your desired url:
from django.http import HttpResponseRedirect
def redirect_to_desired_url(request):
return HttpResponseRedirect('new_url/')
and then in your urls.py
urlpatterns = patterns('',
...
url(r'^/redirect_to_desired_url/$',redirect_to_desired_url),
...
)