views.py
def new_report(request):
user = request.user
reports = Report.objects.filter(user=user)
today = datetime.datetime.today()
reports_today = reports.filter(created_date_time__year=today.year, created_date_time__month=today.month, created_date_time__day=today.day)
num_today = len(reports_today) + 1
num_today = str(num_today).zfill(3)
reportform = ReportForm()
if request.method == 'POST':
reportform = ReportForm(request.POST)
if reportform.is_valid():
report = reportform.save(commit=False)
report.user = user
report.created_date_time = today
return render(request, 'incident/new_report.html',
{
'newreport_menu': True,
'reports': reports,
'reportform':ReportForm,
})
models.py
class Report(models.Model):
user = models.ForeignKey(User, null=False)
incident_number = models.CharField('Incident Number', max_length=100)
device_id = models.CharField('Device Id', max_length=100)
app_uuid = models.CharField('Unique App Id', max_length=100)
created_date_time = models.DateTimeField('Created',auto_now=True)
template is
{{ reports.created_date_time|date:"j M Y g:i A" }}
Fetching the created_date_time from database and convert to this format 20 Jan2011 at 2:26PM to display in template.
To query the created_date_time from database and display into template.I am not getting any error in the code,i think some logic having problem so that it is not happening.
reports variable is accessed in template as it is a single Report object, but it is a list of Report object.
To access to the first item in list in template, use following syntax:
{{ reports.0.created_date_time|date:"j M Y g:i A" }}
Now, the easiest way to print date in format you've mentioned is:
{{ reports.0.created_date_time|date:"j M Y" }} at {{ reports.0.created_date_time|date:"g:i A" }}
But, to my mind, the better way is to create custom template filter, that will print the desired format.
your_app/templatetags/format_dates.py
from django.utils.dateformat import format
from django.template.base import Library
register = Library()
#register.filter(expects_localtime=True, is_safe=False)
def format_date(value):
if not value:
return u''
try:
return u"%s at %s" % (format(value, 'j M Y'), format(value, 'g:i A'))
except AttributeError:
return u''
and then in template:
{% load format_dates %}
...
{{ reports.0.created_date_time|format_date }}
Related
I've implemented a table search product with Ajax and it works well.
But now, I want to build dynamically my table taking in account the number of my warehouses can be increase.
search.js
data.forEach((item) => {
const newName = (item.nom).slice(0, 30) + "...";
tableBody.innerHTML += `
<tr>
<th>${item.sku}</th>
<td>${item.etat__etat}</td>
<td class="small">${newName}</td>
<td>${item.famille__nom}</td>
<td>${item.mageid}</td>
<td>${item.adresse}</td>
models.py (model for witch I need a set)
class SstStock(models.Model):
warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
product = models.ManyToManyField(Produit)
qty = models.IntegerField()
last_update = models.DateTimeField(default=timezone.now)
views.py
def search_product2(request):
if request.method == 'POST':
search_str = json.loads(request.body).get('searchText')
products = Produit.objects.filter(sku__icontains=search_str) | Produit.objects.filter(
nom__icontains=search_str) | Produit.objects.filter(mageid__icontains=search_str)
data = products.values(
'id',
'sku',
'nom',
[...]
'sststock',
[...]
'cau_cli',
'maxsst2',
)
return JsonResponse(list(data), safe=False)
Directly in template I could do :
template
{% for produit in produits %}
{{ produit.sku}}<br>
{% for sst in produit.sststock_set.all %}
<span>{{sst.warehouse.code}} - {{ sst.qty }}</span><br>
{% endfor %}
<br>
{% endfor %}
But I couldn't find the way to pass the the sststock_set.all() in the JsonResponse. I got well a "sststock" value in it but it contains only the last value of the set instead of an array/dict of the whole set.
console.log()
qty: 7
sku: "ACP863"
sststock: 68095
68095 is the last ID of my set.
Worse, when I try to get item.sststock in the ForEach product, in my JS, it returns Undefined.
Any idea please ?
Found the way to apply #WillemVanOnsem advice with serializer.
Before all, my first error war to apply ManyToMany instead of ForeignKey on:
product = models.ManyToManyField(Produit)
After, I have set a serializer that retrieves the different stocks (warehouse_id + qty) and adds it to the Product model (with "source" parameter):
serializers.py
from rest_framework import serializers
from .models import Produit, SstStock
class StockSearchSerializer(serializers.ModelSerializer):
class Meta:
model = SstStock
fields = '__all__'
fields = ['warehouse_id', 'qty']
class ProductSearchSerializer(serializers.ModelSerializer):
sststock = StockSearchSerializer(source='sststock_set', many=True)
class Meta:
model = Produit
fields = '__all__'
To finish, I use the serializer with "many=True" in the view and return its result that will be handled by JS on my search page:
views.py
def search_product(request):
if request.method == 'POST':
search_str = json.loads(request.body).get('searchText')
products = Produit.objects.prefetch_related(
Prefetch('sststock_set',
SstStock.objects.select_related('warehouse'))
).filter(sku__icontains=search_str) | Produit.objects.filter(
nom__icontains=search_str) |
Produit.objects.filter(mageid__icontains=search_str)
serializer = ProductSearchSerializer(products, many=True)
data = serializer.data
return JsonResponse(list(data), safe=False)
And as wished, stocks array is added in the json response
I am trying to show the field(s) related to its foreignkey on html. Let's see I have two models as shown below:
models.py
from django.db import models
class Model_Item(models.Model):
item_name = models.CharField(max_length = 100, null = False, blank = False, unique = True)
item_unit = models.CharField(max_length = 20, null = False, blank = False) # can be kilogram, pound, ounce, etc
def __unicode__(self):
return self.item_name
class Model_Weight(models.Model):
item = models.ForeignKey(Model_Item, to_field = "item_name")
item_weight = models.FloatField(null = True, blank = True)
def __unicode__(self):
return self.item
On Model_Item model, each item can have its own unit, and there can be many items. Then we will choose the item on the second model (Model_Weight), and insert the value of the weight that is according to its unit.
How can we show the corresponding "item_unit" in html, such that when we have selected the "item_name", its unit will show/hover somewhere in the webpage which enables us to put the correct weight value?
These are the rest of the codes:
forms.py
from django import forms
from .models import Model_Weight
class Form_Weight(forms.ModelForm):
class Meta:
model = Model_Weight
fields = ["item", "item_weight"]
views.py
from .models import Model_Weight
from .forms import Form_Weight
from django.views.generic import CreateView
class View_Weight_CV(CreateView):
form_class = Form_Weight
def form_valid(self, form):
instance = form.save(commit = False)
instance.user = self.request.user
return super(View_Weight_CV, self).form_valid(form)
html
<form method = "POST" action = "" enctype = "multipart/form-data"> {% csrf_token %}
{{ form.item}}
<!-- {{ form.model_item.item_unit }} Automatically shows this field once an item has been selected -->
{{ form.item_weight}}
<input type = "submit" value = "Submit">
</form>
The quick solution is to change __unicode__ method definition of Model_Item model
def __unicode__(self):
# add item_unit with name
return self.item_name + " (" + self. item_unit + ")"
Now in your HTML template, the item dropdown will be shown like
{{ form.item }} #--> Bread (Kg)
#--> Rice (Kg)
#--> ...
If you want to show unit under item dropdown, keep above settings as it is and add below javascript code at bottom of your HTML template
$(document).on('change', '#id_item', function(){
// you can also make ajax request from here
// I am using selected item text for now
var item = $(this).find("option:selected").text();
// item = 'Bread (Kg)'
var result = item.match(/\((.*)\)/);
// matched text inside round brackets
// result[1] = Kg
$( "#id_item" ).after( "<p>"+result[1]+"</p>" );
});
There are already a lot of questions+answers regarding for loops in django, but none of the solutions work for me, so there must be something fundamentally wrong.
I have a dictionary in python/json (tried both) that I want to loop through and print.
Doing the following print a new line for each character
{% for item in data.dict %}
<p>{{item}}</p>
{% endfor %}
so something like this get's printed
{
'
N
o
d
e
'
:
The following code straight up prints nothing
{% for key, values in data.dict.items %}
<p>{{key}}</p>
{% endfor %}
Data is the name of my registered model and object is one of its variables.
In my Views.py I have something similar to this:
Data.objects.create(
dict=theDictIAmPassing
}.save
EDIT
models.py
from django.db import models
class Data(models.Model):
dict1= models.TextField()
dict2 = models.TextField()
dict3 = models.TextField()
dict4 = models.TextField()
views.py
def add(request):
if request.method == 'POST':
form = EntryForm(request.POST)
if form.is_valid():
ProjectName = form.cleaned_data['ProjectName']
date = form.cleaned_data['date']
folder = form.cleaned_data['folder']
description = form.cleaned_data['description']
myprog = program.program(folder)
createMetrics(myprog)
Entry.objects.create(
ProjectName=ProjectName,
date=date,
folder=folder,
description=description
).save()
return HttpResponseRedirect('/')
else:
form = EntryForm()
return render(request, 'myApp/form.html', {'form': form})
def createMetrics(myprog):
Metrics.objects.create(
dict1=myprog.getDict1(),
dict2=myprog.getDict2(),
dict3=myprog.getDict3(),
dict4=myprog.getDict4()
).save()
Solution found at https://stackoverflow.com/a/7469287/7761401
I needed to rewrite my Data model. Textfield (which I used because I couldn't find anything else that fits) does not suit dictionary types. Instead install django-picklefield and change type to PickledObjectField
from picklefield.fields import PickledObjectField
class Data(models.Model):
dict1 = PickledObjectField()
dict2 = PickledObjectField()
dict3 = PickledObjectField()
dict4 = PickledObjectField()
In my exercise I have a Django model of a book, having a field "genre". This field has the following option choices
GENRES_CHOICE = (
('ADV','Adventure'),
('FAN','Fantasy'),
('POE','Poetry'),
)
and the model field is
genre = models.CharField(max_length = 3, blank = False, choices = GENRES_CHOICE, db_index = True, editable = False)
In my template I would like to show to the user the list of the genres (Adventure, Fantasy, Poetry) and hava available the keys, in order to possibly use them as parameters.
In order to do so, I would like to have a function that returns the data structure GENRES_CHOICE, but I am not able to. How to solve this problem?
EDIT:
more code details
appname= mybookshelf, file -> models/Book.py
# possible choices for the gerne field
GENRES_CHOICE = (
('ADV','Adventure'),
('FAN','Fantasy'),
('POE','Poetry'),
)
class Book(models.Model):
"""
This is the book model
...
## ATTRIBUTES (better use init, but in Django not always possible)
id = models.CharField(max_length = 64, blank = False, unique = True, primary_key = True, editable = False)
""" unique id for the element """
genre = models.CharField(max_length = 3, blank = False, choices = GENRES_CHOICE, db_index = True, editable = False)
""" book genre """
published_date = models.DateField(null = True, auto_now_add = True, editable = False)
""" date of publishing """
Then, into another file, lets say MyFunctions.py I have
from mybookshelf.models import GENRES_CHOICE
def getBookCategories():
"""
This function returns the possible book categories
categories = GENRES_CHOICE
return categories
views.py
from app_name.models import GENRES_CHOICE
def view_name(request):
...............
return render(request, 'page.html', {
'genres': GENRES_CHOICE
})
page.html
{% for genre in genres %}
{{genre.1}}<br/>
{% endfor %}
I am not 100% sure this is what you are after, but if you want to show the user the list of GENRES_CHOICE you can do this in your templete:
{% for choice_id, choice_label in genres %}
<p> {{ choice_id }} - {{ choice_label }} </p>
{% endfor %}
ofcourse pass GENRES_CHOICE as genres
You could use the get_modelfield_display() method in your template, e.g.:
{{ book.get_genre_display }}
Given the following models:
class Graph(models.Model):
owner = models.ForeignKey(User)
def __unicode__(self):
return u'%d' % self.id
class Point(models.Model):
graph = models.ForeignKey(Graph)
date = models.DateField(primary_key = True)
abs = models.FloatField(null = True)
avg = models.FloatField(null = True)
def __unicode__(self):
return u'%s' % self.date
I am trying to create a form for editing lists of Points.
The HTML input tags require additional attributes to be set, so I am using the following custom form:
class PointForm(forms.ModelForm):
graph = forms.ModelChoiceField(queryset = Graph.objects.all(),
widget = forms.HiddenInput())
date = forms.DateField(widget = forms.HiddenInput(), label = 'date')
abs = forms.FloatField(widget = forms.TextInput(
attrs = {'class': 'abs-field'}),
required = False)
class Meta:
model = Point
fields = ('graph', 'date', 'abs') # Other fields are not edited.
def pretty_date(self):
return self.data.strftime('%B')
At this point I do not know how to pass instances of the Point class to a FormSet:
def edit(request):
PointFormSet = forms.formsets.formset_factory(PointForm, extra = 0)
if request.method == 'POST':
return
# Receive 3 points to edit from the database.
graph, res = Graph.objects.get_or_create(id = 1)
one_day = datetime.timedelta(days = 1)
today = datetime.date.today()
do_edit = []
for date in [today - (x * one_day) for x in range(3)]:
point, res = Point.objects.get_or_create(graph = graph, date = date)
do_edit.append(point)
formset = PointFormSet(????) # How is this initialized with the points?
I found a hack that somewhat works, but it leads to errors later on when trying to process the resulting POST data:
do_edit = []
for date in [today - (x * one_day) for x in range(3)]:
point, res = Point.objects.get_or_create(graph = graph, date = date)
data = point.__dict__.copy()
data['graph'] = graph
do_edit.append(data)
formset = PointFormSet(initial = do_edit)
How is this done correctly?
For the reference, my template looks like this:
<form action="" method="post">
{{ formset.management_form }}
<table>
<tbody>
{% for form in formset.forms %}
<tr>
<td>{{ form.graph }} {{ form.date }} {{ form.pretty_date }}:</td>
<td width="100%">{{ form.abs }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
The trick is to use a "ModelFormset" instead of just a formset since they allow initialization with a queryset. The docs are here, what you do is provide a form=* when creating the model formset and queryset=* when your instantiating the formset. The form=* arguement is not well documented (had to dig around in the code a little to make sure it is actually there).
def edit(request):
PointFormSet = modelformset_factory(Point, form = PointForm)
qset = Point.objects.all() #or however your getting your Points to modify
formset = PointFormset(queryset = qset)
if request.method == 'POST':
#deal with posting the data
formset = PointFormset(request.POST)
if formset.is_valid():
#if it is not valid then the "errors" will fall through and be returned
formset.save()
return #to your redirect
context_dict = {'formset':formset,
#other context info
}
return render_to_response('your_template.html', context_dict)
So the code walks through easily. If the request is a GET then the instantiated form is returned to the user. If the request is a POST and the form is not .is_valid() then the errors "fall through" and are returned in the same template. If the request is a POST and the data is valid then the formset is saved.
Hope that helps.
-Will
If you only have one possible value which you want to set, or perhaps a closed of values, it is possible to set them after the user POSTS the data to your server using commit=False
Please consider the following code:
class UserReferralView(View):
ReferralFormSet = modelformset_factory(ReferralCode,
form=ReferralTokenForm, extra=1)
def get(self, request):
pass
def post(self, request):
referral_formset = UserUpdateView.ReferralFormSet(request.POST)
if referral_formset.is_valid():
instances = referral_formset.save(commit=False)
for instance in instances:
instance.user = request.user
instance.save()
return redirect(reverse('referrals.success_view'))
else:
return redirect(reverse('referrals.failure_view'))