Note that there are some explanatory texts on larger screens.

plurals
  1. PODjango forms: ModelMultipleChoiceField displaying error "null" is not a valid value for a primary key
    text
    copied!<p><em>As commented below, I will try to explain my problem more precisely with more code examples</em></p> <p>In my application I am using a model inheritance, where base model class is:</p> <pre><code>class Entity(models.Model): VISIBILITY_LEVELS = ( ('0', 'Private'), ('1', 'Closedy'), ('2', 'Public'), ) entityType = models.CharField(max_length=50) userCreatedBy = models.ForeignKey(User, related_name='user_createdby', editable=False) dateCreated = models.DateField(editable=False) lastModified = models.DateField() lastModifiedBy = models.ForeignKey(User, related_name='user_lastModifiedBy') tags = models.ManyToManyField('Tag', blank=True, null=True) visibilityLevel = models.CharField(max_length=1, choices=VISIBILITY_LEVELS, default=False) </code></pre> <p>In my form, I am editing a model which derived from Entity:</p> <pre><code>class Place(Entity): name = models.CharField(max_length=155) description = models.TextField() location = models.ForeignKey(Point) </code></pre> <p>And the point and tag models are:</p> <pre><code>class Point(models.Model): lat = models.FloatField() #coordinates lng = models.FloatField() hgt = models.FloatField(default=0.0) class Tag(models.Model): tagName = models.CharField(max_length=250) #tag name usedAmount = models.IntegerField(default = 1) #how many entities has this tag </code></pre> <p>All of the models have primary key generated automatically by django. In my site, I am using AJAX to process the form (currently, there is no AJAX validation, but it will be ;) My first problem was: what will be the easiest way for creating a form for adding a new Place object? Where the most tricky part was Tag addition, cause I need to enable both - adding new tags and selecting existing tags. I am new to Django, so some my attempts can be naive.. My solution was to make two Forms inherited from ModelForm for Point and Place and one custom Form for Tag. In tag form, I want to enable user to choose existing tags from DB or to type new tags separated by ';' in a textinput. So I have created those 3 forms:</p> <pre><code>class PlaceAddForm(forms.ModelForm): def __init__(self, *args, **kwargs): super(PlaceAddForm, self).__init__(*args, **kwargs) self.fields['name'].label = "Name" self.fields['description'].label = "Desc" self.fields['visibilityLevel'].label = "Visibility" class Meta: model = Place fields = ('name', 'description', 'visibilityLevel' ) #-- class PointForm(forms.ModelForm): class Meta: model = Point #--- class TagAppendForm(forms.Form): newTags = forms.CharField( widget=forms.TextInput(), required = False, ) tagsAll = forms.ModelMultipleChoiceField( label="Choose:", queryset=Tag.objects.all(), required = False ) def clean_newTags(self): if len(self.cleaned_data['newTags']) == 0: return [] tags = self.cleaned_data['newTags'].split(';') for t in tags: if len(t) == 0: raise forms.ValidationError('Tag must be minum 3 characters long') return tags </code></pre> <p>And then in my template I have:</p> <pre><code>&lt;form id="save-form" method="post" action="/user/places/addedit/"&gt; {{ pointForm.as_p }} {{ placeForm.as_p }} {{ tagForm.as_p }} &lt;input type="submit" value="save" /&gt; &lt;/form&gt; </code></pre> <p>And View is:</p> <pre><code>def place_save_view(request): ajax = request.GET.has_key('ajax') if request.method == 'POST': placeForm = PlaceAddForm(request.POST) pointForm = PointForm(request.POST) tagForm = TagAppendForm(request.POST) if placeForm.is_valid() and tagForm.is_valid() and pointForm.is_valid(): place = _place_save(request, placeForm, pointForm, tagForm) variables = RequestContext(request, {'places' : place }) return HttpResponseRedirect('/user/places/', variables) #else: # if ajax: elif request.GET.has_key('entity_ptr_id'): place = Place.objects.get(id==request.GET['entity_ptr_id']) placeForm = PlaceAddForm(request.GET,instance=place) point = place.location pointForm = PointForm(request.GET,instance=point) tagForm = TagAppendForm(initial={'tagsAll': place.tags.values_list('id', flat=True)}) else: placeForm = PlaceAddForm() pointForm = PointForm() tagForm = TagAppendForm() variables = RequestContext(request, {'placeForm': placeForm, 'pointForm': pointForm, 'tagForm': tagForm }) if ajax: return render_to_response('places/place_save.html', variables) else: return render_to_response('places/add-edit-place.html', variables) </code></pre> <p>And finally AJAX:</p> <pre><code>function placeAdd() { var div = $(document).find("#leftcontent"); div.load("/user/places/addedit/?ajax", null, function() { $("#save-form").submit(placeSave); }); return false; } function placeSave() { var item = $(this).parent(); var data = { lng: item.find("#id_lng").val(), lat: item.find("#id_lat").val(), hgt: item.find("#id_hgt").val(), name: item.find("#id_name").val(), description: item.find("#id_description").val(), pType: item.find("#id_pType").val(), visibilityLevel: item.find("#id_visibilityLevel").val(), newTags: item.find("#id_newTags").val(), tagsAll: item.find("#id_tagsAll").val() }; $.post("/user/places/addedit/?ajax", data, function(result){ if(result != "failure") { //todo.... } else { alert("Failure!"); } }); return false; </code></pre> <p>}</p> <p>Here I have more than a topic question to ask:</p> <ol> <li><p>Is a better solution for doing that? (ok, I can create a one custom form but I loose some automation parts...)</p></li> <li><p>Why after submitting form with blank newTags and no selection on tagsAll fields, I have an error for the tagsAll field (it appears on form, above tagsAll field):</p></li> </ol> <p><strong>"null" is not a valid value for a primary key</strong></p> <p>I have also a problem with displaying errors on form, when AJAX is used... :/ I find solution, that I must manually iterate through them on template with form (http://infinite-sushi.com/2011/06/using-ajax-with-django/).. For any other solution I will be grateful :)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload