IntegrityError: music_song.album_id may not be NULL - python

I'm Django beginner and facing this error "music_song.album_id may not be NULL" and i was trying to solve this error but unfortunately can't solve it. i put almost all my code here so please Django Experts review the code and let me tell from where i did a mistake?
Views.py
def model_form_upload(request, pk):
all_song = Song.objects.all()
print'\n-------------------------------------------------------'
if request.method == 'POST':
print request.FILES
form = SongForm(request.POST, request.FILES)
if form.is_valid():
songName = request.FILES['audio_file'] #getting song name
fs = FileSystemStorage() #allocate memory
uploaded_file_url = fs.url(songName) #getting url of uploaded file
form.save() #song saved
return render(request, 'music/model_form_upload.html', {'uploaded_file_url': uploaded_file_url,
'form': form})
else:
form = SongForm()
return render(request, 'music/model_form_upload.html', {'form': form, 'all_song': all_song})
forms.py
class SongForm(forms.ModelForm):
class Meta:
model = Song
fields = ('song_title', 'audio_file')
models.py
from django.db import models
from django.core.urlresolvers import reverse
from .validators import validate_file_extension
class Album(models.Model):
artist = models.CharField(max_length=100)
album_title = models.CharField(max_length=100)
genre = models.CharField(max_length=100)
album_logo = models.FileField()
def get_absolute_url(self):
return reverse('music:upload', kwargs={'pk': self.pk})
def __str__(self):
return self.artist
class Song(models.Model):
album = models.ForeignKey(Album, on_delete=models.CASCADE)
song_title = models.CharField(max_length=250, blank=True)
audio_file = models.FileField(validators=[validate_file_extension], max_length=500)
uploaded_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.song_title
urls.py
url(r'^(?P<pk>[0-9]+)/upload/$', views.model_form_upload, name='upload')
model_form_upload.html
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Upload</button>
</form>
{% if uploaded_file_url %}
<strong>Song:</strong>
<audio controls>
<source src="{{ uploaded_file_url }}" type="audio/mpeg">
</audio>
<h2>Modal Example</h2>
<!-- Trigger the modal with a button -->
<button type="button" class="btn btn-info btn-lg" data-toggle="modal" data-target="#myModal">Open Modal</button>
<!-- Modal -->
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<p>Some text in the modal.</p>
<strong>Song:</strong>
<audio controls>
<source src="{{ uploaded_file_url }}" type="audio/mpeg">
</audio>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
{% endif %}

it's just because you're trying to create a song without an Album instance, based on your models structure album = your models.ForeignKey(Album, on_delete=models.CASCADE), you set the album field non-null, so the ForeignKey can't remain empty or Null.
You can either set that field nullable and instead of models.CASCADE, you just add models.SET_NULL plus a signal /pre_delete/post_delete to album in order to delete all the songs related.
class Album(models.Model):
artist = models.CharField(max_length=100)
''' codes '''
class Song(models.Model):
album = models.ForeignKey(Album, on_delete=models.SET_NULL,
null=True,blank=True)
#receiver(pre_delete, sender=Album)
def delete_songs_with_album(sender, instance, *args, **kwargs):
instance.song_set.all().delete()
Or you can instead of having the field album = models.ForeignKey(Album, on_delete=models.CASCADE) in Song, you change your models structure a little bit by removing that field, and add new field ManyToManyField to Song in Album
class Album(models.Model):
artist = models.CharField(max_length=100)
songs = models.ManyToManyFIeld('Song',blank=True)
''' codes '''
class Song(models.Model):
# REMOVE album = models.ForeignKey(Album, on_delete=models.CASCADE) # Remove
''' fields '''
You can still have the signal in the latter case to delete all the songs with an Album

There is no album_id passed into your context, so this error message pops.
So in your modelform, add an album field.
forms.py
class SongForm(forms.ModelForm):
class Meta:
model = Song
fields = ('song_title', 'audio_file', 'album')
Then get the album in your view and pass the album.id into your context.
views.py
def model_form_upload(request, pk):
all_song = Song.objects.all()
print'\n-------------------------------------------------------'
if request.method == 'POST':
print request.FILES
form = SongForm(request.POST, request.FILES)
if form.is_valid():
album = request.POST['album'] #getting the album object
songName = request.FILES['audio_file'] #getting song name
fs = FileSystemStorage() #allocate memory
uploaded_file_url = fs.url(songName) #getting url of uploaded file
form.save() #song saved
return render(request, 'music/model_form_upload.html', {'uploaded_file_url': uploaded_file_url, 'form': form, 'id': album.id})
else:
form = SongForm()
return render(request, 'music/model_form_upload.html', {'form': form, 'all_song': all_song})
Hope it helps

Related

I am confused while rendering my views.py "Django"

My vews.py:
if you want me to share another piece of information feel free to ask!
I just have a problem with the bidding system !!, I tried the bidding but when I add the new number into the input field and click the place bid button the page just reloads which means the function doesn't work!!
I have another problem when I try to close the bid I git this Django error
ValueError at /bidding/26
The view auctions.views.bidding didn't return an HttpResponse object.
It returned None instead.
The code:
def viewList(request, id):
# check for the watchlist
listing = Post.objects.get(id=id)
user = User.objects.get(username=request.user)
if listing.watchers.filter(id=request.user.id).exists():
is_watched = True
else:
is_watched = False
if not listing.activate:
if request.POST.get('button') == "Close":
listing.activate = True
listing.save()
else:
price = request.POST.get('bid', 0)
bids = listing.bids.all()
if user.username != listing.creator.username:
if price <= listing.price:
return render(request, 'auctions/item.html', {
"listing": listing,
'form': BidForm(),
"message": "Error! Your bid must be largest than the current bid!",
'comment_form': CommentForm(),
'comments': listing.get_comments.all(),
'is_watched': is_watched,
})
form = BidForm(request.POST)
if form.is_valid():
bid = form.save(commit=False)
bid.user = user
bid.save()
listing.bids.add(bid)
listing.bid = price
listing.save()
else:
return render(request, 'acutions/item.html', {'form'})
context = {
'listing': listing,
'comment_form': CommentForm(),
'comments': listing.get_comments.all(),
'is_watched': is_watched,
'form': BidForm()}
return render(request, 'auctions/item.html', context)
models.py
class Bid(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
bid = models.DecimalField(max_digits=10, decimal_places=2)
time = models.DateTimeField(default=timezone.now)
class Post(models.Model):
# data fields
title = models.CharField(max_length=64)
textarea = models.TextField()
# bid
price = models.FloatField(default=0)
currentBid = models.FloatField(blank=True, null=True)
imageurl = models.CharField(max_length=255, null=True, blank=True)
category = models.ForeignKey(
Category, on_delete=models.CASCADE, default="No Category Yet!", null=True, blank=True)
creator = models.ForeignKey(
User, on_delete=models.PROTECT, related_name="all_creators_listings")
watchers = models.ManyToManyField(
User, blank=True, related_name='favorite')
date = models.DateTimeField(auto_now_add=True)
# for activated the Category
activate = models.BooleanField(default=False)
bids = models.ManyToManyField(Bid, )
def __str__(self):
return f"{self.title} | {self.textarea} | {self.date.strftime('%B %d %Y')}"
item.html
<div class="card-body">
<ul class="list-group">
<div class="info">
<li class="list-group-item mb-2">Description:<br>{{listing.textarea}}</li>
<li class="list-group-item mb-2">category: {{listing.category.name}}</li>
<li class="list-group-item mb-2"><h5>Start bid: {{listing.price}}$</h5></li>
</div>
<div class="newbid">
<p>{{ message }}</p>
<form action="{% url 'viewList' listing.id %}" method="POST">
{% csrf_token %}
<div class="form-group">
<label for="bid">{{ listing.bids.count }} bid(s) so far. Your bid is the current bid</label>
</div>
<div class="form-group">
{{ form }}
</div>
<div class="form-group">
<input type="submit" name="button" class="btn btn-primary" value="Place Bid">
</div>
</form>
{% if listing.activate %}
<li><strong>Winner: </strong>{{ listing.bids.last.user.username }}</li>
{% endif %}
{% if user.username == listing.creator.username and not listing.activate %}
<form action="{% url 'viewList' listing.id %}" method="POST">
{% csrf_token %}
<button type="submit" name="button" class="btn btn-danger" value="Close">Close</button>
</form>
{% endif %}
</div>
</ul>
</div>
inside this view, I added a punch of my project requirement (comments/watchlist(bookmark)/and the last thing(that what I have a lot of problem with it) is the system of Bid) that lets users add bids on such posts and let the creator of that post the ability to close it.... please help I am sticking in this zone, I tried many times to understand!
Note I am new at Back-end Development!
There is the two problem in you code first one is hi-lighted by Husam
user = User.objects.get(username=request.user.username)
and the other one is in the return statement in the else part
render(request, 'acutions/item.html', {'form'}) instead of context object you pass the string in which is consider as set object in python and thats why you are getting None type error.
here is the refactored code :-
def viewList(request, id):
# check for the watchlist
listing = Post.objects.get(id=id)
user = User.objects.get(username=request.user.username)
form = BidForm()
is_watched = listing.watchers.filter(id=request.user.id).exists():
context = {}
if not listing.activate:
if request.POST.get('button') == "Close":
listing.activate = True
listing.save()
else:
price = request.POST.get('bid', 0)
bids = listing.bids.all()
if user.username != listing.creator.username:
if price <= listing.price:
context.update({'message':"Error! your bid must be largest than the current bid !"})
else:
form = BidForm(request.POST)
if form.is_valid():
bid = form.save(commit=False)
bid.user = user
bid.save()
listing.bids.add(bid)
listing.bid = price
listing.save()
else:
return render(request, 'acutions/item.html', {'form': form})
context.update({'listing': listing,
'comment_form': CommentForm(),
'comments': listing.get_comments.all(),
'is_watched': is_watched,
'form': form})
return render(request, 'auctions/item.html', context)
The error you face in bidding view and the view you have shared is view list, it would be better if you shared the bidding view and highlight the error line/s
Anyway I have noticed that this line has one mistake:
user = User.objects.get(username=request.user)
Which suppose to be :
user = User.objects.get(username=request.user.username)
Hope this can help you little bit

Django Form Not Adding to SQLite3 Database

I have the following Django form that is purposed to create a new item in my database. It is returning a 'false-positive' in that it shows a green 'Done' after I hit submit but the record is not actually added to the database. Any ideas what is causing this?
html
<form method="POST">
{% csrf_token %}
{{form}}
<div style="color:green">{{info}}</div>
<div style="color:red">{{error}}</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
views.py
def creator(request):
if request.method == "POST":
form = CommunicationsForm(request.POST)
if form.is_valid():
form.save()
return render(request,'polls/creation.html',{"form":CommunicationsForm,"info":"Done"})
else:
return render(request,'polls/creation.html',{"form":CommunicationsForm})
forms.py
class CommunicationsForm(forms.ModelForm):
class Meta:
model = Communications
fields = "__all__"
widgets = {
'project':forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter your Project Name'}),
'title':forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter a short Title'}),
'intent':forms.Textarea(attrs={'class': 'form-control','placeholder':'Describe the intent and desired outcome of the communication'}),
'date':forms.TextInput(attrs={'class': 'form-control','placeholder':'Select a Date'}),
'channel':forms.Select(attrs={'class': 'form-control','placeholder':'Select a Channel'}),
'content_type':forms.Select(attrs={'class': 'form-control','placeholder':'Select a Content Type'}),
'audience':forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter the Audience(s)'}),
'status':forms.Select(attrs={'class': 'form-control','placeholder':'Select the Status'}),
}
models.py
class Communications(models.Model):
project = models.CharField(max_length=200)
title = models.CharField(max_length=200)
intent = models.CharField(max_length=200)
date = models.CharField(max_length=200)
channel = models.CharField(max_length=200)
content_type = models.CharField(max_length=200)
audience = models.CharField(max_length=200)
status = models.CharField(max_length=200)
def __str__(self):
return self.communication

Problem with textarea "query_utils.DeferredAttribute" message in empty form

I am new in Django and i am making a typical CRUD app. In the "add" section, in the comment textarea this message appears "
<django.db.models.query_utils.DeferredAttribute object at 0x03B446A0>"
and i dont know what to do. I had tried multiples solutions in other stackoverflow questions but i cant find the solutions!
Here's the code
class Turno(models.Model):
date = models.DateTimeField()
person = models.ForeignKey('Person', on_delete=models.CASCADE)
medic = models.ForeignKey('Medic', on_delete=models.CASCADE)
observations = models.CharField(blank=True, max_length=255)
def __str__(self):
return f'{self.date} {self.person} {self.medic}'
def new_turn(request):
if request.method == 'POST':
turnFormPost = TurnForm(request.POST)
if turnFormPost.is_valid():
turnFormPost.save()
return redirect("admin_index")
turnForm = TurnForm(instance=Turno)
context = {
'form':turnForm
}
return render(request,"turn_new.html", context)
class TurnForm(ModelForm):
class Meta:
model = Turno
fields = '__all__'
widgets = {
'date': DateTimeInput(attrs={'type':'date'}),
'observations': Textarea(attrs={'rows':5, 'cols':50})
}
-turn_new.html
<div class="container">
<h2>New Turn</h2>
<form method="POST">
{% csrf_token %}
<table>
{{form}}
</table>
<button type="submit" class="btn btn-primary">Create</button>
</form>
<div>
Back to index
</div>
</div>
in the textarea of 'observations' in 'turn_new.html' the message that appears is this
"<django.db.models.query_utils.DeferredAttribute object at 0x03B446A0>"

Getting "NOT NULL constraint" when submitting form through view. Works fine when adding through /admin

I'm creating a simple ratemyteacher/prof clone. The issue is that when going trying to add a Review object via my view, I get NOT NULL constraint failed: rate_review.review_id (app name is rate). It works fine when adding via /admin. Also, adding other models work fine.
Here's the view where it occurs:
def add_review(request, teacher_id):
form = ReviewForm()
if request.method == 'POST':
form = ReviewForm(request.POST)
if form.is_valid():
ip = request.META.get('HTTP_CF_CONNECTING_IP')
if ip is None:
ip = request.META.get('REMOTE_ADDR')
form.customSave()
messages.success(request, 'Review added.')
else:
form = ReviewForm(request.POST)
return render(request, 'rate/add_review.html', {'form': form})
return render(request, 'rate/add_review.html', {'form': form})
Here is the form (truncated to exclude loads). I'm using this to render forms:
<form method="POST">{% csrf_token %}
<div class="field">
<label class="label">Stars (whole numbers only)</label>
<div class="control">
{% render_field form.stars class+="input" %}
</div>
</div>
<div class="field">
<label class="label">Review subject</label>
<div class="control">
{% render_field form.subject class+="input" %}
</div>
</div>
<div class="field">
<label class="label">Review text</label>
<div class="control">
{% render_field form.text class+="textarea" placeholder="Review text" rows="10" %}
</div>
</div>
<div class="field">
<label class="label">Username</label>
<div class="control">
{% render_field form.author class+="input" placeholder="eg. ReviewerMan21, John Smith" %}
</div>
</div>
<button type="submit" class="button">Add review</button>
</form>
My models.py:
class Teacher(models.Model):
grade = models.IntegerField()
name = models.CharField(max_length=35)
subject = models.CharField(max_length=50)
ip = models.CharField(max_length=14)
approved = models.BooleanField(null=True, blank=True)
class Review(models.Model):
teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)
text = models.TextField()
subject = models.CharField(max_length=120)
author = models.CharField(max_length=35)
ip = models.CharField(max_length=14)
date = models.DateTimeField(auto_now_add=True)
stars = models.PositiveSmallIntegerField()
My forms.py:
from django import forms
from .models import Teacher, Review, Grade
from django.core import validators
class ReviewForm(forms.ModelForm):
class Meta:
model = Review
fields = ('subject', 'text', 'stars', 'author')
def customSave(self, ip):
lv = self.save(commit=False)
lv.ip = ip
lv.save()
return lv
class TeacherForm(forms.ModelForm):
class Meta:
model = Teacher
fields = ('subject', 'name', 'grade')
def customSave(self, ip):
lv = self.save(commit=False)
lv.ip = ip
lv.save()
return lv
Things I've tried:
Resetting/flushing the DB
Commenting out ip, author & stars
Adding blank=True, null=True to ip, stars and author
Migrating DB
Edit: I've fixed (thanks to the answer below) by changing customSave in ReviewForm to this, and then passing the teacher variable from my view:
def customSave(self, ip, teacher):
lv = self.save(commit=False)
lv.ip = ip
lv.teacher = teacher
lv.save()
return lv
Your error shows that review_id is None (null). I notice that your ForeignKey field to Teacher on the Review model is named review instead of teacher, which would indicate the review_id really belongs to a Teacher object.
I noticed the first line of your view add_review method, you get a Teacher object but never do anything with it. Did you intent to set the teacher ('review' field) on your newly created review to this teacher instance?

Cannot assign "'Album object (6)'": "Music.album_id" must be a "Album" instance

I spend a lot of time in google and find a few solutions for my problem
but none of them works :((
models :
class Album(models.Model):
name = models.CharField(max_length=100)
author = models.CharField(max_length=100)
picture_address = models.TextField(max_length=1000)
creation_year = models.IntegerField(default=-1)
rate = models.IntegerField(default=0)
class Music(models.Model):
name = models.CharField(max_length=100)
cover = models.ImageField(upload_to=upload_destination)
album_id = models.ForeignKey(Album, on_delete=models.CASCADE)
and here is form :
class music_create_form(forms.ModelForm):
album_options = [('', '')]
for album in models.Album.objects.all():
album_options.append((album,album.name))
name = forms.CharField(required=True
, widget=forms.TextInput(attrs={'class': "normal_padding form-control"}))
cover = forms.FileField(required=True
, widget=forms.FileInput(attrs={'class': "normal_padding", 'accept': "image/jpeg"}))
album_id = forms.Field(required=True
,
widget=forms.Select(attrs={'class': "normal_padding form-control"}, choices=album_options))
class Meta:
model = models.Music
fields = [
'name', 'cover', 'album_id'
]
and here is view :
def create_music(request):
form = forms.music_create_form(request.POST or None, request.FILES or None)
context = {'form': form}
if request.method == "POST":
if form.is_valid():
print(form)
data = form.save(commit=False)
data.save()
context['action_done'] = True
return render(request, 'music/create_music.html', context)
when i try to add new model with that form , i got the error at this line : " if form.is_valid() "
Cannot assign “'Album object (6)'”: “Music.album_id” must be a “Album” instance
This is my form in template :
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="container">
<div class="form-inline">
<h5 class="normal_padding">Music Name:</h5>
{{ form.name }}
</div>
<div class="form-inline">
<h5 class="normal_padding">Music Cover:</h5>
{{ form.cover }}
</div>
<div class="form-inline">
<h5 class="normal_padding">Album:</h5>
{{ form.album_id }}
</div>
<button type="submit" class="btn btn-primary">save data</button>
</div>
</form>
You shouldn't use forms.Field. In this case, you should use a ModelChoiceField, that will take care of getting the choices for you.
class MusicCreateForm(forms.ModelForm):
name = forms.CharField(required=True
, widget=forms.TextInput(attrs={'class': "normal_padding form-control"}))
cover = forms.FileField(required=True
, widget=forms.FileInput(attrs={'class': "normal_padding", 'accept': "image/jpeg"}))
album_id = forms.ModelChoiceField(queryset=Album.objects.all(),
widget=forms.Select(attrs={'class': "normal_padding form-control"}))
As an aside, it would be better to rename your ForeignKey and form field to album. That way music.album is the related album and music.album_id is it's id. At the moment, music.album_id is the album and music.album_id_id is the id.

Categories

Resources