I have a django model and csv file separately. What I want to do is that user upload a csv file with a single colomn ('fp_Item').If colomn line exists in the django model as per below
(queryset_list.filter(
Q(fp_Item__contains=query)))
I want to retrieve the necessary fields from the database and show within html if does not exists it shouldn't retrieve anything and leave empty but still should have to print the csv file line.
def check_fp(request):
if not request.user.is_active:
return render(request, 'login.html')
else:
if request.method == 'POST' and request.FILES['csv_file2']:
myfile = request.FILES['csv_file2']
fs = FileSystemStorage()
filename = fs.save(myfile.name, myfile)
data = csv.reader(fs.open(filename, mode='r'))
queryset_list = fp.objects.all()
lines=[]
for row in data:
if row[0] != 'fp_Item':
line = row[0]
lines.append(line)
query= line
if query:
queryset_list.filter(
Q(fp_Item__contains=query))
queryset_list= fp.objects.all()
context = {'lines': lines,
'instances': queryset_list,
}
return render(request, 'check_fp.html', context)
context = {'lines': lines,
'instances': queryset_list,
}
return render(request, 'check_fp.html', context)
return render(request, 'check_fp.html', {})
lines.append(line) is working and writing csv column to html file but I couldn't somehow bind the django model and the csv column together. Isn't "if query" method usable for this scenario ?
Here is my html file: I want to match line at retrieve description and detail,timestamp and updated fields from the database. Am I looping false here ?
<tbody>
{% for line in lines %}
{% for instance in instances %}
<tr>
<td width="25%>
{{ line }}
</td></tr>
<td>
{{ instance.description }}
</td>
<td>
{{ instance.detail }}
</td>
<td width="180">
{{ instance.timestamp }}
</td>
<td width="180">
{{ instance.updated }}
</td>
<td width="200">
</td>
</tr>{% endfor %} {% endfor %}
</tbody>
</table>
Instead of this below part,
if query:
queryset_list.filter(
Q(fp_Item__contains=query))
queryset_list= fp.objects.all()
context = {'lines': lines,
'instances': queryset_list,
}
return render(request, 'check_fp.html', context)
you need to modify as per below
queryset_list = FP.objects.filter(FP_Item = query)
context = {'lines': lines,
'instances': queryset_list,
}
Related
I have a simple table with some rows:
My goal is to instantiate the current value of the quantity and eventually save the new data for all the lines.
At the moment I have a simple view:
#login_required
def compilaDocMultiRow(request,pk):
member = get_object_or_404(testaDoc, pk=pk)
family = corpoDoc.objects.filter(doc=pk)
if request.method == "POST":
form = multiCorpoDocForm(request.POST or None)
if form.is_valid():
reg = form.save(commit=False)
reg.doc_id = member.pk
reg.save()
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
else:
print(form.errors)
else:
form = multiCorpoDocForm()
return render(request, "compilaDocMultiRow.html", {'family':family, 'member':member, 'form':form})
Is there a way to do this using only Django?
EDIT 1
I was able to instantiate the value with widget tweaks. I am left with the problem of passing the pk of the line to the form and saving the value.
This is the html code:
{% for item in family %}
<tr>
<td>{{ item.item}}</td>
<td>{{ item.desc }}</td>
{% with field=form.qt %}
<td width="15%">{% render_field field class="form-control" placeholder=item.qt %}
</td>
{% endwith %}
<td></td>
<td></td>
</tr>
{% endfor %}
I want to upload an excel file containing 4 columns and display each column in different page.
views.py
def upload(request):
if "GET" == request.method:
return render(request, 'myapp/upload.html', {})
else:
excel_file = 'WBSdetails.xlsx'
pd.read_excel(excel_file, sheet_name = 'ItemDetails')
return render(request, 'myapp/structuremaster.html')
def structure(request):
structures=ConVehicleMaster.objects.all()
context={
'structures':structures
}
return render(request, 'myapp/structuremaster.html', context)
models.py
class Excel(models.Model):
structure = models.CharField(("Structure"), max_length=150)
segment = models.CharField(("Segment"), max_length=150)
subsegment = models.CharField(("SubSegment"), max_length=150)
element = models.CharField(("Element"), max_length=150)
structuremaster.html
<tbody>
{% for row in WBSdetails %}
{% for cell in row %}
<tr>
<td>{{ cell.structure }}</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
I am new to django and have very little idea. Any help will be appreciated.
How to display only some columns of Django model in a HTML template?
And also: how do I perform a function on one of the records? (amount)?
Right now I'm displaying a whole table of model like that:
my models.py
class Tabela(models.Model):
block_id = models.CharField(max_length=64)
timestamp = models.DateTimeField()
type = models.CharField(max_length=32)
link = models.CharField(max_length=64)
link_as_account = models.CharField(max_length=100)
account = models.CharField(max_length=100)
amount = models.CharField(max_length=64)
def __str__(self):
return self.block_id
My views.py
def search_results(request):
model = Tabela
query_addresse = request.GET.get('addressee', None)
query_hash = request.GET.get('hash', None)
if not query_hash and not query_addresse and request.method == 'GET':
return render(request, 'nanosite/index.html', {})
if query_hash and request.method == 'GET':
if query_addresse:
result = Tabela.objects.filter(account=query_addresse, block_id=query_hash)
else:
result = Tabela.objects.filter(block_id=query_hash)
field_names = [f.name for f in model._meta.get_fields()]
data = [[getattr(ins, name) for name in field_names]
for ins in result]
elif query_addresse and request.method == 'GET':
result = Tabela.objects.filter(account=query_addresse)
field_names = [f.name for f in model._meta.get_fields()]
data = [[getattr(ins, name) for name in field_names]
for ins in result]
return render(request, 'nanosite/index.html', {'field_names': field_names, 'data': data})
My index.html
<div id="bottomhalf" class="table-responsive">
<table class="table table-sm table-dark table-hover">
<thead class="thead-light">
{% for head in field_names %}
<th scope="col">{{ head }}</th>
{% endfor %}
</thead>
<tbody>
{% for row in data %}
<tr scope="row">
{% for cell in row %}
<td>{{ cell }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
What I'd like to do is display only block_id, timestamp, account and amount in html. I've tried different approaches like using only the result part of views without field_names and data, but of course it didn't work.
My other question is, how can I modify the field amount and perform an operation on it to be displayed in template like amound divided by certain digit with a $ sign before it (for example if amount=1488 to be divided by 124 and displayed as '$12')?
Pass the queryset qs selecting the objects to display to the template and iterate over it to generate your table:
{% for obj in qs %}
<tr>
<td> {{obj.block_id}} </td>
<!-- etc ... -->
</tr>
{% endfor %}
Now, if you also want to pass a variable specifying the names of the fields of the object to tabulate, and in what order, you find out that the Django template engine is by design (!) incapable of doing that. You can either do what you are doing, and generate a list-of-rows in Python which you pass to the Template, or you need a Django custom template tag such as
#register.filter
def attr( obj, name):
return getattr( obj, name, '')
and then you can run an inner loop in your template
<tr>
{% for name in selected_field_names %}
<td> {{obj|attr:name}} </td>
{% endfor %}
</tr>
The answer to the second question, is to define a property on your model to return the field suitably transmogrified:
class Tabela(models.Model):
...
#property
def funny_amount(self):
val = self.amount/12.0
return f'$ {val:.2f}'
and refer to {{obj.funny_amount}} in your template
I've got a History ListView in which I'd like to let my Users filter the Historyitems based on which User they picked in the ModelChoiceFields I'm providing them
My History View looks like this:
class HistoryItems(ListView):
model = HistoryItem
template_name = 'history/history_table.html'
context_object_name = 'history_items'
def get_context_data(self, **kwargs):
user_id = kwargs.get('user_id')
query = {}
if user_id:
user = get_object_or_404(User, pk=user_id)
query['changed_by'] = user
else:
user = None
history_items = HistoryItem.objects.filter(**query).select_related('changed_by',
'content_type')
return {
'filter_history_form': HistoryFilterForm(user_id=user_id),
'history_items': history_items,
}
It returns me the correct History items in a big table (see html below). And then I've got this form:
class HistoryFilterForm(forms.Form):
normal_user = forms.ModelChoiceField(User.objects.filter(special=None), label="Normal Users", empty_label="All normal users")
special_user = forms.ModelChoiceField(User.objects.exclude(special=None), label="Special User", empty_label="All special users")
def __init__(self, *args, **kwargs):
user_id = kwargs.pop('user_id')
super(HistoryFilterForm, self).__init__(*args, **kwargs)
self.fields['normal_user'].initial = user_id
self.fields['special_user'].initial = user_id
self.helper = FormHelper()
self.helper.label_class = 'sr-only'
self.helper.add_layout(Layout(
Row(
Div('normal_user', css_class='col-sm-3'),
Div('special_user', css_class='col-sm-3'),
)
))
This form simply creates two ModelChoiceFields of the same User object, just that one field shows all "normal" users and the other all "special users"
My Urls looks lime this:
urls = [
path('', views.HistoryItems.as_view(), name='history_index'),
path('u=<int:pk>', views.HistoryItems.as_view(), name='history_index'),
]
I figured that I would need to refresh my page all the time when I'm searching for the history items of another user, which I'm doing with JavaScript (see HTML below). I'm also setting the id of the user in the url as an extra parameter.
And finally my HTML:
{% block extra_js %}
{{ block.super }}
<script type="application/javascript">
$(function(){
var historyUrlBase = '/history/';
var getParams = function(){
return {
'normalUserId': $('#id_normal_user').val(),
'specialUserId': $('#id_special_user').val()
}
};
var getNormalUrl = function(){
var params = getParams();
return historyUrlBase + 'u=' + params.normalUserId;
};
$('#id_normal_user').change(function(){
window.location.href = getNormalUrl();
});
var getSpecialUrl = function(){
var params = getParams();
return historyUrlBase + 'u=' + params.specialUserId;
};
$('#id_special_user').change(function(){
window.location.href = getSpecialUrl();
});
});
</script>
{% endblock %}
{% block main %}
{% crispy filter_history_form %}
<table class="table table-bordered table-responsive-sm">
<thead class="thead-light">
<tr>
<th>Changed at</th>
<th>Object</th>
<th>Action</th>
<th>Changed by</th>
<th>Difference</th>
</tr>
</thead>
<tbody>
{% for history_item in history_items %}
<tr>
<td>
{{ history_item.changed_at|date:"d.m.Y h:i:s" }}
</td>
<td>
{{ history_item.object }}
</td>
<td>
{% if history_item.action == 'custom' %}
{{ history_item.description }}
{% else %}
{{ history_item.get_action_display }}
{% endif %}
</td>
<td>
{{ history_item.changed_by }}
</td>
<td>
{{ history_item.difference|default:'' }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
My main problem right now is that in my View the kwargs I am receiving are always an empty dict with which ofc nothing works.
But I don't know how I can receive the ID from the users I'm picking, my form always shows the correct users in the two ModelChoiceFields, but how can I get the ID's from those users to use them in my view?
The users themselves only distinguish by the special field they have, but they share the same model.
I'm using Django 2.2 and Python 3.7 btw, so maybe if there is an even easier way someone knows, that would also be welcome!
I hope someone knows a good solution or can tell me what I'm doing wrong. Thanks in regard! :)
Short Answer
The kwargs dictionary in get_context_data contains any key word arguments defined in your urls.
urls = [
path('', views.HistoryItems.as_view(), name='history_index'),
path('u=<int:pk>', views.HistoryItems.as_view(), name='history_index'),
]
Your first url has no key word arguments defined. Your second url has one key word argument, pk (i.e. not user_id). So your code should actually be
user_id = kwargs.get('pk')
Long Answer
The way you've set up your form isn't typically how you would handle filtering of data. What you want to do is to submit your form using a GET request.
https://docs.djangoproject.com/en/dev/topics/forms/#get-and-post
Which will produce a url with query string parameters that looks something like
/history/?normal_user=1&special_user=1
You can then access these query string parameters in your view via the GET dictionary from the request object.
def get_context_data(self, **kwargs):
normal_user = self.request.GET.get('normal_user')
special_user = self.request.GET.get('special_user')
# filter your history with normal_user/special_user
And finally, delete your second url as this is no longer necessary.
I want to know a way on how to update the data once is edited from the input boxes all with one click. I found this post on how to do it with checkboxes:
Updating several records at once using Django
but I'm not sure how to do it for input boxes.
here is my code:
<table class="table table-striped table-bordered table-hover dataTables-example" >
<thead>
<tr>
<th>Local</th>
<th>line</th>
<th>rack</th>
</tr>
</thead>
<tbody>
{% for linea in lineas_de_reporte %}
<tr>
<td>{{ linea.local }}</td>
<td><input type="text" name="case-opened" value="{{ linea.rack }}" id="caseOpened"/></td>
<td><input type="text" name="case-opened" value="{{ linea.line }}" id="caseOpened"/></td>
</tr>
{% endfor %}
</tbody>
Here is how it looks:
Is there a way bu just sending all the values (by id) to a function in a list using Django?
EDIT:
forms.py
class TVSForm(forms.Form):
rack = forms.CharField()
line = forms.CharField()
views.py
def search_folio(request):
if request.method == 'POST':
form = FolioSearchForm(request.POST)
if form.is_valid():
folio_number = request.POST.get('folio_number', '')
folio = 'FOLIO' + str(folio_number)
folio_query = InventoryFolioManagement.objects.filter(folio=folio)
context = {
'lineas_de_reporte': folio_query,
'folio': ' | ' + folio
}
return render(request, 'inv-search-folio.html', context)
else:
form = FolioSearchForm()
if request.GET.get('rack'):
# ... this means that user clicked on the submit button
# get the id of linea
linea_id = request.GET.get('rack-id')
new_case = request.GET.get('rack')
# fetch object from db, based on that id (aka pk)
linea = TechnicalValidationSystem.objects.get(id=linea_id)
# change its attribute to True
linea.case_opened = new_case
# update db with the new value
linea.save(update_fields=['rack'])
return render(request, 'inv-search-folio.html')