I am writing one middleware class to handle pagination in django.
I am getting issue when user delete entry in ListView and page number is lost. So, i have to check how many pages for that request and adjust page number to reduce issue 404 error. I can get ClassBase Name, model name but cant get object_list data.
my code is:
url = request.path
resolver_match = resolve(url)
func = resolver_match.func
module = func.__module__
view_name = func.__name__
clss = get_class( '{0}.{1}'.format( module, view_name ) )
I want to count the current page of that request.
Please suggest to get it.
Thanks,
ThanhTruong
It would probably be better to handle pagination in a base view or a mixin. See ListView for an example.
Related
I'm using a GET parameter in my Django app to pass in information, that I want to be preserved in future links using Django's {% url %} template tag.
In my case, this is to allow view-only access within the app.
Example URL:
https://my.app/entry/123?key=abcdef
An example link on that page is already created like this:
View more details
Desired result:
I would like Django's URL template tag to automatically preserve any GET parameters named key throughout the app. In this case, it would generate new URLs with that same parameter applied. For example:
https://my.app/entry/123/details?key=abcdef
Workarounds
This blog post and this gist solve the problem by creating a new template tag and using that instead of Django's url template tag.
Is that really the best solution? I'd end up having to replace every instance of {% url %} throughout my app with my own tag. It also wouldn't fix the use of reverse().
Django middlewares may work for what you want. You could check when you receive the key parameter and store in session, then if there is not key parameter in the url append it :
class DetectKeyParameter:
def __init__(self, get_response):
self.get_response = get_response
#staticmethod
def process_view(request, view_func, view_args, view_kwargs):
return view_func(request, *view_args, **view_kwargs)
def __call__(self, request):
if 'key' in request.GET:
#If alerady is on the url just store it on session
request.session['key'] = request.GET.get('key')
else:
if 'key' in request.session:
if not request.GET._mutable:
#You need to change this property to add parameters to GET
request.GET._mutable = True
# now you can edit it
request.GET['key'] = request.session['key']
request.GET._mutable = False
response = self.get_response(request)
return response
This way, you'll have the key parameter on every request, until you delete the session variable. Perhaps the code doesn't work 100%, but I hope you get the idea.
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?
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.
Need to access URL by name at model, can't just hardcode it. Need it for error message for a new object creating. Any suggestions?
Update: Just need to put url to error message, not reverse
Your question is not totally clear, but I think you are asking about the reverse function.
You can define get_absolute_url method in your model and than access it in other model's methods. Check https://docs.djangoproject.com/en/2.1/ref/models/instances/#get-absolute-url
I suggest you use a template tag. You can build one for your model and avoid polluting the model about stuff not related to the domain level and keep the presentation level to the template.
Check the docs here on how add a templatetags your app.: https://docs.djangoproject.com/en/2.1/howto/custom-template-tags/
Here a snippet of code to use as starting point for your url generation
from django import template
register = template.Library()
#register.simple_tag(takes_context=True)
def url_for_object(context, object):
# you have both the context and the object available to
# generate your url here
url = ....
return url
In your template use
{% url_for_object my_object %}
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.