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.
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'm essentially trying to make my URLs more readable by incorporating a slug that is not used for lookup purposes in my views. Previously, I had this in my main URLconf:
urls.py
path('<int:team_pk>/', TeamDetails.as_view(), name='team_details'),
path('<int:team_pk>/', include('tracker.urls', namespace='tracker')),
So I had urls like mysite/1/stuff and mysite/1/more/stuff.
Then I added a slug field to my Team model. The behavior I want is for any url that only includes a team_pk to be redirected to an expanded URL that incorporates the slug. For example, mysite/1/ should redirect to mysite/1/team_1_slug and mysite/1/stuff should redirect to mysite/1/team_1_slug/stuff. It's this latter behavior that I'm having trouble with.
I modified my URLconf to this:
path('<int:team_pk>/', TeamRedirectView.as_view(), name='team_details'),
path('<int:team_pk>/<slug:team_slug>/', TeamDetails.as_view(), name='team_details_redirected'),
path('<int:team_pk>/<slug:team_slug>/', include('tracker.urls', namespace='tracker')),
Then I have a simple view to redirect:
# views.py
class TeamRedirectView(generic.RedirectView):
def get_redirect_url(self, *args, **kwargs):
team = get_object_or_404(models.Team, pk=self.kwargs['team_pk'])
return reverse('team_details_redirected', kwargs={'team_pk': team.pk, 'team_slug': team.slug})
This works for redirecting mysite/1/ to mysite/1/team_1_slug, but any url tag that points to a url inside the tracker app throws a reverse error because I'm not supplying team_slug to the url tag.
So I'm basically trying to get my RedirectView to be a little more universal and add this slug to any url without having to manually supply it to every url tag. Is that doable?
When defining URL patterns, I am supposed to use a regular expression to acquire a PK from the URL.
What if I want a URL that has no PK, and if it's not provided, it will use the currently logged in user? Examples:
visiting /user will get a DetailView of the currently logged in user
/user/edit will show an UpdateView for the currently logged in user
I tried hard-coding the pk= in the Detail.as_view() call but it reports invalid keyword.
How do I specify that in the URL conf?
My sample code that shows PK required error when visiting /user URL:
urlpatterns = patterns('',
url(r'user/$',
DetailView.as_view(
model=Account,
template_name='user/detail.html')),
)`
An alternative approach would be overriding the get_object method of the DetailView subclass, something along the line of:
class CurrentUserDetailView(UserDetailView):
def get_object(self):
return self.request.user
Much cleaner, simpler and more in the spirit of the class-based views than the mixin approach.
EDIT: To clarify, I believe that two different URL patterns (i.e. one with a pk and the other without) should be defined separately in the urlconf. Therefore they could be served by two different views as well, especially as this makes the code cleaner. In this case the urlconf might look something like:
urlpatterns = patterns('',
url(r"^users/(?P<pk>\d+)/$", UserDetailView.as_view(), name="user_detail"),
url(r"^users/current/$", CurrentUserDetailView.as_view(), name="current_user_detail"),
url(r"^users/$", UserListView.as_view(), name="user_list"),
)
And I've updated my example above to note that it inherits the UserDetailView, which makes it even cleaner, and makes it clear what it really is: a special case of the parent view.
As far as I know, you can't define that on the URL definition, since you don't have access to that information.
However, what you can do is create your own mixin and use it to build views that behave like you want.
Your mixin would look something like this:
class CurrentUserMixin(object):
model = Account
def get_object(self, *args, **kwargs):
try:
obj = super(CurrentUserMixin, self).get_object(*args, **kwargs)
except AttributeError:
# SingleObjectMixin throws an AttributeError when no pk or slug
# is present on the url. In those cases, we use the current user
obj = self.request.user.account
return obj
and then, make your custom views:
class UserDetailView(CurrentUserMixin, DetailView):
pass
class UserUpdateView(CurrentUserMixin, UpdateView):
pass
Generic views uses always RequestContext. And this paragraph in the Django Documentation says that when using RequestContext with auth app, the template gets passed an user variable that represents current user logged in. So, go ahead, and feel free to reference user in your templates.
You can get the details of the current user from the request object. If you'd like to see a different user's details, you can pass the url as parameter. The url would be encoded like:
url(r'user/(?P<user_id>.*)$', 'views.user_details', name='user-details'),
views.user_details 2nd parameter would be user_id which is a string (you can change the regex in the url to restrict integer values, but the parameter would still of type string). Here's a list of other examples for url patterns from the Django documentation.
What I am trying to do is as follows
I have urls like this /blog/1/sdc/?c=119 or /forum/83/ksnd/?c=100 What I want to do is to redirect these to a view, so that I can change the url to /blog/1/sdc/#c119
One way would be to do this is to make provision in views of each of the app, where such a url maybe generated, but that is not scalable. What I want to do is to catch any url that has ?c=<some_digit> at the end and redirect to my custom view.
Can anybody help, I am not good with regex.
You can't do this in your urlconf, it doesn't match anything in the query string. What you'll need to do is write a middleware along the lines of this:
class RedirectMiddleware:
def process_request(self, request):
if 'c' in request.GET:
# return a HttpResponseRedirect here
See https://docs.djangoproject.com/en/dev/topics/http/middleware/ for more details.
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.