I have a model called Song and another called Chord. They have a ManyToMany relationship through a label called ChordIndex.

A song might need to have the same chord more than once, which django would not allow. Hence, I gave the model an extra field (manually coded auto-incremental field) called index, so objects are not identical.

Still I can't add "duplicate" chords.

Nevertheless the approach works with a form and a POST method. But, if I use the POST method I am unable to set song field to default="lastSongByUser" because you can only query "user" inside a view.

models.py

class ChordIndex(models.Model):
    def incrementalNumber():
        objectCount    = ChordIndex.objects.count()
        if objectCount == None:
            return 2
        else:
            return objectCount + 1

    index  = models.PositiveIntegerField(default=incrementalNumber)
    chord  = models.ForeignKey('Chord', on_delete=models.CASCADE)
    song   = models.ForeignKey('Song', on_delete=models.CASCADE)

views.py

def addchord_view(request, idChord):
    user                    = request.user.profile
    chord                   = Chord.objects.get(pk=idChord)
    songsByUser             = Song.objects.filter(uploader=user)
    lastSongByUser          = songsByUser.last()
    previousPage            = request.META.get('HTTP_REFERER')
    filterUserLastSong      = ChordIndex.objects.filter(song=lastSongByUser)
    lastSongByUser.chords.add(chord)
    thisObjectAdded         = filterUserLastSong.last()
    thisObjectAdded.save()
    return HttpResponseRedirect(previousPage)

editchords.html

    {% for chord in allChords  %}
        {% if chord.acronym != silent%}
            <button class="btn btn-dark"><a href="{% url 'add-chord-view' idChord=chord.pk %}">{{ chord.acronym }}</a></button>
        {% else %}
            <button class="btn btn-primary"><a class="text-dark" href="{% url 'add-chord-view' idChord=chord.pk %}">next part</a></button>
        {% endif %}
    {% endfor %}

I would expect to get same results that from POST method.

1 Answers

1
ruddra On Best Solutions

You can add duplicate objects like this:

def addchord_view(request, idChord):
    user = request.user.profile
    chord  Chord.objects.get(pk=idChord)
    songsByUser = Song.objects.filter(uploader=user)
    lastSongByUser = songsByUser.last()
    previousPage = request.META.get('HTTP_REFERER')
    filterUserLastSong = ChordIndex.objects.create(song=lastSongByUser, chord=chord)

    return HttpResponseRedirect(previousPage)

Explanation

When you call ChordIndex.objects.create(song=lastSongByUser, chord=chord), it will create a new ChordIndex instance. Then if you call song.chords.all(), then you should get multiple chords for a song ordered by creation. You don't need to use index = models.PositiveIntegerField(default=incrementalNumber) field as well in your model, so you can remove that.