How to use AJAX for dependent drop down lists? - ajax

I want my "Location" drop down list to be dependent on my "Client" drop down list. My models:
class Client(models.Model):
name = models.CharField(max_length=50)
class Location(models.Model):
name = models.CharField(max_length=50)
What is the next step after this?
Should I put a FK somewhere?
What is the AJAX code for this?

If you want to display two dropdowns, first one with Client options and second one with Location options, with Locations changing on Client dropdown change you should add a js event handler, for example with jQuery:
$(document).on('change', '#clients', () => {
...call locations endpoint and update locations options...
})
On backend append your Location model with a Client FK and make an endpoint for path app/locations/<int:client_id>/ where you select Locations based on a Client:
from django.shortcuts import get_object_or_404
...
def locations(request, client_id):
client = get_object_or_404(Client, id=client_id)
locations = Location.objects.filter(client=client)
return JsonResponse(dict(locations=locations), status=200)

Related

Combining AJAX with ModelMultipleChoiceField and custom form

I've been banging my head for a while and could not find a similar issue.
I'll go over my code
Model
class RestauranteMenu(models.Model):
restaurante = models.ForeignKey(RestauranteUser)
name = models.CharField(max_length=60, blank=False)
class OpeningHours(models.Model):
...
restaurante = models.ForeignKey(RestauranteUser)
menu = models.ForeignKey(RestauranteMenu, blank=True, null=True)
...
Form
class MenuForm(ModelForm):
'''
View = menus(request)
Template = pages/menus.html
'''
horario = ModelMultipleChoiceField(queryset=OpeningHours.objects.all())
def save(self, restaurante, horario, commit=True):
#Linking relationship Restaurant x RestaurantMenu
menu = super(MenuForm, self).save(commit=False)
menu.restaurante = restaurante
if commit:
menu.save()
#Linking relationship RestaurantMenu x OpeningHours
horario = OpeningHours.objects.filter(id=horario, restaurante = restaurante).first()
if horario:
horario.menu = menu
horario.save()
return menu
class Meta:
model = RestauranteMenu
exclude = ['restaurante']
view
def menus(request):
#verify if its an update.
instance = request.POST.get('instance')
if instance not in [None, '']:
menu = RestauranteMenu.objects.get(id=instance)
form = MenuForm(request.POST or None, instance=menu, initial={'horario': OpeningHours.objects.filter(restaurante=request.user).values_list('id', flat=True)})
else:
form = MenuForm(request.POST or None, initial={'horario': OpeningHours.objects.filter(restaurante=request.user).values_list('id', flat=True)})
if request.POST:
if form.is_valid():
try:
#When saving, we pass a restaurant reference and OpeningHours reference.
form.save(request.user, form.data.get('horario'))
JS
$(document).on("click", "#sendmenuform", function() {
var horariosId = [];
$('#horario :selected').each(function(i, selected) {
horariosId.push($(selected).val());
});
$.ajax({
type: "POST",
url: "../menus/",
data: {
name : $('[name="name"]').val(),
horario : horariosId,
instance : $('#sendmenuform').attr("data-id"),
csrfmiddlewaretoken: $('[name="csrfmiddlewaretoken"]').val()
},
success : function(data) {
.... process response...
}
});
What's the issue
Based on my models, I want a Menu to have a ManyToOne relationship with OpeningHours, that means that one Menu can be at different OpeningHours.
When I'm submitting my form (via AJAX), I'm not able to populate the field 'horario' inside the form. When instantiating the form, I'm filling the field with a queryset that will filter by that Restaurant.
On the html, I have a select multiple, so that the restaurant is able to link one Menu to several different OpeningHours object.
I don't know how I'm supposed to process the information sent by the AJAX request to the view, specially this ModelMultipleChoiceField. Do I need to override any of the forms method?
ModelMultipleChoiceField expects model objects and not arbitrary strings. Hence using the values_list query set will only land you into trouble. Your form will not validate.
For your use case, use ChoiceFields. You can populate them with a string by overriding your __init__ method. For example, in your Forms.py
horario = ChoiceField(
choices[],)
def __init__(self, *args, **kwargs):
super(MenuForm, self).__init__(*args, **kwargs)
self.fields['horario'].choices = [(x.id, x.modelfieldtodisplay) for x in OpeningHours.objects.all()]
If you want to do this when you post the form or load it do it inside a view that is triggered by a listener for the event. You'll have to write Javascript to handle this similar to this tutorial but this asks you to use ModelChoiceField which I do not recommend for you because it doesn't work gracefully when you're trying to dynamically populate multiple fields and submit the form, validate it and run some operations on the data.
Instead, I implore you to take a look at Dajax and Dajaxice which takes altogether 5 minutes to set up and handles forms and AJAX effortlessly making your job significantly simpler. I do emphasize though, void using ModelChoiceField for you use case. I learnt that the hard way.

django rest framework choosing between two possible views for hyperlinked field

So I have two different API views on to User, one that superusers can use, and one that normal users can use.
At the moment, the problem is that my hyperlinks are going to auth_users view by default, instead of to the users view.
i.e.
'url': 'localhost:8000/auth_users/5/'
instead of
'url': 'localhost:8000/users/5/'
Here are extracts from the relevant files...
* URLS *
router =
routers.SimpleRouter()
router.register(r'auth_users', UserAPI.AdminUserViewSet)
urlpatterns = patterns('',
url(r'^', include(router.urls)),
url(r'^users/?$', UserAPI.CreateOrList.as_view(), name='users'),
url(r'^users/(?P<pk>[0-9]+)/?$', UserAPI.RetrieveUpdateOrDestroy.as_view()),
...
)
* serializer *
class basic_user_serializer(serializers.HyperlinkedModelSerializer):
url = HyperlinkedIdentityField(view_name='users')
class Meta:
model = User
fields = ['url', 'email', 'username']
* views *
class CreateOrList(generics.GenericAPIView):
"""
List all users, or create a new one.
"""
serializer_class = create_user_serializer
class RetrieveUpdateOrDestroy(generics.RetrieveUpdateDestroyAPIView):
queryset = User.objects.all()
serializer_class = create_user_serializer
I've had a look at the docs (linked below) but am not sure if this is explained...
http://django-rest-framework.org/api-guide/relations.html#hyperlinkedidentityfield
Anyone know how to fix it?
Cheers.
Oh, I fixed it.
I got rid of the auth_user view to see what would happen, and it threw an error page saying it couldn't find 'user-detail'.
I then changed the name of the users view to 'user-detail', re-enabled the auth_user view, and it works properly now.
No idea why, though - didn't I tell it to use 'users' instead of 'user-detail'??

reading related data after a selection of a foreign key - MVC3 and EF4

I am new to MVC and EF and I have a question.
I have built a site with models views controllers etc.
On an edit view for a Case (pretty big model so I won't post it here) I have a FK to a Customer model using CustomerID. When a user selects a customer id from a drop down list, I would like to display CustomerName, CustomerPhone etc after the selection of the ID. I think I might need to do a post back for this to work?
Also, do I need to Include the related entities as part of the initial data "get"? I have read some detail on that but I dont fully understand how that needs to work.
Please let me know if I should post more info. Thanks!
Here is my ActionResult for Edit
public ActionResult Edit(int id)
{
Cases cases = db.Cases.Find(id);
//related data needs to loaded to show related data fields
//include related data entities
var v = db.Cases.Include("Customers");
ViewBag.TechnicianID = new SelectList(db.Technicians, "TechnicianID", "LastName", cases.TechnicianID);
ViewBag.BranchID = new SelectList(db.Branches, "BranchID", "BranchName", cases.BranchID);
ViewBag.EngineModelID = new SelectList(db.EngineModels, "EngineModelID", "EngineModelName", cases.EngineModelID);
ViewBag.CaseCategoryID = new SelectList(db.CaseCategories, "CaseCategoryID", "CategoryName",cases.CaseCategoryID);
ViewBag.Qualified = new SelectList(new[] { "YES", "NO", "PARTIALLY" });
ViewBag.CaseStatus = new SelectList(new[] { "OPEN/IN PROCESS", "CLOSED" });
return View(cases);
}
The line
var v = db.Cases.Include("Customers")
is what I am trying to use to load related customer data and then show in my edit view like this:
#Html.EditorFor(model => model.Customer.CustomerName)
Well it depends on what you are trying to do. You could include a model which holds all the required data and send it with every call on that page (initial empty ofcourse)
Once you selected the customer, do post-back and send the customerId to your application and return the same page with the desired model.
You could do that via AJAX too.
Also, do I need to Include the related entities as part of the initial data "get"?
Not sure if I understand what you are trying to say. You mean that you think you would have to send all customer's data down to the page and select the related data on client side?

MVC3 -- Adding additional items to List<> with Jquery

I have a view model that looks like this:
HomeViewModel hvm = new HomeViewModel();
hvm.Applicant = new Person();
hvm.Applicant.Residences = new List<Residence>();
hvm.Applicant.Residences.Add(new Residence() { Type = "Current" });
In my .cshtml page, I have:
<label>Street # *:</label> #Html.TextBoxFor(m => m.Applicant.Residences[0].StreetNumber)
And so on and so forth for my properties in my Residence model. However, I want the user to be able to add multiple residences(previous, secondary, other, etc). I can add the necessary form fields via jquery, however, since the model doesn't know about the new list items, I get an error about null objects. The front end may be adding numerous residences via jquery.
This is a surprisingly complex topic. Check out the blog series starting with http://ivanz.com/2011/06/16/editing-variable-length-reorderable-collections-in-asp-net-mvc-part-1/
Try this: http://archive.plugins.jquery.com/project/jquery-dynamic-form
View demo here: http://sroucheray.org/blog/jquery-dynamic-form/

Django ModelForms: Trying to save a form using a foreign key ID

I'm trying to create a new Topic and the category id is dynamically determined in javascript on the client side. The problem i'm having is I pass the category id and I want to lookup the correct category object, but using a model form, it checks if the category is an instance of Category before I can assign it and save it.
--model.py--
class Topic(models.Model):
category = models.ForeignKey(Category)
--form.py--
class TopicForm(ModelForm):
category = forms.IntegerField(widget=forms.HiddenInput())
class Meta:
model = Topic
fields = ('category')
--view.py--
form = TopicForm(request.POST)
if form.is_valid():
form.save(commit=False) # throws exception category is not a Category instance
form.category = Category.objects.get(pk=form.cleaned_data.get('category'))
form.save()
Use a ModelChoiceField instead of the IntegerField in your form. See the built-in fields reference
Following Oggy's suggestion, I changed it to a ModelChoiceField and now Django does all the magic behind the scenes.
category = forms.ModelChoiceField(Category.objects.all(), widget=forms.HiddenInput())
Now I hope the queryset doesn't get evaluated, since it's not necessary and there are 90,000 records. :)

Resources