The 'image' attribute has no file associated with it - python

I have been trying to update image since I added an ImageField to model.py but it always gives me this error The 'image' attribute has no file associated with it.
From Admin panel given by Django I can do so I can add and update, but I need to create my own way of updating images but id doesn't work.
Here are my attachments
This is my model
class rooms(models.Model):
room_number = models.PositiveIntegerField(unique = True)
room_type = models.ForeignKey(room_types, on_delete=models.CASCADE)
number_of_beds = models.PositiveIntegerField()
image = models.ImageField(upload_to = 'room_pics/', null = True, blank = True)
price = models.PositiveIntegerField(default=0)
class Meta:
verbose_name_plural = 'Rooms'
def __str__(self):
room_number = "Room number: " + str(self.room_number)
return room_number
Here is a form from forms.py
class addRoomForm(forms.ModelForm):
class Meta:
model = rooms
fields = ['room_number', 'room_type', 'number_of_beds', 'price', 'image']
and here are the views from views.py to add and update
def add_room(request):
form = addRoomForm()
if request.method == 'POST':
form = addRoomForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, f'Room added successfully!')
return redirect('add_room')
else:
form = addRoomForm()
context = {
'form' : form,
}
myTemplate = 'hotel/addRoom.html'
return render(request, myTemplate, context)
def update_room(request, id):
instance = get_object_or_404(rooms, pk = id)
form = addRoomForm(request.POST or None, instance = instance)
if form.is_valid():
form.save()
messages.success(request, f'Room has been updated successifully!')
return redirect ('view_rooms')
context = {
'form': form,
}
myTemplate = 'hotel/addRoom.html'
return render(request, myTemplate, context)`
and the template source code is
<div class=" w3-card">
<table class="table table-hover table-bordered">
<thead>
{% if room.image.url %}
<tr>
<img src="{{room.image.url}}" alt="image" width="711px" height="400px;">
</tr>
{% endif %}
</thead>
<tbody>
<tr>
<td>Room number</td>
<td>{{room.room_number}}</td>
</tr>
<tr>
<td>Room Type</td>
<td>{{room.room_type}}</td>
</tr>
<tr>
<td>Number of beds</td>
<td>{{room.number_of_beds}}</td>
</tr>
<tr>
<td>Price</td>
<td>{{room.price}}</td>
</tr>
<tr>
<td><i class="fa fa-edit"></i>
<i class="fa fa-trash"></i>
</td>
</tr>
</tbody>
</table>
</div>

It should be form = addRoomForm(request.POST, request.FILES)
See File Uploads, Here is detailed and good documented tutorial for you.

Related

Django Multiple Files Upload

I would like to upload multiples files in my model in Django. I am struggling on the HTML part. I would like to include it part of my detail view without having to create a special view to upload the files. When I click on the button, it open the file upload, I select them but they don`t seem to be attached to the model. Any ideas please?
models.py
class Quote(models.Model):
name = models.CharField(max_length=30)
class Attachment(models.Model):
quote = models.ForeignKey(Quote, on_delete=models.CASCADE, blank=True, null=True)
name = models.CharField(max_length=30)
file = models.FileField(upload_to='quotes/%Y/%m/%d',blank=True, null=True)
def __str__(self):
return self.name
forms.py
class AttachmentForm(forms.ModelForm):
class Meta:
model = Attachment
fields = ('file', )
widgets = {
'file': ClearableFileInput(attrs={'multiple': True}),
}
# widget is important to upload multiple files
views.py
#login_required(login_url="/login/")
def add_attachment(request, quote_id):
form = AttachmentForm(request.POST or None, request.FILES or None)
quote = get_object_or_404(Quote, pk=quote_id)
if form.is_valid():
quotes_attachments = quote.attachment_set.all()
attachment = form.save(commit=False)
attachment.quote = quote
attachment.attachments = request.FILES['attachments']
file_type = attachment.attachments.url.split('.')[-1]
file_type = file_type.lower()
attachment.save()
return render(request, 'quotes/quote_detail.html', {'quote': quote})
context = {
'quote': quote,
'form': form,
}
return render(request, 'quotes/quote_detail.html', context)
quote_detail.html
<div class="card-block">
<form action="/static/assets/plugins/fileupload/js/file-upload.php" method="post" class="dropzone" enctype="multipart/form-data" >
<div class="fallback">
<input name="file" type="file" multiple
style="display: none;"
data-url="{% url 'projects:add_attachment' quote.id %}"
data-form-data='{"csrfmiddlewaretoken": "{{ csrf_token }}"}'>
</div>
</form>
<table id="table" class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>File Name</th>
<th>File</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ quote.attachments.id }}</td>
<td></td>
<td><a target="_blank" href="{{ quote.attachments.url }}"><i class="fas fa-eye"></i></a></td>
</tr>
</tbody>
</table>
</div>
file-upload.php
<?php
$ds= DIRECTORY_SEPARATOR; //1
$storeFolder = 'uploads'; //2
if (!empty($_FILES)) {
$tempFile = $_FILES['file']['tmp_name']; //3
$targetPath = dirname( __FILE__ ) . $ds. $storeFolder . $ds; //4
$targetFile = $targetPath. $_FILES['file']['name']; //5
move_uploaded_file($tempFile,$targetFile); //6
}
?>

Django:Child Model Fields Not Rendering

All Foreign Keys,Booleans and Choices fields are not rendering on the form template.But their label tags are rendering.
For example:
This is a "Generated TimeTable" model of a school system.
The model
class GT(models.Model):
timetable_id = models.CharField(primary_key=True,max_length=200)
period_number = models.ForeignKey(Ref_Period,on_delete=models.CASCADE)
scheduled_date_and_time = models.ForeignKey(Ref_Calendar,on_delete=models.CASCADE)
schedule_id = models.ForeignKey(Planned_Timetable,on_delete=models.CASCADE)
subject = models.ForeignKey(Ref_Subject,on_delete=models.CASCADE)
teacher_id = models.ForeignKey(Teacher,on_delete=models.CASCADE)
def __str__(self):
return str(self.teacher_id)
I already imported the in the forms.py file
forms.py
class GTForm(ModelForm):
class Meta:
model = GT
fields = '__all__'
View:
#login_required(login_url = 'main:loginPage')
#allowed_users(allowed_roles=['admin'])
def dalltt(request):
gtform = GTForm()
if request.method == "POST":
gtform = GTForm(request.POST)
print(gtform)
if gtform.is_valid():
gtform.save()
print("saved")
return redirect('/')
else:
print(gtform.errors)
print(gtform)
context = {'gtform':gtform}
return render(request=request,template_name="main/dalltimetable.html",context=context)
The template(dalltimetable.html):
<form enctype="multipart/form-data" action="" method="POST" >
{% csrf_token %}
<table>
<tr>
<th>ID</th>
<th>Time</th>
<th>Day</th>
<th>Subject</th>
<th>{{ gtform.teacher_id.label_tag }} </th>
</tr>
<tr>
<td>{{ gtform.teacher_id }} </td>
<td>{{ gtform.teacher_id }}</td>
</tr>
</table>
<input class="btn btn-warning" type="submit" value="Update">
{{ form.name.errors }}
{{ form.non_field_errors }}
</form>
Give this a try:
#login_required(login_url = 'main:loginPage')
#allowed_users(allowed_roles=['admin'])
def dalltt(request):
if request.method == "POST":
gtform = GTForm(request.POST)
print(gtform)
if gtform.is_valid():
gtform.save()
print("saved")
return redirect('/')
else:
print(gtform.errors)
else:
gtform = GTForm()
return render(request, 'main/dalltimetable.html', {'gtform': gtform })
Also maybe try switching to class-based views to help with the boilerplate:
class dalltt(LoginRequiredMixin, FormView):
template_name = 'main/dalltimetable.html'
form_class = GTForm
success_url = '/'
login_url = 'main:loginPage'
def form_valid(self, form):
form.save()
return super().form_valid(form)
def form_invalid(self, form):
print(form.errors)

How to fetch data from different tables in Django?

I am new to Django and Python,
I have a table for clients, and one for trips. I can display the clients on the clients page, and the same for the trips.
But on the clients page, I want to show all the trips that are linked to each client. And this is where I hit a wall.
This is my models.py
from django.db import models
from django.core.validators import RegexValidator
# Create your models here.
class Clientes(models.Model):
nome = models.CharField(max_length=30)
apelido = models.CharField(max_length=30)
morada = models.CharField(max_length=200)
tel = models.CharField(max_length=9, validators=[RegexValidator(r'^\d{1,10}$')])
nif = models.CharField(max_length=9, validators=[RegexValidator(r'^\d{1,10}$')])
def __str__(self):
return "%s %s" % (self.nome, self.apelido)
class Meta:
verbose_name_plural = "Clientes"
class Viagem(models.Model):
trip_id = models.CharField(max_length=30)
cliente = models.ForeignKey(Clientes, on_delete=models.CASCADE)
comp = models.CharField(max_length=30)
data = models.DateField()
destino = models.CharField(max_length=30)
def __str__(self):
return self.trip_id
class Meta:
verbose_name_plural = "Viagens"
This is my views.py
from django.shortcuts import render
from django.http import HttpResponse
from .models import Clientes, Viagem
# Create your views here.
def index(request):
ls= Clientes.objects.all()
context = {'ls': ls}
return render(request, "booking/home.html", context)
def cliente(request, id):
ls= Clientes.objects.filter(id=id)
context = {'ls': ls}
return render(request, "booking/cliente.html", context)
def trip(request):
ls= Viagem.objects.all()
context = {'ls': ls}
return render(request, "booking/trip.html", context)
and this is the table on the home.html
<table id="selector" class="table is-fullwidth is-hoverable">
<thead>
<tr>
<th>Nome</th>
<th>Apelido</th>
<th>Morada</th>
<th>Telemóvel</th>
<th>NIF</th>
<th>Viagens</th>
</tr>
</thead>
<tbody>
{% for ls in ls %}
<tr>
<td>{{ls.nome}}</td>
<td>{{ls.apelido}}</td>
<td>{{ls.morada}}</td>
<td>{{ls.tel}}</td>
<td>{{ls.nif}}</td>
<td>{{ls.trip_id}}</td>
</tr>
{% endfor %}
</tbody>
</table>
I assume it has something to do with ForeignKey, but a ForeignKey on the first class won't work.
I thought about creating a new def on the views.py using the Viagem table and a diferent context, but that also doesn't seem to be the solution.
So, anyone can point me in the right direction?
In your views.py, specifically the cliente function, you want to add the following line:
viagems=Viabem.objects.filter(cliente=ls)
modify the following line:
ls= Clientes.objects.filter(id=id)
so that it now shows:
ls=Clientes.objects.get(id=id)
and then change your context to equal:
context = {'ls': ls, 'viagems': viagems}
then you will be able to iterate over the different viagems in your html template file with the following kind of structure:
{% for viagem in viagems %}
{{ viagem.whatever_field }}
{% endfor %}
and that should be it, I believe...
Since you are filtering by ID (fetching single object), this is one of the options to go:
views.py
from django.shortcuts import get_object_or_404
def cliente(request, id):
ls = get_object_or_404(Clientes, id=id)
trips = obj.viagem_set.all()
context = {'ls': ls, 'trips': trips}
return render(request, "booking/cliente.html", context)
template.html
<table id="selector" class="table is-fullwidth is-hoverable">
<thead>
<tr>
<th>Nome</th>
<th>Apelido</th>
<th>Morada</th>
<th>Telemóvel</th>
<th>NIF</th>
<th>Viagens</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ls.nome}}</td>
<td>{{ls.apelido}}</td>
<td>{{ls.morada}}</td>
<td>{{ls.tel}}</td>
<td>{{ls.nif}}</td>
<td>{% for trip in trips %}{{ trip.id }}{% endfor %}</td>
</tr>
{% endfor %}
</tbody>
While I'm not sure why you need to show record ID's in the table.
#João de Sousa, I found you want to show all trips that are associated with each client.
First of all you have to get a single client by his id obj = clients.objects.get(id = id) then this id pass to referred model like this obj1 = Viagem.objects.filter( id = obj.id)
According to my understanding from your above posted question is that you want to get help about how you get data from reference model/table. Django provides very easy and flexible way to get data from tables.
Feel free to ask any question if you need more clarification.

Data not saving in sqlite db using Django

I am facing issues in saving data to my sqlite db using Django.
When i am accessing 127.0.0.1/personal/makeentry--> the page shows the form , but when i click on submit after entering the details, the detils are not saved in db.
Below is the code
model.py
from django.db import models
class Account(models.Model):
accountId = models.IntegerField(primary_key=True,unique=True,
blank=False, null=False, auto_created=True)
accountName = models.CharField(max_length=100)
countryName = models.CharField(max_length=100)
marketName = models.CharField(max_length=100)
msdmName = models.CharField(max_length=100)
deliveryManagedFrom = models.CharField(max_length=100)
location = models.CharField(max_length=100)
def __str__(self):
return self.accountName
admin.py
from django.contrib import admin
from .models import Account
# Register your models here.
class AccountAdmin(admin.ModelAdmin):
list_display = ['accountId', 'accountName','countryName', 'marketName',
'msdmName','deliveryManagedFrom','location']
admin.site.register(Account, AccountAdmin)
forms.py
from django import forms
from . models import Account
from django.forms import ModelForm
class AccountForm(forms.Form):
accountName = forms.CharField(label="Account Name", max_length=100)
countryName = forms.CharField(label="Country Name", max_length=100)
marketName = forms.CharField(label="Market Name", max_length=100)
msdmName = forms.CharField(label="MSDM Name", max_length=100)
deliveryManagedFrom = forms.CharField(label="Delivery Managed From", max_length=100)
location = forms.CharField(label="Location", max_length=100)
class AccountForm(ModelForm):
class Meta:
model = Account
fields = ['accountName','countryName', 'marketName', 'msdmName', 'deliveryManagedFrom', 'location']
views.py
from django.shortcuts import render
from django.views import generic
from .models import Account
from .forms import AccountForm
def index(request):
return render(request, 'personal/home.html')
# generic view to fetch the data then show in a list
class IndexView(generic.ListView):
# a name to refer to the object_list(to be used in the index.html)
context_object_name = 'account_list'
template_name = 'personal/index.html'
def get_queryset(self):
return Account.objects.all()
# generic view to show the details of a particular object
class DetailsView(generic.DetailView):
model = Account
template_name = 'personal/detail.html'
def makeentry(request):
if request.method == 'POST':
form = AccountForm(request.POST)
if form.is_valid():
accountName = request.POST.get('Account Name', '')
countryName = request.POST.get('Country Name', '')
marketName = request.POST.get('Market Name', '')
msdmName = request.POST.get('MSDM Name', '')
deliveryManagedFrom = request.POST.get('Delivery Managed From', '')
location = request.POST.get('Location', '')
account = Account(accountName=accountName, countryName=countryName, marketName=marketName, msdmName=msdmName, deliveryManagedFrom=deliveryManagedFrom, location=location)
account.save()
form = AccountForm()
return render(request, 'personal/makeentry.html', {'form': form})
else:
form = AccountForm()
return render(request, 'personal/makeentry.html', {'form': form})
makeentry.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Account Entry</title>
</head>
<body>
<form action="{% url 'makeentry' %}" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
</body>
</html>
detail.html
{% if account_list %}
<table>
<tr>
<td> Account Name </td>
<td> Country Name </td>
<td> Market Name </td>
<td> MSDM Name </td>
<td> Delivery Managed From </td>
<td> Location </td>
</tr>
{% for account in account_list %}
<tr>
<td>{{ account.accountName }}</td>
<td>{{ account.countryName }}</td>
<td>{{ account.marketName }}</td>
<td>{{ account.msdmName }}</td>
<td>{{ account.deliveryManagedFrom }}</td>
<td>{{ account.location }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
I think you are making this harder than it needs to. You have a Form and a ModelForm of the same name. You should just be able to use the ModelForm. If there are attributes you want to pass with your ModelForm check out ModelForm Overriding default widgets. It has also been my experience to set action=“” and let the view handle the redirect on success.
def make_entry(request):
if request.POST:
form = AccountForm(request.POST)
if form.is_valid():
new_form = form.save()
return redirect('where-you-want-to-redirect ',
# View current saved info or change to what you want to show
pk=new_form.pk)

Django ModelForm not rendering in the template

I've looked at several answers here and I can't get this to work. I'm trying to create a model form that will save the user's profile after he has signed up on the website. The problem is that when I try to render the form I get a blank page and no errors. Any help will be much appreciated.
models.py
class Perfil(models.Model):
user = models.OneToOneField(User)
Sexo = models.CharField(max_length=100)
Direccion = models.CharField(max_length=100)
CP = models.CharField(max_length=100)
Ciudad = models.CharField(max_length=100)
Estado = models.CharField(max_length=100)
Pais = models.CharField(max_length=100)
Telefono = models.CharField(max_length=100)
Celular = models.CharField(max_length=100)
PaisPasaporte = models.CharField(max_length=100)
NumeroPasaporte = models.CharField(max_length=100)
VigenciaPasaporte = models.DateField(max_length=100)
ContactoEmergencia = models.CharField(max_length=100)
TelefonoEmergencia = models.CharField(max_length=100)
CorreoEmergencia = models.CharField(max_length=100)
Alergias = models.CharField(max_length=500)
forms.py
class ProfileForm(forms.ModelForm):
class Meta:
model = Perfil
views.py
#verified_email_required()
def profile(request):
if request.method == "POST":
form = ProfileForm(request.POST)
if form.is_valid():
perfil = form.save(commit=False)
perfil.user = request.user
perfil.save()
return HttpResponseRedirect("/profile/")
else:
return render(request, "explore/profile.html", {"form": form})
return render(request, "explore/profile.html")
and finally my html
<form class="profile" id="profile_form" method="post" action="" style="width: 50%;">
{% csrf_token %}
{% for field in form %}
<table>
<colgroup>
<col style="width: 45%;">
<col style="width: 10%;">
<col style="width: 45%;">
</colgroup>
<tr>
<td>{{ field.label_tag }}</td>
<td></td>
<td>{{ field }}</td>
</tr>
</table>
{% endfor %}
</form>
Thanks!
You are sending the form in the context only when request type is POST. The first time the page loads, by default it is a GET request. Hence the issue
Something like this should work:
def profile(request):
form = ProfileForm()
if request.method == "POST":
form = ProfileForm(request.POST)
if form.is_valid():
perfil = form.save(commit=False)
perfil.user = request.user
perfil.save()
return HttpResponseRedirect("/profile/")
return render(request, "explore/profile.html" {'form': form})
Note that you dont need the else clause at all - if the form is invalid, it automatically sends the erroneous form in the context, and your error messages are displayed just fine.

Categories