1

I have a many to many field ConnectedTo in my model and I want to create the object using a form. However when I list it as a field I just get a listbox with options to highlight and no way of selecting one or more.

Ideally I'd love a multiple selection checkbox with a list of items in a scroll box. But I'd start with just having a selectable item.

Here's my code so far:

models.py:

class Part(models.Model):
    PartID = models.AutoField(primary_key=True, unique=True)
    SiteID = models.ForeignKey('Site', on_delete=models.CASCADE, null=True)
    Comment = models.CharField(max_length=255, blank=True)
    Subtype = models.ForeignKey('Subtype', on_delete=models.CASCADE, null=True)
    Location = models.CharField(max_length=255, blank=True)
    ConnectedTo= models.ManyToManyField('self', blank=True, null=True)
    BatchNo = models.CharField(max_length=32, blank=False, null=True)
    SerialNo = models.CharField(max_length=32,blank=True)
    Manufacturer = models.CharField(max_length=32, blank=False, null=True)
    Length = models.CharField(max_length=6, blank=True, null=True)
    InspectionPeriod = models.IntegerField(blank=True, null=True)
    LastInspected = models.DateField(blank=True, null=True)
    InspectionDue = models.CharField(max_length=255, blank=True)

    @classmethod
    def create(cls, siteid, comment, subtype, location, batchno, serialno, manufacturer, length, inspectionperiod, lastinspected, inspectiondue):
        part = cls(SiteID = siteid, Comment = comment, Subtype = subtype, Location = location, BatchNo = batchno, SerialNo = serialno, Manufacturer = manufacturer, Length = length, InspectionPeriod = inspectionperiod, LastInspected = lastinspected, InspectionDue = inspectiondue)
        return part

    def __str__(self):
        return str(self.PartID)

forms.py:

class PartForm(forms.ModelForm):

    class Meta:
        model = Part
        fields = ('Comment', 'Subtype', 'Location', 'ConnectedTo', 'BatchNo', 'SerialNo', 'Manufacturer', 'Length', 'InspectionPeriod', 'LastInspected')

views.py:

@login_required(login_url='/accounts/login/')
def addPartForm_Create(request, site, subtype):
siteselected = site
subtypeselected = Subtype.objects.get(SubtypeID = subtype)
if request.method == 'POST':
    form = addPartForm(request.POST)
    if form.is_valid():
        obj = form.save(commit=False)
        obj.SiteID = Site.objects.get(SiteID = siteselected)
        obj.Subtype = subtypeselected
        obj.save()
        return redirect('/sites/'+str(site))
else:
    form = addPartForm()
return render(request, 'myproj/addPart.html', {'form': form, 'SiteNo': Site.objects.get(SiteID = siteselected).SiteID, 'subtype': subtypeselected})

EDIT: had the wrong view, sorry.

EDIT 2: example of what I mean by the highlighted box:

form screenshot

UPDATE:

Jey_Jen's answer has helped me get the style I want. I now have a multiple selection checkbox. But the ConnectedTo attributes do not save. Everything else in the model is saved and a new part is created. But no many to many links.

  • "options to highlight" *is* selecting them, surely? – Daniel Roseman Dec 05 '19 at 14:29
  • No it doesnt. I have attached a screenshot to further clarify –  Dec 05 '19 at 14:35
  • @DanielRoseman I have also checked my database table to clarify that no connectedto relation is made behind the scenes in case my html just wasnt showing anything happening. There is absolutely nothing happening under the hood for that box it seems. –  Dec 05 '19 at 14:38
  • Like I said, that is something you can select; that's the default way browsers present a multiple selection (ie ` – Daniel Roseman Dec 05 '19 at 15:58

1 Answers1

0

I would suggest looking into django form widgets. you can override the default widget to be a whatever you want. you can view them here.

heres a small example the django docs give:

class CommentForm(forms.Form):
    name = forms.CharField()
    url = forms.URLField()
    comment = forms.CharField(widget=forms.Textarea)
Jay_jen
  • 44
  • 5
  • I thought of this but it seems different to doing it in a Model Form? Does this work just the same? –  Dec 05 '19 at 14:42
  • It should be similar. you can see a small description of how it would work with a modelform here: https://stackoverflow.com/questions/9878475/django-modelform-override-widget – Jay_jen Dec 05 '19 at 14:50
  • I tried doing this but it seems to not override it and it remains a listbox: `class Meta: ... widgets = {'ConnectedTo': forms.CheckboxSelectMultiple()}` –  Dec 05 '19 at 14:54
  • Nevermind I'm just an idiot and put that in the wrong Meta class haha –  Dec 05 '19 at 15:00
  • New problem though... it doesn't select anything still. I can check boxes and hit create. but my model isnt saved –  Dec 05 '19 at 15:15
  • 1
    Adding to this answer for the final solution. I had to add `form.save_m2m()` under my `obj.save()` line to save the m2m link too. –  Dec 05 '19 at 15:28