Is there any magic why to do this in admin panel of django?
Let me know
Off the top of my head, you could use JS to grab the popup link and load the HTML in a div on the page. But that means you need to override the admin template. This QA should be helpful.
It also means you need to capture the saving of the new house. So, when someone presses save, depending on the response, the div either closes or shows the errors WITHOUT refreshing th page. I'm not sure but I think you'll also need to override the admin view that does this to send back json responses.
OR
You could use JS to mute that link and call up your own url, which would allow you to create your own view with your own custom form that does this. This would give you a bit more control without having to hack away at the Admin functionality.
e.g /house/ajax_add
You'll need to refresh the options in the House dropdown though. So I don't think you can avoid extending the template, now that I think about it.
It seems like a lot of trouble, really. No magic way that I know of, but it's possible.
To avoid popups, you might want to look at https://github.com/FZambia/django-fm:
Django-fm allows to create AJAX forms for creating, editing, deleting
objects in Django. This is a very personalized approach to quickly
build admin-like interfaces.
A live example can be found on http://djangofm.herokuapp.com/.
I'm not sure how this integrates with the current admin site, but with some changes it should not be hard.
Related
I am trying to make a simple e-commerce website and followed some tutorials.
However, the author of the book used complicated function based view to make cart function..
there are bunch of session stuffs.. and I don't understand the logic..
and I am trying to think the other way..
what about using database to store all the cart related data, and
use CBV to build it?
for example,
CartListView to see the contents of the cart, and CartUpdateView to change the quantity..
then are they going to be two different pages? separated page that user should go to the
different page to change the value??
please help me T T
You can access the session in any sort of CBV as self.request.session and a "shopping cart" is normally stored therein.
You'll certainly need to implement a CartListView to see what's in it, or possibly a CartEditView to show the cart with options to edit the quantities and delete anything that shouldn't be in there.
Adding products to the cart may well be an "Add" button on a ProductDetailView or lots of add buttons in a ProductListView. You might add a POST handler method to these views which are otherwise read-only (GET-only) bt default. Or you might make them FormViews, even though the form would be hidden and filled/POSTed by JS rather than the shopper doing anything other than clicking "add".
And then there will be a CheckoutView.
Check https://djangopackages.org/ (put "cart" in the search box). this will throw up several shopping cart things which might be the code you want, or the source of which might be a valuable learning resource before you end up rolling your own.
My situation is as follows.
I have a django app that is a CMS, and this one app generates page content and menus.
There is 'default' view that generates all the page content. One of the fields of the main model is designed to limit the visibility of pages depending on the setting:
'internal' (limited to users on our network),
'worldwide' (viewable by the www) and now, I would like to add an extra value
'secure', which would limit viewing only to those who are logged in to the site.
I dont think #login_required would work, as it only works on whole functions.
We want the author or editor to be able to set this flag, rather than code a special function; and there will be instances where a page migrates from 'internal' to 'secure' then to 'worldwide' - so ideally the urls should stay the same.
What is the best way to go about this?
thanks in advance... patrick
As you want the flag set on your object, I'm assuming that flag can't be read until you're already within the view (i.e. you won't be storing it in something accessible by the request object, like a session), so that precludes custom decorators. You could choose to go with something a bit crude but workable like this:
if (val=="internal" and inrange(request.META['REMOTE_ADDR'])) or (val=="secure" and request.user.is_authenticated()) or val=="worldwide":
return render_to_response .... etc.
else:
return HttpResponseForbidden()
Substituting your model values, and writing the inrange function, naturally.
The more sophisticated approach, though, would be to write custom middleware and use the process_view() function. See the docs for more details.
I'm trying to write a simple CRM app in Django; partly as a learning exercise and partly for in-house use.
My schema is slightly complex, as rather that have a single Contact model (with a home phone, work phone, home email, etc.), I have stripped down Cntact model plus a Phone model, an Email model, etc., with a ForeignKey pointing back to a Contact. The point is to let Contacts have an arbitrary number of phone numbers, email addresses, etc. Simple, right?
I have some working views and templates for displaying the data - no issues there. And with only a very small amount of poking at admin.py I have a um...eight different TabularInlines set up, and the admin interface works to create and edit the data...but it's ugly and clunky to the point of unusability, and of course there's no conception of permissions or anything. I'm also not really a fan of having a completely different interface for displaying and searching through the data than for editing and adding contacts...I'd like as much as possible to be done inline, so that I can search for a name, look at the record, click "add note", have it popup a form, fill in the details, click submit, and be done, all with AJAXy goodness so there's no page reloads.
Question: Should I plug away at modifying the admin interface to try and make it usable for a user-facing app? And if so, can anyone point me to a good guide or example where someone has really changed the admin interface to make it work for user-facing CRUD operations?
Or should I just go ahead and write my own CRUD views? And if so, can anyone point me to a good guide or example where someone has written custom CRUD views that work with lots of ForeignKeys and inlines? Ideally I want a form that displays a single Contact, all his Email records, plus a blank form to add a new Email record, plus a button to add more blank forms, plus his Phone records, plus a blank form, and so on for all 8 of my associated models.
(Or am I thinking about this all wrong? Any advice appreciated.)
For our intranet, we use ModelAdmin subclasses (not mounted on the admin site via admin.site.register) for most of our C(R)UD views. By using custom templates for the views, it doesn't look like Django admin at all. What is very convenient though, is that it already handles all the validation/saving for us.
In general, I found admin-"hacking" quite useful to quickly write up C(R)UD views and usually with relatively small changes to your ModelAdmin subclass, you can make it work for your use case.
So I'd vote for use ModelAdmin, but not the one you use in admin, hook a different template and come up with some fancy CSS.
I successfully created a software on top of admin.
The admin hooks (these days) allow very fine-grained customizations, i.e. in general you only need to touch what you want to change.
The changes can go from a trivial cosmetic adjustment to a complete swap-out:
If you provide templates/admin/base.html your admin site can look any way you like. And of course, a navigation bar at the top could include links to some of your own views. Watch out not to hardcode URLs in your links, always reverse.
You can overload ModelAdmin's "change_view", "changelist_view" etc. and swap them for your own views. For example I replaced a default changelist and its simple filtering with a search interface that allows dynamic queries to be built, result columns to be customized by the user, and loading/saving of these searches. That didn't affect any of the other views of that ModelAdmin.
Overloading a ModelAdmin's "get_urls()" let's you rewrap existing admin urls to go to your own views. I did the latter for one model where I wanted the simple Add screen to be replaced by a totally customized Wizard (only leaning on ModelForm).
Don't forget the simplest approach, esp. regarding your "AJAXy goodness": Just define "css" and "js" in your ModelAdmin's Meta. Want to move an inline from the bottom to sit between third and fourth field, and that's not possible via parameters? A one-liner in jquery.
Check out "django-grappelli" for an example of how to improve admin look and feel.
What did you mean by "and of course there's no conception of permissions or anything"?
What is the best way to conditionally display a field in the admin depending upon the values of other fields?
In particular I'm thinking about the add_form and change_form. Whenever a certain choice is selected I'd like to hide or disable some fields.
I'm thinking that this might require a javascript solution, but am wondering if there is a better (i.e. builtin) way to do this.
Bernhard is right. You might be able to hack the admin view and template to conditionally show/not show widgets for a field, but if you want to do it dynamically based on user behaviors in the admin, you'll be using javascript.
It's not so terrible, though. At least the Django admin templates have model- and instance-specific ids to give you granular control over your show/hide behavior.
My answer may sound esoteric - but I suspect the design direction you may be taking could benefit from some reconsideration. When an interface requires that much TLC to resort to AJAX to make for a superior UX I am inclined to not use Admin interface for that.
My personal view of the Admin interface of Django is that it is a great freebie that gives me an instant CRUD view at a basic level. I would refrain from piggy backing on it for those who need a more user friendly interface (even if some of these users are handling admin functions). You will acquire technical debt in trying to do these type of Ajax UI/UX and complex form validations using the Admin interface.
I think you should be able to create your own ModelForm and specify that the admin uses that (https://docs.djangoproject.com/en/1.7/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form).
Use the _init__() method of the form to selectively display the fields.
I will give it a try and update this answer if it works.
(Actually re-reading the question, it depends. If "values of other fields" is set before the page is loaded, this idea should work. If you want an instant response - click one field and another appears/disappears, yes you will need JavaScript).
I have a custom action on a model Foo all set up and ready to go, complete with a new permission I've made.
Problem is, my administrators need the can_change_foo permission to view a change list and perform that custom action (which I don't want to award).
Is there an easier way to set this up without rewriting the model list admin view?
There is a horrid hack I can think of... Completely untested, obviously...
You could disable all other actions by overriding get_actions() and only allow for your custom action. Then you could follow T.Stone's suggestion here and completely disable links to edit individual instances of the model. What that would allow you to do is give your users the can_change_foo permission knowing that the only action they would be able to perform was yours.
Not pretty... Especially the part about not linking to the edit page...
Is re-writing the list admin view that bad? :-)
I ended up overriding the changelist_view() method on my ModelAdmin class, copying the defaults from django and just commenting out the permissions check. The list (at least the way I have it configured) doesn't have links to edit the individual objects, and even if it did, django raises a PermissionDenied if you try and edit an individual object. (since I never awarded the can_change permission).
It's a hack, and some monkeypatching, but until there's a separate permission for viewing a changelist, it works pretty well.