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
}
?>
Related
I'm still a beginner in Django and building a management system, I wish to display content from the database using a for loop from 2 tables(GoCustomerRegisration and GoCustomerStatus). But unfortunately, when I iterate over one table the other table brings me only the last element of that table. What I really wish to do is iterate over both tables at once and each element should correspond to it on the other table.
Check out my code below:
something.html
{% for item in detail %}
<tr>
<td>
<a class="text-black text-decoration-none" href="{{ item.photo.url }}">
<img class="rounded-circle me-2" style="object-fit: contain; background-color:#91debb; border:1px solid palegreen;" alt="" width="30" height="30" src="{{ item.photo.url }}"></a>
</td>
<td>
<a class="text-black lg:hover:text-blue-400 text-decoration-none" href="{% url 'customer_detail' pk=item.id %}">{{ item.name }}</a>
</td>
<td class="text-capitalize">{{ item.type }}</td>
<td>{{ item.destination }}</td>
<td>{{ item.age }}</td>
<td>{{ item.time_of_submission }}</td>
<td>
<span>{{ hello.value }}%</span>
<div class="col">
<div class="progress progress-sm">
<div class="progress-bar progress-bar-striped bg-success" aria-valuenow="{{ hello.value }}" aria-valuemin="0" aria-valuemax="100" style="width: {{ h.value }}%;"><span class="visually-hidden"></span>
</div>
</div>
</div>
</td>
{% endfor %}
my views.py
#login_required
def preview(request):
global hello
detail = GoCustomerRegistration.objects.all()
next_event = Event.objects.last()
for i in range(1, (len(detail))+1):
print(i)
hello = GoCustomerStatus.objects.get(name_id=i)
print(hello)
context = {
'detail': detail,
'event': next_event,
'hello': hello,
}
return render(request, 'customers_preview.html', context)
my urls.py
from django.urls import path
urlpatterns = [
path('preview/', preview, name='preview'),
]
my models.py
class GoCustomerRegistration(models.Model):
name = models.CharField(max_length=300, verbose_name='Full name')
email = models.EmailField(null=False)
type = models.CharField(max_length=20, verbose_name='Customer Type')
destination = models.CharField(max_length=30, null=False, verbose_name='Destination')
time_of_submission = models.DateTimeField(auto_now_add=True, null=False, verbose_name=' Submit Time')
phone_number = models.IntegerField(verbose_name='Phone number')
age = models.IntegerField(verbose_name="Age", null=False)
photo = models.ImageField(max_length=10000, verbose_name='Customer Picture',
null=False, upload_to='customers/profiles/')
documents = models.FileField(upload_to='%Y/customers/documents/')
class Meta:
ordering = ["time_of_submission"]
verbose_name = "Customer Registration"
verbose_name_plural = "Customers Registration"
def __str__(self):
return self.name
class GoCustomerStatus(models.Model):
name = models.OneToOneField(GoCustomerRegistration,
max_length=300, verbose_name='Full name',
on_delete=models.CASCADE, primary_key=True,
null=False,
)
value = models.IntegerField(default=0, verbose_name='Level', null=False, primary_key=False)
class Meta:
verbose_name_plural = 'Customers Status'
verbose_name = 'Customer\'s Status'
def __str__(self):
return self.name.name
I am creating a bulletin board that communicates by DB <> API <> WEB method.
I want to create a view to delete comments, but an Improperly Configured error occurs when I request to delete comments from the web. Can I define a query set without Model,DB? Or is my code a problem? Which view should I use?
Improperly Configured Error with deleteview, Method not allowed with view
generic.deleteview
view
WEB view.py
class Commentapi_delete(generic.DeleteView):
def delete(self, request, *args, **kwargs):
datas = {
'pk': self.kwargs['pk'],
'id': self.kwargs['id']
}
url = 'http://127.0.0.1:8080/boardapi/' + str(datas['pk']) + '/comment/' + str(datas['id']) + '/delete/'
c_delete = requests.delete(url, params=datas)
print(datas)
print(c_delete)
return redirect(reverse('board_detail', kwargs={'pk': self.kwargs['pk']}))
API view.py
class CommentUpdateDeleteView(generics.RetrieveUpdateDestroyAPIView):
model = Comment
queryset = Comment.objects.all()
serializer_class = CommentSerializer
EDIT
WEB view.py
class Commentapi_delete(generic.DeleteView):
def get(self, request, *args, **kwargs):
data ={
'pk': self.kwargs['pk'],
'id': self.kwargs['id']
}
url = 'http://127.0.0.1:8080/boardapi/' + str(data['pk']) + '/comment/'
c_get = requests.get(url, params=data)
return **What shoud i return?**
def post(self, request, *args, **kwargs):
datas = {
'pk': self.kwargs['pk'],
'id': self.kwargs['id']
}
url = 'http://127.0.0.1:8080/boardapi/' + str(datas['pk']) + '/comment/' + str(datas['id']) + '/delete/'
c_delete = requests.delete(url, params=datas)
print(datas)
print(c_delete)
return redirect(reverse('board_detail', kwargs={'pk': self.kwargs['pk']}))
html
<form action="{% url 'comment_delete' %}" method="POST">
{% csrf_token %}
<td style="vertical-align: top;border-top: 1px solid #eee;padding: 10px 0;padding-right: 5px;" align="right" width="10%">
<button class="btn btn-outline-success my-2 my-sm-0" style="margin-right:10px;">Delete</button>
</td>
</form>
</tr>
</tbody>
</table>
{% endfor %}
</div>
<div>
<form method="POST">
{% csrf_token %}
<table width="100%" cellpadding="0" cellspacing="0">
<tr style="height:45px;border-top:solid 1px #dddddd;">
<td width="20%" align="left" style="vertical-align: top; padding-top: 10px;"><input type="input" name="c_writer" placeholder="writer" /></td>
<td width="80%" align="left" style="vertical-align: top; padding-top: 10px;"><textarea name="c_note" rows="4"></textarea></td>
</tr>
</table>
<div>
<button class="btn btn-outline-success my-2 my-sm-0" style="margin-right:10px;">save</button>
</div>
</form>
Error
The generic.DeleteView seems to be the correct one, but you haven't defined your queryset, you did so in your CommentUpdateDeleteView(generics.RetrieveUpdateDestroyAPIView), u should either define you queryset in a similar way on your Commentapi_delete(generic.DeleteView) or override the get_queryset method on the class to return you own desired queryset.
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.
This is my models.py file
class Report_item(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
title = models.CharField(max_length=255, help_text='*Title for the post e.g. item identity')
item_type = models.CharField(default="", max_length=100,
help_text='*Enter the item name you found e.g. Marksheet,key,wallet')
location = models.CharField(max_length=60, help_text='*Enter the address/street where you find this item')
city = models.CharField(max_length=60, help_text='*Enter the city name')
date = models.DateTimeField(default=timezone.now)
Description = models.TextField(blank=True,null=True,help_text='*Enter full description about item')
publish = models.BooleanField(default=False)
image = models.ImageField(default="add Item image",
help_text='*Please uplocad a item image to identify by the owner')
def __str__(self):
return self.title + " " + str(self.publish)
def get_absolute_url(self):
return reverse('feed:detail', kwargs={'pk': self.pk})
class Meta:
ordering = ["-date"]
This is my upload views:
class ReportCreate(generic.CreateView):
model = Report_item
fields = ['title', 'item_type', 'location', 'city', 'image', 'Description']
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.owner = self.request.user
self.object.save()
return FormMixin.form_valid(self, form)
This is my view.py file
def IndexView(request):
query_list = Report_item.objects.filter(publish=True)
query = request.GET.get('q')
if query:
query_list = query_list.filter(Q(title__icontains=query) |
Q(item_type__icontains=query) |
Q(city__icontains=query) |
Q(location__icontains=query) |
Q(Description__icontains=query)).distinct()
context = {
"object_list": query_list
}
return render(request, "feed/index.html", context)
This is my feed/index file
{% for obj in object_list %}
<div class="thumbnail" onclick="window.open('{% url 'feed:detail' obj.id %}','mywindow');" style="cursor: pointer;">
<div class="row">
<div class="col-md-9">
<table class="mytable table-responsive">
<tr><td class="my-td-item">Title</td><td>{{ obj.title }}</td></tr>
<tr><td class="my-td-item">Item Type</td><td>{{ obj.item_type }}</td></tr>
<tr><td class="my-td-item">Location</td><td>{{ obj.location }}</td></tr>
<tr><td class="my-td-item">City</td><td>{{ obj.city }}</td></td></tr>
</table>
</div>
<div class="col-md-3">
<img class="img-responsive center" src="{{ obj.image.url }}" alt="backmyitem" width="80" height="100" style="margin: 0 auto;">
<br><b><p style="font-size: 10px;text-align:center;">Posted Date</b><br>{{ obj.date }}</p>
</div>
</div>
<div class="row">
<div class="more-detail-div col-md-12">
<a class="">More Detail</a>
</div>
</div>
</div>
{% endfor %}
When I upload an image from my laptop in my application, the image upload successfully and also images display in feed/index.html but at the same time when the same image I upload using my mobile phone or any other mobile devices then It causes the error. Even the image upload successfully but in the admin section as well as in the feed page image upload successfully and its name and path is also correct but is not display in admin as well as in the index file When I try to open the image in a new tab then it shows 403 forbidden.
The error in the ngin
2018/08/20 19:34:37 [error] 4498#4498: *89 open() "/home/ubuntu/media/153476127499997915256.jpg" failed (13: Permission denied), client: 103.201.$
x-error log is following:
I have a dat_transacao field and I'd like to create a range with it, but it didn't work. I created dat_inicial and dat_final in filters.py, but the screen didn't filter the records by these fields. Something is wrong but I don't know what is it. Anyone can help me please?
Thanks.
models.py:
class transacao(models.Model):
dat_transacao = models.DateTimeField('Geração da Transação', auto_now=True)
pessoa = models.ForeignKey(pessoa, default='', blank=True, null=True) # Chave estrangeira da Classe Pessoa
tipotransacao = models.ForeignKey(tipotransacao, default='', blank=True, null=True) # Chave estrangeira da Classe Tipo de Transação
servico = models.ForeignKey(servico, default='', blank=True, null=True) # Chave estrangeira da Classe Servico (que pode ser NULL)
bloco = models.ForeignKey(bloco, default='', blank=True, null=True) # Chave estrangeira da Classe Bloco
filters.py:
from .models import *
import django_filters
#from django_filters import DateTimeFilter
class livrorazaoFilter(django_filters.FilterSet):
dat_inicial = django_filters.DateTimeFilter(name='dat_transacao',lookup_type=('gte'))
dat_final = django_filters.DateTimeFilter(name='dat_transacao',lookup_type=('lte'))
class Meta:
model = transacao
fields = ['dat_inicial', 'dat_final', 'tipotransacao', 'pessoa', 'bloco']
views.py
def transacao_livrorazao(request, id=None):
instancia_transacao = transacao.objects.all().order_by('-dat_transacao')
instancia_transacaofilter = livrorazaoFilter(request.GET, queryset=instancia_transacao)
context = {
"queryset": instancia_transacao,
"filter": instancia_transacaofilter,
"instancia_transacao": instancia_transacao
}
return render(request, 'livrorazao/livrorazao.html', context)
livrorazao.html:
<!DOCTYPE html>
<html dir="ltr">
<form class=" bd-form-2 " action="#" name="form-name" method="get">
{% csrf_token %}
<p>Período</p>
<p>De</p>
<input type="date" name='filter.form.dat_inicial' id="dat_inicial" class="bd-form-input" >
<p>até</p>
<input type="date" name='filter.form.dat_final' id="dat_final" class="bd-form-input" >
<p>Tipo de Transação</p>
{{ filter.form.tipotransacao }}
<button type="submit">Consultar</button>
</form>
<br>
<table width="100%" border="0" cellspacing="1" cellpadding="2">
<tbody><tr>
<th>ID Transação</th>
<th>Data/Hora</th>
<th>TipoTransação</th>
<th>Blockchain</th>
</tr>
{% for instance in filter.qs %}
<tr>
<td>{{ instance.id }}</td>
<td>{{ instance.dat_transacao }}</td>
<td>{{ instance.tipotransacao }}</td>
<!--<td>{{ instance.pessoa }}</td>-->
<td>{{ instance.bloco }}</td>
</tr>
{% endfor %}
</tbody></table>
</html>
my solution is similar to what #cezar posted. However, changing attrs={'class': 'datepicker'} to attrs={'type': 'date'} was what worked for me.
my frontend form display is managed using django-widget-tweaks
Here is an extract of what works for me:
models.py
class Applications(models.Model):
#...
status = models.CharField(max_length=10, choices=STATUS)
start_date = models.DateTimeField(auto_now_add=True)
filters.py
from .models import Applications
import django_filters
class ApplicationFilter(django_filters.FilterSet):
start_date = django_filter.DateTimeFromRangeFilter(widget=django.widgets.RangeWidget(
attrs={'type': 'date'}))
class Meta:
model = Applications
fields = ['status', 'start_date']
views.py
from django.shortcuts import render
from .models import Applications
from .filters import ApplicationFilter
def application_search(request):
#... I stripped the view function down to what concerns filters.py
application_list = Application.objects.all()
application_filter = ApplicationFilter(request.GET, queryset=application_list)
return render(
request,
"applications.html,
{'filter': application_filter}
)
applications.html (with bootstrap)
...
{% load bootstrap4 %}{% load widget_tweaks %}
<form method="GET" class="form-inline">
<div class=form-group>
<label style="margin-right: 20px">Filter: </label>
{% render_field filter.form.status class="form-control"%}
<label style="margin-left: 20px; margin-right: 10px;">From </label>
{% render_field filter.form.start_date class="form-control" %}
<button style="margin-left: 10px" class="btn btn-primary btn-md">
GO
</button>
</div>
</form>
...
P.S: By default, I'd added django_filters to settings.py
Here's how the form looks
You could use the DateFromToRangeFilter. Instead of dat_inicial and dat_final add this snippet to your FilterSet class:
dat_transacao = django_filters.DateTimeFromToRangeFilter()
This filter should create two input fields and query for entries having values between the lower and upper limit. By passing further arguments you can modify the look and behaviour, for example add datepicker:
dat_transacao = django_filters.DateTimeFromToRangeFilter(
widget=django_filters.widgets.RangeWidget(
attrs={'class': 'datepicker'}
)
)
Adapt after that your HTML template as needed. Basically it should work with these lines:
<form class="bd-form-2 " action="" name="form-name" method="get">
{% csrf_token %}
{{ filter.form }}
<button type="submit">Consultar</button>
</form>