reversing admin "change" url - django

I´m trying to find some example of how to use change url of modelAdmin and what exactly result it gives. Sincerly I do not understand the part from docs:
"This will find the first registered instance of the admin application (whatever the instance name), and resolve to the view for changing poll.Choice instances in that instance."

You can reverse with:
reverse('app:poll_choice_change', kwargs={'object_id': pk})
With app the default namespace (you can specify a different one if you include this in the path(…) where you attach the admin.urls. poll the name of the app, choice the name of the model in lowercase, and pk the primary key of the object.

Related

what does {variable_name} in an url pattern mean in Django?

I'm reading Django Rest Framework documentation on router (https://www.django-rest-framework.org/api-guide/routers/) and encounter this:
^accounts/{pk}/$
I understand ^ means start of line, $ means end of line and everything but {pk}. What does it mean?
It means that an url pattern that includes a primary key, si valid. In the case of the documentation you are consulting, it means that the following url pattern is valid: accounts/121/. What SimpleRouter will do with it, is that urls that contain a primary key ({pk}), will be used to update or delete the accounts record with such primary key. In the example, account with primary key '121' would be retrieved, updated or deleted through such url.
This "variable_name" is received as a parameter by the view method or class method.

Django context processors and URL arguments

I have some code that is repeated at the start of my Django views. It basically just adds some variables to the context, but based on the URL argument, e.g.
def someView(request, id):
target = Target.objects.get(id=id)
# name will be added to ctx
name = target.name
(there are more attributes added and other attributes from related models, but this gives the general idea --- There are quite a few lines of repeat code at the start of each view)
I thought I could make my code more DRY by taking advantage of Django's context processors, but it would seem these don't access to the URL arguments?
Is there another way to avoid these repeat lines? Maybe middleware or something else?
You can access the URL parameters via request through the resolver_match attribute. So for instance you can do request.resolver_match.kwargs['id'] to get the ID kwarg.

How to find user group and use of caching in django?

I am new to django/python and working my way through my webapp. I need assistance in solving one of my problems.
In my app, I am planning to assign each user (from auth_user) to one of the group ( from auth_group). Each group can have multiple users. I have entry in auth_group, auth_user and auth_user_groups. Here is my question:
At time of login I want to check that logging user belongs to which group?
I want to keep that group info in session/cache so all pages I can show information about that group only.
If you have any sample code will be great.
Giving support to the very well #trinchet's answer with an example of context_processor code.
Puts inside your webapp a new file called context_processors.py and writes this lines on it:
def user_groups(request):
"""
Add `groups` var to the context with all the
groups the logged in user has, so you can access
in your templates to this var as: {{ groups }}
"""
groups = None
if request.user.is_authenticated():
groups = user.groups
return {'groups': groups}
Finally on your settings.py add 'webbapp.context_processors.user_groups'to TEMPLATE_CONTEXT_PROCESSOR:
TEMPLATE_CONTEXT_PROCESSORS = (
'webbapp.context_processors.user_groups',
)
1) Be user an instance of auth.models.User, you can get all groups the user belong to, through user.groups. If you want to ask at time of login then you should do this in your login view.
2) You can use session or cache approaches to deal with, this is irrelevant, but once you have the group you need to render the pages having this value, i mean, you need to provide the group to the template rendering, to do this I suggest to you using a custom context processor.

Tastypie resource name clash

I am currently using tastypie with 2 apps. Each of those apps has a model called Group. They operate very differently, and the only similarity is the name 'Group'.
When only one or the other app is added to the urls file, then it works like a charm. However, as soon as I add both apps, then there's a name clash, and the get_resource_uri() method returns the wrong string. Here is some code:
urls.py
from myapp1.resources import GroupResource as gr_a
from myapp2.resources import GroupResource as gr_b
myapp1_api = Api(api_name='1.0')
myapp1_api.register(gr_a())
myapp2_api = Api(api_name='1.0')
myapp2_api.register(gr_b())
on line 37 of the current api.py file in the tastypie repo I see this code:
if resource_name is None:
raise ImproperlyConfigured("Resource %r must define a 'resource_name'." % resource)
self._registry[resource_name] = resource
Since both of my Group resources have the resource_name of 'group', they get registered on top of each other, even though they are registered at separate urls. Apart from changing the actual resource name, is there a way around this name clash?
Update
The uris would look something like this:
/myapp1/1.0/group/
/myapp2/1.0/group/
Ideally I don't want myapp1 and myapp2 to know about each other (ie the Group class is distinct). The workaround for this is to change myapp2.Group to myapp2.MyGroup (to avoid the name clash), but its really not that elegant.
In all my resources I had the resource_name blank, since I was happy with the default name. Also I wanted a url such as /myapp/1.0/group/ and not /myapp/1.0/myapp/group/
What I've now done is change all the resource_name attributes to the form "myapp/group" and bound them all to an empty url. This gave me a nice such as: /1.0/myapp/group/ while making sure there are no name clashes in the resources.

django admin filter tweaking

I want to use django's admin filter on the list page.
The models I have are something like this:
class Location(model):
name = CharField()
class Inquiry(Model):
name = CharFiled()
location = ManyToManyField(Location)
Now I want to filter Inquiries, to display only those that contain relation to specific Location object. If I use
class InqAdmin(ModelAdmin):
list_filter = ['location', ]
admin.site.register(Inquiry, InqAdmin)
the admin page displays me the list of all Locations and allows to filter.
What I would like to get, is to get list of only those locations that have some Inquiries in relation to them (so I don't ever get the empty list result after filtering).
How can this be done?
You could create a custom manager for Locations that only returns Locations that have an Inquiry associated with them. If you make this the default manager, the admin will use it.
Only caveat is that you'll need create another manager that returns all Locations and use that in the rest of your app whenever you want to retrieve Locations that don't have an associated Inquiry.
The managers section in the Django docs is quite good, and should be all you need to get this set up.
EDIT:
sienf brings up a good point. Another way to accomplish this would be to define a subclass of django.contrib.admin.SimpleListFilter, and write the queryset method to filter out Inquiries with empty Locations. See https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter