Change value in views before rendering it at html page - python

I have a listview in my Django's project like:
class KaoiroView(ListView):
template_name = 'main/show-kaoiro.html'
queryset = Kaoiro.objects.all()
context_object_name = 'kaoiro'
paginate_by = 10
where Kaoiro has one column called
checkTime = models.BigIntegerField()
in models.py.
this checkTime is an unixtime like one big number.
I would like to convert this time when user get above page from my views.py, but because I'm using a listview I don't know how to access this data

you can create a new property in your model class such as :
this property is called derived property you can use any formula or code here to calculate new value.
class kaoiro(models.Model):
...
...
checkTime = models.BigIntegerField()
#property
def normal_time(self):
ct = self.checkTime
## do something with ct
return ct
you can use normal_time as any other property of your class.

Related

How to pass a variable to class based views (ListView)

My Views.py code
class ListaFuncionariosView(ListView):
model = Funcionarios
template_name = '../templates/funcionarios/lista_funcionarios.html'
paginate_by = 10
ordering = ['FuncionarioCartao']
queryset = Funcionarios.objects.filter(EmpresaCodigo=1)
funcionarios_number = Funcionarios.objects.aggregate(Count('FuncionarioCartao'))
My HTML
<h1>Good Morning</h1>
Exists: {{funcionarios_number}}
<br>
{{funcionarios}}
I would like to show the total number of registered employees in my db table (in the HTML file below), but I don't know how to put variables in class based views, in this case ListView. I'm using 4.0 Django
I tried put: funcionarios_number = Funcionarios.objects.aggregate(Count('FuncionarioCartao')) in bellow of my class, but this is not showed in my html.
By aggregating at the class-level, the query will run when you start the server, and the count will thus always remain that exact number.
You can define this in a function:
class ListaFuncionariosView(ListView):
model = Funcionarios
template_name = '../templates/funcionarios/lista_funcionarios.html'
paginate_by = 10
ordering = ['FuncionarioCartao']
queryset = Funcionarios.objects.filter(EmpresaCodigo=1)
def funcionarios_number(self):
return Funcionarios.objects.aggregate(total=Count('FuncionarioCartao'))[
'total'
]
and then access the function in the view in the template:
{{ view.functionarios_number }}

How to serialize an array of objects in Django

I am working with Django and REST Framework and I am trying to create a get function for one of my Views and running into an error. The basic idea is that I am creating a market which can have multiple shops. For each shop there can be many products. So, I am trying to query all those products which exist in one shop. Once I get all those products I want to send it to my serializer which will finally return it as a JSON object. I have been able to make it work for one product but it does not work for an array of products.
My Product model looks like this:
'''Product model to store the details of all the products'''
class Product(models.Model):
# Define the fields of the product model
name = models.CharField(max_length=100)
price = models.IntegerField(default=0)
quantity = models.IntegerField(default=0)
description = models.CharField(max_length=200, default='', null=True, blank=True)
image = models.ImageField(upload_to='uploads/images/products')
category = models.ForeignKey(Category, on_delete=models.CASCADE, default=1) # Foriegn key with Category Model
store = models.ForeignKey(Store, on_delete=models.CASCADE, default=1)
''' Filter functions for the product model '''
# Create a static method to retrieve all products from the database
#staticmethod
def get_all_products():
# Return all products
return Product.objects.all()
# Filter the data by store ID:
#staticmethod
def get_all_products_by_store(store_id):
# Check if store ID was passed
if store_id:
return Product.objects.filter(store=store_id)
The product serializer that I built is as follows:-
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
and the view that I created is below
class StoreView(generics.ListAPIView):
"""Store view which returns the store data as a Json file.
"""
# Define class variables
serializer_class = StoreSerializer
# Manage a get request
def get(self, request):
# Get storeid for filtering from the page
store_id = request.GET.get('id')
if store_id:
queryset = Product.get_all_products_by_store(store_id)
# queryset = Product.get_all_products_by_store(store_id)[0]
else:
queryset = Product.get_all_products()
# queryset = Product.get_all_products()[0]
print("QUERYSET", queryset)
return Response(ProductSerializer(queryset).data)
The above view gives me the following error
AttributeError at /market
Got AttributeError when attempting to get a value for field `name` on serializer `ProductSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `QuerySet` instance.
Original exception text was: 'QuerySet' object has no attribute 'name'.
If instead queryset = Product.get_all_products_by_store(store_id), I use the line below it where I am only selecting the first option then I get the correct JSON response but if there multiple products then I am not able to serialize. How do I make it work?
If you want to serialize more than one record, either use ListSerializer instead, or pass many=True the the constructor of ModelSerializer:
return Response(ProductSerializer(queryset, many=True).data)
I found the answer thanks to #yedpodtrzitko for giving the direction.
I had to make two changes.
Define queryset outside the function
Pass many=True the the constructor of ModelSerializer
class StoreView(generics.ListAPIView):
"""Store view which returns the store data as a Json file.
"""
# Define class variables
queryset = []
serializer_class = StoreSerializer
# Manage a get request
def get(self, request):
# Get storeid for filtering from the page
store_id = request.GET.get('id')
if store_id:
queryset = Product.get_all_products_by_store(store_id)
else:
queryset = Product.get_all_products()
print("QUERYSET", queryset)
return Response(ProductSerializer(queryset, many = True).data)

How to display instances from two different django models on the same template, inside the same table?

In a django app I've created different models and everything looks okay until I try using data from two different models inside the same table.
To sum it up: in the homepage, I need to create a table that contains data from both the models, ordered by date.
The two models I need to display are the following.
models.py
class Document(models.Model):
number = models.CharField(max_length=10)
description = models.CharField(max_length=50)
assigned = models.BooleanField
validity_date = models.DateField
is_issued = models.BooleanField
class Program(models.Model):
name = models.CharField(max_length=25)
description = models.CharField(max_length=100)
validity_date = models.DateField
Then, I tried to create a view that would allow me to work with different models.
This is my view.py:
class BaseView(generic.ListView):
template_name = 'base/base_list.html'
context_object_name = 'base_list'
def get_queryset(self):
queryset = Document.objects.order_by('due_date')
return queryset
def get_context_data(self, **kwargs):
context = super(BaseView, self).get_context_data(**kwargs)
context['Programs'] = Program.objects.all()
context['Employees'] = Employee.objects.all()
return context
Now how can I create inside the template a table that shows both the models at once, ordering each entry by validity date (no matter if the entry belongs to Program or to Document)?
Thank you in advance!
You need to first query both the models, chain them together (Concatenate them) and then order by their shared attribute, that is the validity_date. You may do something like:
from itertools import chain
documents = Documents.objects.all()
programs = Program.objects.all()
final_combined_list = sorted(chain(documents,programs),key=lambda instance: instance.validity_date)
You can now simply pass final_combine_list to the template and render it to display it in the manner you want.
def get_context_data(self, **kwargs):
context = super(BaseView, self).get_context_data(**kwargs)
context['object_list'] = sorted(
itertools.chain(Document.objects.all(), Program.objects.all()),
key=lambda x: x.validity_date
)
return context

How to take form string value from CharField and convert into object instance in Django?

I keep running into this error:
Cannot assign "u'Foo Group'": "Team.membership_group" must be a "Group" instance.
In my Django application, I give the user an option to create a Team. The team has a memebership_group ForeignKey attribute which maps to 'Group' (django.contrib.auth.models.Group). In the form, I've changed the widget to be a CharField so that if a group that the user types isn't actually a group, my code should create it. Here is my form:
class TeamForm(ModelForm):
"""Form to create and modify systems"""
membership_group = CharField()
manager = ModelChoiceField(queryset=Manager.objects.all(), required=True)
class Meta:
model = Team
fields = ['name', 'manager', 'membership_group']
In my views (or possibly I need to write the code elsewhere?), I want to take the string value and run a get_or_create to either return the existing group or create a new one. Here is the code in my views that isn't working:
class TeamCreateView(AutoEventLogMixin, SuccessMessageMixin, PermissionRequiredMixin, CreateView):
"""View to create Teams"""
form_class = TeamForm
model = Team
permission_required = 'teams.add_team'
success_message = "Team '%(name)s' created successfully."
template_name = 'teams/team_form.html'
def form_valid(self, form):
team_created = super(TeamCreateView, self).form_valid(form)
team = self.object
group_name = form.instance.membership_group
group_name.encode('utf-8')
membership_group = Group.objects.get_or_create(name=group_name)[0]
team.membership_group = membership_group
team.save()
return team_created
What am I doing wrong? What code do I need to add (and where) to be able to serialize/deserialize the membership group value from string to group and vice versa
I think in anyway it is not a good idea to do type translation in form_valid. If you use django1.9, then consider to create a customized FormField:
from django import forms
class MyGroupField(forms.Field):
def to_python(self, group_name):
return Group.objects.get_or_create(name=group_name)[0]
class TeamForm(ModelForm):
membership_group = MyGroupField()

Django Serializer Method Field

Can't seem to find the right google search for this so here it goes:
I have a field in my serializer:
likescount = serializers.IntegerField(source='post.count', read_only=True)
which counts all the related field "post".
Now I want to use that field as part of my method:
def popularity(self, obj):
like = self.likescount
time = datetime.datetime.now()
return like/time
Is this possible?
assuming post.count is being used to measure the number of likes on a post and you don't actually intend to divide an integer by a timestamp in your popularity method, then try this:
use a SerializerMethodField
likescount = serializers.SerializerMethodField('get_popularity')
def popularity(self, obj):
likes = obj.post.count
time = #hours since created
return likes / time if time > 0 else likes
however I would recommend making this a property in your model
in your model:
#property
def popularity(self):
likes = self.post.count
time = #hours since created
return likes / time if time > 0 else likes
then use a generic Field to reference it in your serializer:
class ListingSerializer(serializers.ModelSerializer):
...
popularity = serializers.Field(source='popularity')

Categories