Django 2 tables in model cycle "for" in template - django

I try to make a simple illustration of my question click to view
I have a task to make a quiz.
I try to solve a problem :
Taking items in cycle by "Metrix" model there I get Questions for Quiz
It is no way to get data from "User_metrix" model while using {% for item in metrix_list %} cycle by "Metrix" model.
My models:
from django.db import models
from django.conf import settings
class Metrix(models.Model):
title = models.CharField(max_length=256, verbose_name='Question')
metrix_category = models.ForeignKey(
'category',
related_name='Question_category',
on_delete=models.CASCADE,
verbose_name='Category',
)
is_published = models.BooleanField(default=False)
def __str__(self):
return self.title
class Category(models.Model):
title = models.CharField(max_length=256,
verbose_name='Question_category')
is_published = models.BooleanField(default=False)
def __str__(self):
return self.title
class User_metrix(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="user_metrix",
verbose_name='User')
metrix = models.ForeignKey('Metrix', on_delete=models.CASCADE,
verbose_name='Question')
value = models.DecimalField(max_digits=12, decimal_places=2,
verbose_name='Value')
My view:
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from metrix.models import Metrix, User_metrix
#login_required
def metrix_view(request, pk=None):
metrix_category = {
'pk': 4
}
#Get questions by category
metrix_list = Metrix.objects.filter(is_published=True,
metrix_category__pk=pk)
context = {
'metrix_list': metrix_list
}
return render(request, 'metrix/metrix.html', context)
Template:
I list the questions in template, by cycle "metrix_list"
How to save answers to values and if answers exists return values to template?
<!--cycle for metrix-->
{% for item in metrix_list %}
<div class="row metrix_quiestion_line justify-content-center">
<div class="metrix_quiestion">
<h2>
{{ item }}
</h2>
</div>
<div class="metrix_value">
<input type="number" name="{{ item.id }}" value=" ">
</div>
</div>
{% endfor %}
<!--END cycle -->

Related

generic createview and django form only rendering a button in a template

I have encountered a funny challenge, as am building some apps where they want track some expenses and revenues profits ...
I used generic views to create and get details and delete, all work fine with expenses, but I copied the same code and I used it for revenues from expenses you can't imagine this view is rendering a button only yet it has a form, NOTE SAME CODE WORK WELL ON EXPENSES. I even exchanged templates but it kept rendering the former content even after changing the template. it doesn't matter what's in the template the view just renders the same thing even when I remove the form, even when I put pass.
class AccountsRevenueCreate(CreateView):
template_name='dashboard/expense_create.html'
model= AccountsExpense
success_url = reverse_lazy('dashboard:expenses')
form_class=AccountsExpenseForm
and the form
class AccountsRevenueForm(forms.ModelForm):
class Meta:
model = AccountsRevenue
fields = '__all__'
and in the template
<div class="row">
<div class="col-12">
<h5 class="form-title"><span>revenue Update
</span></h5>
</div>
<form method="post", action="{% url
'dashboard:revenue_add' %}">
{% csrf_token %}
{% comment %} {{ form|crispy }} {% endcomment %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary col-12 col-sm-12">Save
</button>
</form>
</div>
and the URLs
path ('accounts/revenues/create/', AccountsRevenueCreate.as_view(), name='revenue_create'),
I have chosen to show you only where the problem is not paste unnecessary code
here are the models you requested me to update
from django.db import models
class AccountsRevenue(models.Model):
revenue_of = models.CharField(max_length=250, default='',null=False)
revenue_by = models.CharField(max_length=250, default='',null=False)
amount = models.IntegerField( default='100,000')
day_on_which = models.DateField(null=True, blank=True)
evidence_document = models.ImageField(upload_to = 'uploads/', blank=True, default='')
signature = models.ImageField(upload_to = 'uploads/', blank=True, default='')
def __str__(self):
return str(self.revenue_of)
def get_absolute_url(self):
return reverse('dashboard:revenue', kwargs= {'pk':self.pk} )
def get_document(self):
if self.evidence_document and hasattr(self.evidence_document, 'url'):
return self.evidence_document.url
else:
return "/static/assets/img/user.png"
class AccountsExpense(models.Model):
expense_of= models.CharField(max_length=250, default='',null=False)
expense_by = models.CharField(max_length=250, default='',null=False)
amount = models.IntegerField( default='100,000')
day_on_which = models.DateField(null=True, blank=True)
evidence_document = models.ImageField(upload_to = 'uploads/',
blank=True, default='')
signature = models.ImageField(upload_to = 'uploads/', blank=True,
default='')
def __str__(self):
return str(self.expense_of)
def get_absolute_url(self):
return reverse('dashboard:expense', kwargs= {'pk':self.pk} )
def get_document(self):
if self.evidence_document and hasattr(self.evidence_document,
'url'):
return self.evidence_document.url
else:
return "/static/assets/img/user.png"
from django.urls import URLPattern, path
from django.conf.urls.static import static
from. views import profiles, Profile_detail, Profile_update,
Profile_delete, dashboard, Profile_create,\
AccountsRevenues, revenue_detail_view, AccountsRevenueUpdate,
AccountsRevenue_delete, \
AccountsExpenses, AccountsExpenseDetail, AccountsExpenseCreate,
AccountsExpenseUpdate, AccountsExpenseDelete,\
userprofileupdate, revenue_add, AccountsRevenueCreate
app_name = "dashboard"
urlpatterns = [
path ('accounts/revenues', AccountsRevenues.as_view(), name='revenues'),
path ('accounts/revenues/<str:pk>/', revenue_detail_view,
name='revenue'),
path ('accounts/revenues/<str:pk>/update/',
AccountsRevenueUpdate.as_view(), name='revenue_update'),
path ('accounts/revenues/<str:pk>/delete/',
AccountsRevenue_delete.as_view(), name='revenue_delete'),
path ('accounts/revenues/create/', AccountsRevenueCreate.as_view(),
name='revenue_create'),
# accounts expenses
path ('accounts/expenses', AccountsExpenses.as_view(), name='expenses'),
path ('accounts/expenses/<str:pk>', AccountsExpenseDetail.as_view(),
name='expense'),
path ('accounts/expenses/<str:pk>/update/',
AccountsExpenseUpdate.as_view(), name='expense_update'),
path ('accounts/expenses/<str:pk>/delete/',
AccountsExpenseDelete.as_view(), name='expense_delete'),
path ('accounts/expenses/create/', AccountsExpenseCreate.as_view(),
name='expense_create'),
]
I have added a screenshot of what it comes out as enter image description here
left model.py, forms.py, urls.py as it was.
views.py
in the line: template_name = 'bboard/expense_create.html' replace bboard with the name of the folder where the templates are located. I have it templates/bboard. Also in your field: form_class=AccountsExpenseForm changed to form_class = AccountsRevenueForm.
And the return goes to the same page with the form: success_url = reverse_lazy('revenue_create').
success_url can then be returned to what it was, now you need to make sure that everything works.
views.py
class AccountsRevenueCreate(CreateView):
template_name = 'bboard/expense_create.html'
model = AccountsExpense
success_url = reverse_lazy('revenue_create')
form_class = AccountsRevenueForm
expense_create.html
in the template you have an error form method="post", there should not be a comma.
<div class="row">
<div class="col-12">
<h5 class="form-title"><span>revenue Update
</span></h5>
</div>
<form method="post" action="{% url 'revenue_create' %}">
{% csrf_token %}
{% comment %} {{ form|crispy }} {% endcomment %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary col-12 col-sm-12">Save
</button>
</form>
</div>
Followed the link: http://localhost:8000/accounts/revenues/create/
Screenshot attached:

Django Model form not saving data to the database model on form submission

I have created a project and added models in the models and also created a form in forms.py. I am trying to modify some values using the commit=False. On submitting the form, it's not saving the data to the database and there is no error thrown from the code. I have no idea on how I can solve the issue.
models.py
from django.db import models
from django.contrib.auth.models import User
class Agent(models.Model):
name = models.CharField(max_length=255)
id_no = models.CharField(max_length=20)
address = models.CharField(max_length=255)
gender = models.CharField(max_length=8)
age = models.IntegerField()
agent_no = models.CharField(unique=True, max_length=12, null=True)
email = models.EmailField(max_length=50)
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.name}"
class Company(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
name = models.CharField(max_length=255, null=True, blank=True)
address = models.CharField(max_length=255, null=True, blank=True)
telephone = models.IntegerField( null=True, blank=True)
email = models.EmailField(max_length=50, null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.name}"
class Task(models.Model):
company = models.ForeignKey(Company, null=True, on_delete=models.SET_NULL)
agent = models.ForeignKey(Agent, null=True, on_delete=models.SET_NULL)
cargo = models.CharField(max_length=200)
document = models.FileField(upload_to='documents/')
quantity = models.FloatField()
amount = models.FloatField()
duty = models.FloatField(null=True, blank=True)
status = models.CharField(max_length=50, default='Pending')
date_created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.cargo}"
forms.py
from django.contrib.auth.models import User
from django import forms
import re
from django.core.exceptions import ValidationError
from .models import *
class TaskForm(forms.ModelForm):
cargo = forms.CharField( required=False)
document = forms.FileField()
quantity = forms.FloatField()
amount = forms.FloatField()
class Meta:
model = Task
fields = ['cargo', 'document', 'quantity', 'amount']
views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from .forms import *
from django.contrib.auth.models import Group
from django.contrib.auth import login, authenticate
#login_required(login_url='/login/')
def task(request):
if request.method == "POST":
form=TaskForm(request.POST)
if form.is_valid():
m = form.save(commit=False)
m.status ='Pending'
m.company = request.user.username
m.save()
else:
form= TaskForm(None)
context = {'form':form}
return render(request, 'registration/templates/task.html', context)
template.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
<div class="container my-2 d-flex" style="align-items:center; justify-content:center;">
<div class="card d-flex" style="width:70%; align-items:center; justify-content:center;">
<div class="form-control pt-3 " style="text-transform:uppercase;color:green"><h5>Upload trip information
</h5>
</div>
<div class="card-body" style="width:98%">
{{ form|crispy}}
</div>
<div class="card-footer" style="width:98%">
<input type="submit" value="Upload Information" class="btn btn-outline-secondary btn-sm">
</div>
</div>
</div>
</form>
{% endblock %}
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.urls import reverse
from django.http import HttpResponseRedirect
from .forms import *
from django.contrib.auth.models import Group
from django.contrib.auth import login, authenticate
#login_required(login_url='/login/')
def task(request):
if request.method == "POST":
form=TaskForm(request.POST,request.FILES) # this is important if you are dealing with files
if form.is_valid():
m = form.save(commit=False)
m.status ='Pending'
m.company = request.user.username
m.save()
return HttpResponseRedirect(reverse(' the url of where you want to redirect the user '))
else:
form= TaskForm()
context = {'form':form}
return render(request, 'registration/templates/task.html', context)
and in your templates try to add enctype in your form.
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="container my-2 d-flex" style="align-items:center; justify-content:center;">
<div class="card d-flex" style="width:70%; align-items:center; justify-content:center;">
<div class="form-control pt-3 " style="text-transform:uppercase;color:green"><h5>Upload trip information
</h5>
</div>
<div class="card-body" style="width:98%">
{{ form|crispy }}
</div>
<div class="card-footer" style="width:98%">
<input type="submit" value="Upload Information" class="btn btn-outline-secondary btn-sm">
</div>
</div>
</div>
</form>
{% endblock %}

Django complex QuerySet ManyToManyField with other ManyToManyField

Sorry for this title, I wasn't sure how to name it properly. I'm having problem with getting queryset of ManyToManyField that is in relation with other ManyToManyField. So it's look like this, there is model Company that has ManyToManyField with Person and Person model got ManyToManyField with Position, because logic behind it is that 1 company can have many persons and 1 person can have few positions and can be employed by few companies (which is clear I think). I'm getting the queryset for Person in Company by this way
{% for team in brand.team.all %}
<p>{{ team.first_name }} {{ team.last_name }}</p>
<img class="img-thumbnail" src="/media/{{ team.photo }}">
<p>{{ team.position }} </p>
<p>{{ team.about }} </p>
{% endfor %}
And I'm getting what I want, comparing this to template looks like this
but I'm not getting positions of person, only company.Position.None and I've no idea how to get this. From documentation so far I know that it works for single ManyToManyField but I couldn't find example similar to mine case and I'm not sure how I should get (person's position)
Below are my files
models.py
from django.db import models
...
TYPES = (
('Startup', 'Startup'),
... )
CITIES = (
('Warszawa', 'Warszawa'),
... )
STACK = (
('PHP', 'PHP'),
... )
STUDENTS = (
('No', 'No'),
('Yes', 'Yes')
)
STACK_ICONS = (
('/static/icons/stack/php.png', 'PHP'),
('/static/icons/stack/javascript.png', 'JavaScript'),
...
)
POSITIONS = (
('CEO', 'Chief Executive Officer'),
('CTO', 'Chief Technology Officer'),
...
)
# object position with relationship many to many to person
class Position(models.Model):
position = models.CharField(max_length=50, choices=POSITIONS)
def __str__(self):
return self.position
# object person relation many to one (many persons to one company)
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
about = models.TextField(max_length=500, default=None)
position = models.ManyToManyField('Position')
photo = models.ImageField(blank=True, null=True, default=None)
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
# object company
class Company(models.Model):
# field person with relation many to one (many persons to 1 company)
team = models.ManyToManyField('Person')
name = models.CharField(max_length=100, blank=False)
technologies = models.ManyToManyField('Stack')
website = models.TextField(max_length=150, blank=True, null=True, validators=[URLValidator()])
...
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Company, self).save(*args, **kwargs)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.name
# object stack relation manytomany with Company
class Stack(models.Model):
name = models.CharField(max_length=30, choices=STACK)
icon = models.CharField(max_length=80, choices=STACK_ICONS)
def __str__(self):
return self.name
views.py
from django.shortcuts import render, get_object_or_404, redirect
...
def brands(request, slug):
brand = get_object_or_404(Company, slug=slug)
return render(request, 'company/comp_view.html', {'brand': brand})
def stacks(request):
stack = get_object_or_404(Stack)
return render(request, 'company/comp_view.html', {'stack': stack})
def positions(request):
position = get_object_or_404(Position)
return render(request, 'company/comp_view.html', {'position': position})
...
comp_view.html
{% extends 'company/base.html' %}
<div class="col col-md-1"></div>
<div class="col col-md-5 card-section">
<div class="team ">
<div class="card-title">
<span>Team</span>
</div>
<div class="row text-center">
<div class="col col-md-4">
{% for team in brand.team.all %}
<p>{{ team.first_name }} {{ team.last_name }}</p>
<img class="img-thumbnail" src="/media/{{ team.photo }}">
<p>{{ team.position }}</p>
<p>{{ team.about }} </p>
</div>
{% endfor %}
</div>
</div>
{% endblock %}
There's no such thing as a "single ManyToManyField". You have an m2m relationship, you need to iterate through it just like you do for the team members.
{% for position in team.position.all %}
{{ position.name }}
{% endfor %}

Django - How to make an upvote button?

Currently logged in users can upvote x amount of times.
The idea of fixing it is to create a new model called Vote. And it will have foreignkeys for user and product. When someone goes to upvote, you check and see:
is there vote object with this user id and product id, and if there is, you don't allow him to upvote again; and if it is not, then you can go ahead and create that, and just increase total_votes on one.
But actually, i ran into it and cant figure it out and solve.
So, there is my models.py
from django.db import models
from django.contrib.auth.models import User
class Product(models.Model):
title = models.CharField(max_length=255)
pub_date = models.DateTimeField()
body = models.TextField()
url = models.TextField()
image = models.ImageField(upload_to='images/')
icon = models.ImageField(upload_to='images/')
votes_total = models.IntegerField(default=1)
hunter = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
def summary(self):
return self.body[:100]
def pub_date_pretty(self):
return self.pub_date.strftime('%b %e %Y')
class Vote(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
voteproduct = models.ForeignKey(Product, on_delete=models.CASCADE)
And my views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from .models import Product, Vote
from django.utils import timezone
#login_required(login_url="/accounts/signup")
def upvote(request, product_id):
if request.method == 'POST':
product = get_object_or_404(Product, pk=product_id)
product.votes_total += 1
product.save()
return redirect('/products/' + str(product.id))
Updates:
class Vote(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
class Meta:
unique_together(('user', 'product'),)
views.py
if request.method == 'POST':
product = get_object_or_404(Product, pk=product_id)
try:
Vote.objects.create(user=request.user, product=product)
product.votes_total += 1
product.save()
except:
product.save()
return redirect('/products/' + str(product.id))
Also, how should i change my .html file? I really cant understand what is going on. Looking forward to hear from u.
{% for product in products.all %}
<div class="row pt-3">
<div class="col-2" onclick="window.location='{% url 'detail' product.id
%}';" style="cursor: pointer;">
<img src="{{ product.icon.url }}" class="img-fluid" />
</div>
<div class="col-7" onclick="window.location='{% url 'detail' product.id
%}';" style="cursor: pointer;">
<h1>{{ product.title }}</h1>
<p>{{ product.summary }}</p>
</div>
<div class="col-3">
<a href="javascript:{document.getElementById('{% url 'upvote'
product.id %}').submit()}"><button class="btn btn-primary btn-lg btn-
block" name="btn1" value="upvote"><span class="oi oi-caret-top">
</span> Upvote {{ product.votes_total }}</button></a>
</div>
</div>
<form id="get_redirect_url{{ product.id }}" action="{% url 'upvote'
object.id %}" method="POST">
{% csrf_token %}
<input type="hidden" />
</form>
well if i were you i would do it like that :
#step 1 change votes_total from integerfield to manytomany field
##models
class Product(models.Model):
#other fields goes here
votes_total = models.ManyToManyField(User, related_name="votes" ,)
#step 2 ; go to your views.py and copy paste the following :
from django.views.generic import RedirectView
class ProductVoteToggle(RedirectView):
def get_redirect_url(self, *args ,**kwargs):
obj = get_object_or_404(Product, pk=self.kwargs['pk'])
url_ = obj.get_absolute_url()
user = self.request.user
if user.is_authenticated():
if user in obj.votes_total.all():
# you could remove the user if double upvote or display a message or what ever you want here
obj.votes_total.remove(user)
else:
obj.votes_total.add(user)
return url_
#step 3 : go to urls.py and paste add the following :
urlpatterns = [
#other urls here
path('vote/<int:pk>',ProductVoteToggle.as_view() , name="upvote"),
]
#in your template remove that form and paste the following code :
<a href="{% url 'upvote' product.id %}>Click to vote<a/>
when you are done it should work if it didn't past the error here and i'll let you know what you are doing wrong
Your code doesn't use Vote at all. In upvote(), first try to create a Vote for the user and product:
try:
Vote.objects.create(user=request.user, product=product)
# consider using the name product instead of voteproduct
If it succeeds, increment the counter. If it fails, notify the user that they have voted already.
Obviously, you need a unique constraint in Vote:
class Meta:
unique_together = ('user', 'product')

Retrieve ImageField on Many-To-Many relationship

I have two apps related in a Many-To-Many relationship, Recipes and Tags, and I'm having trouble at retrieving a query of Tags having image != null and the Recipes that are currently PUBLISHED.
Recipe app: recipes/models.py
from django.db import models
from django.contrib.auth.models import User
from tags.models import Tag
DRAFT = 'D'
PUBLISHED = 'P'
RECIPE_STATES = (
(DRAFT, 'Draft'),
(PUBLISHED, 'Published')
)
class Recipe(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100, unique=True)
date_created = models.DateField(auto_now_add=True)
date_modified = models.DateField(auto_now=True)
state = models.CharField(max_length=1, choices=RECIPE_STATES)
ingredients = models.TextField(blank=True)
introduction = models.TextField(blank=True)
preparation = models.TextField(blank=True)
tip = models.TextField(blank=True)
rating = models.IntegerField(blank=True)
diners = models.IntegerField(blank=True)
tags = models.ManyToManyField(Tag, blank=True)
def __str__(self):
return self.title
And the Tag app: tags/models.py
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=50, unique=True)
image = models.ImageField(blank=True, null=True, upload_to='categories')
def __str__(self):
return self.name
recipes/views.py:
class HomeView(View):
def get(self, request):
queryset = Recipe.objects.filter(state=PUBLISHED)
last_recipes = queryset.order_by('-date_created')
top_recipes = queryset.order_by('-rating')
categories = Tag.objects.filter(image__isnull=False, recipe__state=PUBLISHED)
context = {
'last_recipes': last_recipes[:4],
'top_recipes': top_recipes[:4],
'categories': categories
}
return render(request, 'recipes/home.html', context)
When I try to retrieve that query from the views.py in home.html:
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
{% for category in categories %}
<a href="{% url 'category_recipes' category.name %}">
<div class="col-xs-6 col-sm-4 col-md-3 text-center">
<h3>{{ category.name }}</h3>
<img src="{{ category.image.url }}" alt="{{ category.name }}" height="100">
</div>
</a>
{% endfor %}
</div>
</div>
I'm getting this error:
ValueError at /
The 'image' attribute has no file associated with it.
I also have the tags populated with data:
Check, that Tag with id=20 not have '' (empty string) as value. You exclude only null values, but empty string is not checked.
I finally get it working using:
categories = Tag.objects.filter(image__isnull=False, recipe__state=PUBLISHED).distinct()
Now, categories in home.html is provided with data, and I'm not having trouble using category.image.url.