'Django: how to delete item in one model AND change many to many relationship in another model that was linked to the first model?
This website allows users to select Rolling Stones concerts they've been to. It will add the Concert and the Song to the model from the API if they select it. And Concert.song has a many to many relationship with the user model.
If a user removes a concert from their concert list, the songs still appear. I don't necessarily want the song to be deleted because they could have heard the song from another concert. I also don't think it's the best idea to change the user of the song from the usernmae to --- (because null=True). I think my only choice is to change the usersonglist.html template tags somehow?
Models.py
class Concert(models.Model):
venue = models.CharField(max_length=200, null=True)
concertid = models.CharField(max_length = 200, null=False, default='didnotsaveproperly')
date = models.DateField(null=True)
city = models.CharField(max_length=100, null=True)
country = models.CharField(max_length=200, null=True)
user = models.ForeignKey(USER_MODEL, related_name="concerts", on_delete=models.CASCADE, null=True)
song = models.ManyToManyField("Song", blank=True, null=True)
def __str__(self):
return str(self.concertid) + " " + str(self.venue) + " " + str(self.date)
class Song(models.Model):
name = models.CharField(max_length = 100, null=True)
user = models.ForeignKey(USER_MODEL, related_name="songs", on_delete=models.CASCADE, null=True)
def __str__(self):
return self.name
URLS.py
urlpatterns = [
path("", views.display_concerts, name="choose_concerts"),
path('add/<str:concertdict>/', views.log_concert_and_song, name='concert_add'),
path('userconcerts/', views.ConcertListView.as_view(), name='user_concert_list'),
path('<int:pk>/delete/', views.ConcertDeleteView.as_view(), name='delete_concert'),
path('usersonglist/', views.SongListView.as_view(), name='user_song_list'),
]
Views.py/SongListView for usersonglist.html
class SongListView(LoginRequiredMixin, ListView):
model = Song
template_name = "concerts/usersonglist.html"
def get_queryset(self):
queryset = Song.objects.filter(user=self.request.user)
return queryset
Views.py/function view to log concert and corresponding songs for user
def log_concert_and_song(request, concertdict):
if request.method == "POST":
url = 'https://api.setlist.fm/rest/1.0/'
setlist_path = f'setlist/{concertdict}'
header = {
"x-api-key": "******",
"Accept": "application/json"
}
params = {
"p": 1
}
setlists = requests.get(f"{url}{setlist_path}", params=params, headers=header).json()
concertdict = {}
user_concert_list = []
concertdict['venue'] = setlists['venue']['name']
concertdict['eventDate'] = format_date(setlists['eventDate'])
concertdict['city'] = setlists['venue']['city']['name']
concertdict['country'] = setlists['venue']['city']['country']['name']
concertdict['id'] = setlists['id']
concert_id_to_generate_songs = concertdict['id']
Concert_save = Concert(
concertid=concertdict['id'],
date=concertdict['eventDate'],
venue=concertdict['venue'],
city=concertdict['city'],
country=concertdict['country'],
user = request.user
)
Concert_save.save()
user_concert_list.append(concertdict)
songdict = {} # {concertid: [song1, song2, etc.]} #not needed for saving song name but in case I need to reference
list_of_songs_from_api = setlists['sets']['set'][0]['song'] #[{"name": "Shame, Shame, Shame","cover": {},},{"name": "Down the Road Apiece", "cover": { },}]
final_list = []
for song in list_of_songs_from_api: #song = {"name": "Shame, Shame, Shame","cover": {},}
song_name = song['name']
try:
Song_save = Song.objects.get(name=song_name, user=request.user)
except:
Song_save = Song(
name=song_name,
user=request.user
)
Song_save.save()
Concert_save.song.add(Song_save)
final_list.append(song['name'])
songdict[concert_id_to_generate_songs] = final_list
return redirect("user_concert_list")
else:
return render(request, 'concerts/concertslist.html')
Views/DeleteView to delete concert (but I need this to also remove the song from the usersonglist.html)
class ConcertDeleteView(DeleteView):
model = Concert
success_url = reverse_lazy('user_concert_list')
def get(self, *a, **kw):
return self.delete(*a, **kw)
HTML form to delete concert
<form method="post" action="{% url 'delete_concert' concert.pk %}">
{% csrf_token %}
<input type="submit" value="Delete" />
</form>
Solution 1:[1]
This is not possible. Also, is not recommended even if it were possible. if you could connect to key vault to retrieve secrets in JavaScript on client side, it's a huge security risk, as anyone could be able to access your secrets. it does not provide any security.
As a best practice you should never access secured resources directly from client code.
But here is an example code provided by official site of npmjs, please refer this blog post.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | DraggonDragger |
