I have a model named Agency.agency has a field named URL,for example I add 2 Agencies that the first one give the value of A to URL and the second one give the value of B to URL field.now I wanna override save_model method in index in views.py to add Agencie's URL to urls.py when adding an Agency,like this:
(r'^airAgency/A/$','airAgency.views.index'),
(r'^airAgency/B/$','airAgency.views.index'),
so,when enter http://127.0.0.1:8080/airAgency/A the index view detect which Agency I wanna access and pass its data to the page.now I have 2 question:
how can I add/remove url to urls.py when overriding save method in views.py
when user enter a URL in browser how can I parse it and find out which Agency he wanna access to send that Agency Information.
about the first question I searched a lot but I didn't find anything.for second question I googled and I found out how to parse the requested URL,but U think doing string search in Agency Table based on its URL field is a good way?
As others have said and/or pointed to, don't hardcode specific Agencies into your urls.py
Keep it generic and DRY by allowing variables in your urls
# urls
(r'^airAgency/(?P<name>[a-zA-Z0-9]+)/$', 'airAgency.views.index'),
# this passes the value there as 'name' to the view for index
#views
def index(request, name): # it needs to know name will be passed to it
some_query = Agency.objects.filter( agency_name = name )
#should also add catching for unknown objects to go to 404s
...
return some_sort_of_http_response
more examples are in the docs
Related
In my site, I have pages that are created on the fly using primary keys (for privacy/security reasons using uuid.uuid4()) as the URLs. I end up with .../reports/e657334b-75e2-48ce-8571-211251f1b341/ Is there a way to make aliases for all of these dynamically created sites to something like .../reports/report/.
Right now my urls.py includes the following:
path("reports/<str:pk>/", views.report_detail, name="report")
I tried changing it to:
re_path('reports/<str:pk>/', RedirectView.as_view(url='/reports/report/'), name="report"),
path("reports/report/", views.report_detail),
But I go to the site that has the links to the long URLs, I get the following error:
NoReverseMatch at /reports/Reverse for 'report' with arguments '('e657334b-75e2-48ce-8571-211251f1b341',)' not found. 1 pattern(s) tried: ['reports/str:pk/']
The template for that site includes:
<a class="card-title" href="{% url 'report' report.pk%}">
I also tried the following for urls:
path("reports/report/", views.report_detail),
path('reports/<str:pk>/', RedirectView.as_view(url='reports/report/'), name="report"),
Which allowed the previous site to load, but when I clicked on the link got the following 404 error:
Request URL: http://127.0.0.1:8000/reports/e657334b-75e2-48ce-8571-211251f1b341/reports/report/
I am trying to have one alias for multiple pages - essentially removing/replacing the long uuid with a single word.
Without trying to make an alias, the site works fine.
If you really don't want to pass the pk/uuid of the report to the shortened url, you could pass it in the session
Create a custom RedirectView that saves the pk to the session and then read that pk in the target view
class ReportRedirect(RedirectView):
def get(self, request, pk):
request.session['report_pk'] = pk
return super().get(request, pk)
def report_detail(request):
report_pk = request.session['report_pk']
...
You use the custom RedirectView just like the built-in one
path("reports/report/", views.report_detail),
path('reports/<str:pk>/', views.ReportRedirect.as_view(url='/reports/report/'), name="report"),
I am trying to make urls pattern to catch all urls from root.
my main urls.py is:
path('', (include('myapp.urls', namespace='app1')
I am using two url patterns in app1.urls:
re_path(r'^(?P<url_var1>[-\w./]+)/$', DetailView1.as_view(), name='DetailView1'),
re_path(r'^(?P<url_var2>[-\w./]+)/$', DetailView2.as_view(), name='DetailView2'),
My views.py file is as:
class DetailView1(View):
template_name = 'detail.html'
def get(self, request, url_var1):
obj1 = model1.objects.get(my_url=url_var1)
return render(request, self.template_name, {'obj1':obj1})
class DetailView2(View):
template_name = 'detail.html'
def get(self, request, url_var2):
obj2 = model2.objects.get(my_url=url_var2)
return render(request, self.template_name, {'obj2':obj2})
when i request url "/first-post/my-first-post/", It checks out the url which is in my "model1" under ther header "my_url" and return the page.
But when I request url "/second-post/my-second-post/", It checks out the url in "model1" and throws an error, as the url is in "model2" under header "my_url".
I know that the urlpattern follows a squence check, and stops at the pattern which matches the first urlpattern(DetailView1), thats why It is giving me this error.
I want to know is there a way I can override this behavior of urlpattern.
I have also tried reverse, when url is not found in DetailView1:
try:
obj1 = model1.objects.get(my_url=url_var1)
except:
return reverse('app1:DetailView2')
But Its still giving me an error.
If any of you got any other suggestions for catching urlpattern from root for mare than two type of urlpattern please tell me.
I am making a product cum blog website which has two models "model1" which is a product model, and "model2" which is a blog model. Now the "model1" is for automobile having 2 main categories "car" and "bike" and "model2" is having the same as "latest in cars" & "latest in bikes". For these categories I want to pick up urls from the root which have been given as "/cars/lexus.....", "/bike/ducati....". Also, there can be further additions of subfolder url and all urls have product IDs having "." and numbers. So is there is way i can pick urls frm root for both models using the above url pattern.
Its not possible to have multiple views and single urlpattern in Django.
Take a look at your views. They are almost the same. You should put the logic handling different url parameters in single view.
My advice would be also to carefully review your model design, it looks like you have two models that are essentially the same. I feel that this is the root of your problem.
Additionally I assume that you are trying to create some kind of blog.
Django had its beginning as framework powering news site. And it has some helpful tools. For example take a look at SlugField This may provide you with functionality you are looking for. Without over complicating the urlpatterns.
On a legacy app, I need to check if a URL exists, and if it does not, to redirect it to another location. The problem is that I need to check if that url is present in a set of values, in the urls file and I'm not clear on how best to do that.
For example, both projects and cities are sharing the same url pattern. e.g. /projects/london and /projects/my-project-name.
I want to first check if the slug matches a city, and if it does not to then return the project view (cities cannot match project names).
My urls are currently structured as follows:
url(r'^projects/(?P<project-name>[-\w]+)', get_project, name='project-view'),
url(r'^projects/.*', get_city, name='city-view'),
I know this is very messy, and a bad overall pattern but unfortunately it's not something that can be changed at the moment. So my goal is to figure out if I can first check if the project-name could be a city, and if it is, to redirect onto that view without falling into a redirect loop.
I wondered if I could do something like this:
url(r'^projects/(?P<city>london|paris|new-york)/', get_city, name='city-view'),
where london|paris|new-york are generated dynamically
You can dynamically generate a url with all of the city names, but the url will be cached once django accesses it the first time, so in order to modify the url regex, you'd have to restart the django process. If that's fine for your purposes, you can generate the url like this:
url(r'^projects/(?P<city>{})/$'.format(city_slugs.join('|')),
get_city, name='city-view')
But, it would probably be better to create a view routing method that implements the logic to send requests to their appropriate view:
# urls.py
# ...
url(r'^projects/(?P<slug>[-\w]+)/$',
project_city_router, name='project-city-router'),
# ...
# views.py
def is_a_city(slug):
# If they're in the database, something like:
# return City.objects.filter(slug=slug).exists()
return slug in ['london', 'paris', 'new-york', '...']
def project_city_router(request, slug=None):
if not slug:
# /projects/
return render(request, 'my/template.html', {'foo': 'bar'})
elif is_a_city(slug):
# /projects/<city>/
return get_city(request, city=slug)
else:
# /projects/<project-name/
return get_project(request, project_name=slug)
With this router, if the slug argument is a project or city, it returns the result of the get_project or get_city view itself.
This also allows for your list of cities to be checked dynamically against a database, or file.
Django newbie here, need help on basic middleware to redirect to another view if a certain model field is empty.
I am creating a terms of agreement page that users must get redirected to right after they signup to the platform if their filed_terms field on their Profile model is empty.
I am using middleware for this. However I am unable to get this to work. This is my middleware class:
class TermsMiddleware(object):
def process_request(self, request):
if request.user.profile.filled_terms is None:
return redirect(reverse(terms))
This gives me the following error:
global name 'terms' is not defined
I also have the url matcher that works perfectly when I navigate to it manually:
url(r'^terms/', 'my_app.views.terms')
I have a terms.html template and a terms view in my views.py file that is working perfectly in all other respects. I have also added it to the settings middleware requirements to make sure it loads.
Do I have to import something from views or url dispatcher into my middleware file? If so what would that be? I have been at this for a while an cannot find anything helpful.
reverse function takes url name instead on the regex. So you need to add name on your url configuration. Here is the example.
url(r'^terms/', 'my_app.views.terms', name='terms')
Add this in your views.py
from django.core.urlresolvers import reverse
And you need to fix your reverse function into.
return redirect(reverse('terms'))
Python interpret your terms as a variable and you have no variable named terms while you need to put string on reverse.
I have a model like this:
class EventTypeCategory(models.Model):
name = models.CharField(max_length=50, verbose_name="Name")
user = models.ForeignKey(User, verbose_name="User")
Message_slug = models.SlugField(blank=True, verbose_name="Message")
def __unicode__(self):
return self.name
In urls.py:
url(r'^categ/$',
'eventcateg_detail', name='eventcateg_detail'),
In views.py:
def eventcateg_detail(request,event_categ_id=None, event_categ_slug=None):
I want to add/edit/delete(CRUD) above defined value i.e name and Message_slug by template level. I am not getting any hint how to relate url.py with views.py and what should be definition of eventcateg_detail function.How this function will pass values to template (template name will be categ.html)
I am newbie in Django :)
want your help
You need to allow the URL to accept parameters to allow you specify which event category you want to view:
/categ/outdoor-events/
/categ/catered-events/
...
Do do this, you use a named URL pattern in your url scheme:
url(r'^categ/(?P<slug>[-\w]+)/$','eventcateg_detail', name='eventcateg_detail'),
and in your view:
from django.shortcuts import get_object_or_404, render
def eventcateg_detail(request,slug):
return render(request, "categ.html", {
'obj' : get_object_or_404(EventCateg, Message_slug =slug) # You should change Message_slug to just slug
})
and in your template:
<h1>{{ obj.name }}</h1>
So when a user enters a URL like we have outlined above, it gets matched to our URL pattern and the slug part of the url (catered-events) gets passed as a parameter to our view.
It's better that you follow the Django tutorial first, this is all covered in there. See for example part 3 of the tutorial for more information on how to relate urls.py with views.py and part 4 discusses passing variables to the template.
I believe that a view function is only passed an httprequest when it is called by the Django framework, the other two parameters of the function will only be useful if you call the function yourself but will not be useful through the web.
As pointed out in the comments I was mistaken in my belief, extra parameters can be passed as dynamic urls (i.e. urls designated like this url(r'^polls/(?P<poll_id>\d+)/$', 'polls.views.detail'),. See this link and the answer by #pastylegs
The Django Admin will allow you to edit all model fields if this is what you are after. Instructions on setting it up can be found in the Django documentation.
However I think what you are asking is how to enable CRUD editing through the web to users who are not admin level users. In that case you have many options. One of those options is to use a pre-built framework for Django like piston. Another way would be to use generic views
The other option is to build views yourself enabling operations on your model. In that case all of Django is available to you. You can pass parameters to your custom functions within the httprequest, for example as POST data.