I have two manytomany fields for my model ModelFrom, that both go to the same Model, call it ModelTo.
ModelFrom(models.Model):
field_one = ManyToManyField(ModelTo)
checked = ManyToManyField(ModelTo)
checked is a subset of field one. I have properly validated this in model clean() and adminform clean() methods, and updated model::save() to call self.full_clean().
Ideally, I would have one widget, much like the django.forms.SelectMultiple, but with a checkbox inside each <option>.
what it currently looks like, I have one of these widgets for each field:
:
I want to combine them and have a checkbox or something, here is my unicode representation of what it would look like
{ [ blah: 2 ☐] , [blah: 1 ☑] }
Value in the list -> field one is set. Checked box -> checked is set as it is a subset of field_one.
I have seen jQuery UI MultiSelect Widget but there doesn't seem to be a way to be able to select an option, but not check the box.
I couldn't directly answer my own question, but like most questions, if the answer is not possible then there may be an underlying problem.
Instead of having two many2many fields, I should just have one, setting the through property, for an intermediate field.
Like so:
class IntermediateField(models.Model):
checked = BooleanField()
from = ForeignKey(ModelFrom)
to = ForeignKey(ModelTo)
ModelFrom(models.Model):
field_one = ManyToManyField(ModelTo, through=IntermediateField)
Then, we can just use an inline for IntermediateField in ModelFrom admin, easily checking the boxes etc
Related
How to use a range slider (for example the jQuery one) with django-filter package?
So now I'm using the RangeFilter which just displays to normal text fields for the range. So the search function is working perfectly fin but it's just not that fancy as a cool slider.
class TentFilter(django_filters.FilterSet):
width = django_filters.NumberFilter(label="Breite")
length = django_filters.NumberFilter(label="Länge")
number_of_People = RangeFilter(label="People range")
class Meta:
model = Tent
fields = ['width', 'length', 'number_of_People', ]
I really would appreciate help because this thing is stressing me out.
Any non-filter arguments are passed to a filter's underlying form field. e.g.,
class TentFilter(django_filters.FilterSet):
number_of_people = RangeFilter(label='People range', widget=MyCustomWidget)
When the form is generated, the form field generated for number_of_people will use the given widget. If that's insufficient and you need to customize the form, there's also the Meta.form option where you can pass a custom Form class.
I have a made detailed tutorial on how to do create a jQuery range-slider with django-crispy-forms and django-filters. Hope it will be helpful.
Link to the tutorial https://mmtechslv.medium.com/how-to-create-a-fancy-range-slider-filter-in-django-890bd0486e13
In my code I've something like this (I'm using Django 1.6):
class CategoryAdmin(CategoryBaseAdmin):
[...]
list_per_page = 50
[...]
But I want to give users the possibility to switch the table for displaying all rows...
Something like a button (or a link) in the pagination bar... Is it possible?
Django 1.6 has an inbuilt thing called ModelAdmin.list_max_show_all set this value greater than the value that you're expecting would be the total number of resultset returned and the 'Show All' (appears in the form link) at bottom of page(area where you can switch pages).
Here's the link to django where you can find the explanation. Go ahead and add it to your class in admin.py.
Example :
class foo(admin.ModelAdmin):
list_display = ['feild1', 'feild2']
ordering = ['feild1']
list_max_show_all = n
actions = ('action1', 'action2')
where n is your value (should be greater than the expaected number of resultset). And it should work. Hope that you're fine with the 'Show all' appearing as link.
I was wondering what is the correct approach,
Do I create HiddenInput fields in my ModelForm and from the
View I pass in the primaryKey for the models I am about to edit into
the hiddenInput fields and then grab those hiddenInput fields from
the AJAX script to use it like this?
item.load(
"/bookmark/save/" + hidden_input_field_1,
null,
function () {
$("#save-form").submit(bookmark_save);
}
);
Or is there is some more clever way of doing it and I have no idea?
Thanks
It depends upon how you want to implement.
The basic idea is to edit 1. you need to get the existing instance, 2. Save provided information into this object.
For #1 you can do it multiple ways, like passing ID or any other primary key like attribute in url like http://myserver/edit_object/1 , Or pass ID as hidden input then you have to do it through templates.
For #2, I think you would already know this. Do something like
inst = MyModel.objects.get(id=input_id) # input_id taken as per #1
myform = MyForm(request.POST, instance=inst)
if myform.is_valid():
saved_inst = myform.save()
I just asked in the django IRC room and it says:
since js isn't processed by the django template engine, this is not
possible.
Hence the id or the object passed in from django view can't be accessed within AJAX script.
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
Given the following models (cut down for understanding):
class Venue(models.Model):
name = models.CharField(unique=True)
class Band(models.Model):
name = models.CharField(unique=True)
class Event(models.Model):
name = models.CharField(max_length=50, unique=True)
bands = models.ManyToManyField(Band)
venue = models.ForeignKey(Venue)
start = models.DateField()
end = models.DateField()
The admin area works great for what I'm doing, but I'd like to open the site up a bit so that certain users can add new Events. For the public portions, I have several "administrative" fields on these models that I don't want the public to see (which is easy enough to fix).
My specific problem, though, is changing the display of the ManyToMany selections when creating a new Event. Because the number of Bands possible to list for an event should not be sent along as a multiselect box, I'd like to use an AutoComplete that handles multiples (like the Tags box, here on StackOverflow!).
I have this part working, and it correctly fills in a hidden input with the Band.id's separated by commas for a value. However, I can't understand how to put together letting Django do the validation using the ModelForms, and somehow also validating the 'Bands' selection.
Ideally, I want to auto-complete like the tags here on StackOverflow, and send along the selected Bands ID's in some kind of Delimited string - all while letting Django validate that the bands passed exist, etc, as if I left the annoying multi-select list in place.
Do I have to create my own Auto-Complete Field type for a form or model, and use that? Is there something else I'm overlooking?
I have seen some existing AutoComplete widgets, but I'd really-really-really like to use my own Autocomplete code, since it's already set up, and some of them look a bit convoluted.
There was a lot more text/explanation here, but I cut back because I'm avoiding Wall Of Text. If I left important stuff out, let me know.
It's a little hard to say without knowing exactly what your autocomplete code is doing, but as long as it is sending the ids of the bands like they would be sent with the <select>, the ModelForm should validate them as usual.
Basically, your POST string should look like:
name=FooBar2009&bands=1&bands=3&bands=4&venue=7&start=...
The easiest way to do this might be to use Javascript to add (and remove) a hidden input field for each band entered with the name band and the id of the band as the value. Then, when the user submits the form, the browser will take care of posting the right stuff, and the ModelForm will validate it.
Using the annointed jquery autocomplete plugin,
On the client-side I have something like this:
jQuery("#id_tags").autocomplete('/tagging_utils/autocomplete/tasks/task/', {
max: 10,
highlight: false,
multiple: true,
multipleSeparator: " ",
scroll: true,
scrollHeight: 300,
matchContains: true,
autoFill: true,
});
So, I have a view that returns when I type in a:
http://skyl.org/tagging_utils/autocomplete/tasks/task/?q=a&limit=10×tamp=1259652876009
You can see the view that serves that here:
http://github.com/skyl/skyl.org/blob/master/apps/tagging_utils/views.py
Now, it's going to be a little tricky .. you might except the POST, then in the clean method of the field try to .get() based on the strings and raise a form validation error if you can't get it ... right, name = ... unique=True .. so something like (off the top of my head) ... :
def clean_bands(self):
return Band.objects.filter( name__in = self.cleaned_data['bands'].split(' ') )
You could also check each string and raise a form error if there are no bands by that name .. not sure that the clean method should return a qs. Let me know if this helps and you want me to keep going/clarify.