Updating a Django Model from DetailView - python

I have a Django model that is receiving most of it's variable values from a form created by User 1 using CreateView. User 1 creates an object and selects most field values.
Once the object is created it is posted to a wall, another user (User 2) can access the object and add information for the final unfilled field. My question is, how do I allow for this functionality in the DetailView html form? In the code below, "basketball.salary2" is the previously empty field User 2 will be inputting and posting in the DetailView. All other values are already filled in and displaying in the HTML.
basketball_detail.html:
{% extends "base.html" %}
{% block title %}By: {{ basketball.creator }}{% endblock %}
{% block content %}
<h2>{{ basketball.creator }} has placed an opinion:</h2>
<p>{{ basketball.creator }} says that {{ basketball.player }} deserves
{{ basketball.salary1 }}
<p> Do you agree with {{ basketball.creator }}? </p>
<p>I believe {{ basketball.player }} deserves {{ basketball.salary2 }} <p>
{% endblock content %}
views.py:
from django.shortcuts import render
from django.views.generic import ListView, CreateView, DetailView
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Basketball
class BasketballListView(LoginRequiredMixin, ListView):
model = Basketball
class BasketballDetailView(DetailView):
model = Basketball
class BasketballCreateView(LoginRequiredMixin, CreateView):
model = Basketball
fields = [
'player',
'salary1',
'salary2',
]
def form_valid(self, form):
form.instance.creator =self.request.user
return super().form_valid(form)
models.py:
from django.db import models
from django.urls import reverse
from django.conf import settings
from django.utils.text import slugify
from autoslug import AutoSlugField
from model_utils.models import TimeStampedModel
from nba_api.stats.static import players
PLAYER_CHOICES = [(i['full_name'], i['full_name']) for i in players.get_active_players()]
class Basketball(TimeStampedModel):
player = models.CharField(max_length = 50, choices = PLAYER_CHOICES, default = None)
slug = AutoSlugField("Basketball Player", unique = True, populate_from ="player")
salary1 = models.DecimalField(decimal_places = 2, max_digits = 15)
salary2 = models.DecimalField(decimal_places = 2, max_digits = 15)
creator = models.ForeignKey(settings.AUTH_USER_MODEL,
null = True,
on_delete = models.SET_NULL
)
def get_absolute_url(self):
return reverse(
'basketball:detail', kwargs={'slug': self.slug}
)

I think for this case UpdateView will work instead of DetailView.
class BasketballUpdateView(UpdateView):
model = Basketball

Related

Django html display from model

I need on my html page to display data from Profesor and Ucenik model: ime, prezime, jmbg.
{{profesor.ime}}
{{profesor.prezime}}
{{ucenik.ime}}
{{ucenik.prezime}}
{{ucenik.jmbg}}
my profile page id dynamic, need to display profesor data or if ucenik to display ucenik data
what i need to add on my views.py
models.py
class Profesor(models.Model):
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
ime = models.CharField(max_length=200, null=True)
prezime = models.CharField(max_length=200, null=True)
class Ucenik(models.Model):
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
ime = models.CharField(max_length=200, null=True)
prezime = models.CharField(max_length=200, null=True)
jmbg = models.IntegerField(null=True)
urls.py
path('profesor/', views.profesor, name='profesor'),
path('ucenik/', views.ucenik, name='ucenik'),
path('posetioc/', views.posetioc, name='posetioc'),
path('profil/<str:pk>/', views.profil, name='profil'), ]
views.py
def profesor(request):
return render(request, 'pocetna_profesor.html')
def ucenik(request):
return render(request, 'pocetna_ucenik.html')
def profil(request, pk):
return render(request, 'profil.html')
HTML:
{% extends 'base.html' %}
<title>profesor</title>
{% block content %}
<body>
{% include 'navbar.html' %}
<h1>Ime:</h1>
{{profesor.ime}}
</body>
{% endblock %}
You need to add a Professor and Ucenik instance to your view context.
context = {
'professor': Professor.objects.get(),
'ucenik': Ucenik.objects.get()
}
return render(request, context, 'url.html')
You can make your profile view dynamic by introducing an extra parameter which defines your role (i.e, Professor/Ucenik)
/profil/profesor/2/ for profesor
/profil/ucenik/1 for ucenik
from django.urls import path
urlpatterns=[
path('profil/<str:role>/<int:pk>/', views.profil, name='profil'),
]
# views.py
from .models import Profesor,Ucenik # import your model
def profil(request,role,pk):
context = {}
context['role'] = type
if type=="profesor":
context['person'] = Profesor.objects.get(id=pk)
else:
context['person'] = Ucenik.objects.get(id=pk)
return render(request, 'profil.html',context)
<!-- profil.html -->
{% extends 'base.html' %}
<title>{{role}}</title>
{% block content %}
<body>
{% include 'navbar.html' %}
<h1>Ime:</h1>
{{person.ime}}
</body>
{% endblock %}
Different Approach:
Assuming your User Model is having an id or any unique field.
You could use that id to be your profil id (i.e, url's <int:pk>).
so instead of profil/profesor/3, you can use profil/3 which must be definitely one of two categories(assuming profesor and ucenik are mutually exclusive).
So in order to do that import User model into views along with other models.
views.py
from django.shortcuts import render
from ..models import User # give correct path to user model
from .models import Profesor,Ucenik
def profil(request,pk):
context={}
person = User.objects.get(id=pk)
try :
person.profesor
# print(dir(person))
except Profesor.DoesNotExist:
context['person'] = Ucenik.objects.get(id=person.ucenik.id)
else:
context['person'] = Profesor.objects.get(id=person.profesor.id)
return render(request,"profil.html",context)
urls.py
from django.urls import path
from .views import profil
urlpatterns = [
path('profil/<int:pk>/',profil) # I have used int
]
I used person,neutral variable name instead of profesor or ucenik.
You can name it anything even profil
profil.html
{{person.id}}
{{person.ime}}
{{person.prezime}}
{% if role == "ucenik" %}
{{person.jmbg}}
{% else %}
<!-- profesor does not have jmbg -->
{% endif %}

Search field in Django is not redirecting to detail view

I am adding a search field in my blog so people can put the name of the blog they want to read and a list of items come up and after clicking on any of the list items, it will redirect to the detail view. However, in my case,If I put anything in search, it is not redirecting to a detail view but going to http://127.0.0.1:8000/home/search/2 instead of http://127.0.0.1:8000/home/list/2/.
I have posted my models, views, URLs and template files below.
Is there any reverse method I need to use here to redirect and what changes I need in my template file?
models.py
from django.db import models
class Category(models.Model):
cat_name = models.CharField(max_length = 256, blank = True)
def __str__(self):
return self.cat_name
class Blog(models.Model):
name = models.CharField(max_length = 256, blank = True)
pub_date = models.DateTimeField('date published')
text = models.TextField(blank = True)
category = models.ForeignKey(Category, on_delete=models.CASCADE,
related_name='categories', verbose_name = 'blog_categories')
def __str__(self):
return self.name
views.py
from django.shortcuts import render
from homepage.models import Blog
from django.views.generic import TemplateView, ListView, DetailView
from homepage import models
from django.db.models import Q
class Home(TemplateView):
template_name = 'homepage/index.html'
class BlogListView(ListView):
context_object_name = 'blogs'
model = models.Blog
template_name = 'homepage/blog_list.html'
class BlogDetailView(DetailView):
context_object_name = 'blogs_detail'
model = models.Blog
template_name = 'homepage/blog_detail.html'
def get_queryset(self):
query = self.request.GET.get('q')
return Blog.objects.filter(
Q(name__icontains = query) | Q(name__icontains = query) )
class SearchResultsListView(ListView):
model = Blog
context_object_name = 'blog_list'
template_name = 'homepage/search_result_list.html'
def get_queryset(self):
query = self.request.GET.get('q')
return Blog.objects.filter(
Q(name__icontains = query) | Q(name__icontains = query) )
urls.py
from django.urls import path
from homepage import views
from homepage.views import SearchResultsListView
app_name = 'homepage'
urlpatterns = [
path('', views.Home.as_view(), name = 'index'),
path('list/', views.BlogListView.as_view(), name = 'blog-list'),
path('list/<int:pk>/', views.BlogDetailView.as_view(), name = 'blog-list'),
path('search/', SearchResultsListView.as_view(), name = 'search_result'),
]
index.html
<div class="grid-item-1">
<h1>G</h1>
<input type="button" name="" value="Back to Home" placeholder="">
<form action="{% url 'home:search_result' %}" method = 'get'>
<input type="text" name="q" placeholder="search">
</form>
</div>
search_result_list.html
{% for blog in blog_list %}
<ul>
<li>
{{blog.name}}
{{blog.address}}
here
</li>
</ul>
{% endfor %}
the URL redirects to http://127.0.0.1:8000/home/search/2 and its a 404 page.
how can I redirect it to the detail view page http://127.0.0.1:8000/home/list/1/ and see the detail of the list pulled by search result.
The reason this happens is because {{ blog.id }} just contains a number, for example 2. It will be appended to the URL. You can fix this by prepending the URL with a slash (/) and write list with:
{{blog.name}}
{{blog.address}}
here
But it is likely better to make use of the {% url … %} template tag [Django-doc]:
{{blog.name}}
{{blog.address}}
here
In your BlogDetailView, there is no q parameter, so you can remove the get_queryset:
class BlogDetailView(DetailView):
context_object_name = 'blogs_detail'
model = models.Blog
template_name = 'homepage/blog_detail.html'
# no get_queryset
Furthermore perhaps you should consider renaming the DetailView from blog-list, to blog-detail, or something similar.

Django DateTimeField not showing up properly in browser

I want my django DateTimeField to be inputted the same way I input the values from the admin page, where the dates are selected from a calender.
for reference this is how my models.py look like:
from django.db import models
# Create your models here.
class TheDate(models.Model):
"""A topic the user is learning about"""
theDate = models.DateTimeField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
"""returns a string representation of the model"""
return str(self.theDate)
forms.py
class NewDate(forms.ModelForm):
class Meta:
model = TheDate
fields = ['theDate']
labels = {'theDate': ''}
the html page where i have set to create a new plan- new_date.html:
{% extends "meal_plans/base.html" %}
{% block content %}
<p>Add new Date:</p>
<form action="{% url 'meal_plans:new_date' %}">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Add New Date</button>
</form>
{% endblock content %}
what can i do to the data be inputted in that way
i hope the code here is enough and relevant.
Hello I had similar problem and I found something like this
class DateInput(forms.DateInput):
input_type = 'date'
And then in your modelform
class NewDate(forms.ModelForm):
class Meta:
model = TheDate
widgets = {
'theDate': DateInput()
}
fields = ['theDate']
Put in your forms.py something like this:
class NewDate(forms.ModelForm):
theDate = forms.DateTimeField (
widget=forms.DateTimeInput (
attrs={
'type': 'datetime-local',
}
)
)
class Meta:
model = TheDate
fields = ['theDate']
labels = {'theDate': ''}
This worked here!

How to render information from a ForeignKey field through DetailView class?

I have two models (Taxonomia and Distribucion) which are the following:
# models.py file
class Taxonomia(models.Model):
id_cactacea = models.AutoField(primary_key=True)
subfamilia = models.CharField(max_length=200)
class Distribucion(models.Model):
id_distribucion = models.AutoField(primary_key=True)
localidad = models.TextField(null=True, blank=True)
taxonomia = models.ForeignKey(Taxonomia, on_delete=models.CASCADE, default=1)
As you can see in Distribucion there is a one to many relationship with the Taxomia table.
Implement the two models in the "admin.py" file so that you can edit the Distribucion table from Taxonomia
class DistribucionInline(admin.TabularInline):
model = Distribucion
extra = 0
class TaxonomiaAdmin(admin.ModelAdmin):
actions = None # desactivando accion de 'eliminar'
list_per_page = 20
search_fields = ('genero',)
radio_fields = {"estado_conservacion": admin.HORIZONTAL}
inlines = [DistribucionInline]
admin.site.register(Taxonomia, TaxonomiaAdmin)
In turn, the file "view.py" renders the Taxonomia table as follows:
from repositorio.models import Taxonomia, Distribucion
class CactaceaDetail(DetailView):
model = Taxonomia
template_name = 'repositorio/cactacea_detail.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['distribuciones'] = Distribucion.objects.all()
return context
I tried to access to context ['distribuciones'] information from the template as follows without getting any results:
{% for obj in object.distribuciones %}
{{ obj.localidad }}
{% endfor %}
OBS: For each Taxonomia element there will be four elements from the Distribucion table, so I need to use a FOR loop
Is the way I add the information from the Taxonomia table in the "CactaceaDetail" view correct?
Is the way I read the information in the template correct?
How could I visualize all the information that "CactaceaDetail" sends to the template using the DJANGO shell so that I can debug better in the future?
Thank you.
Try removing the "object" from your for loop in the template:
{% for obj in distribuciones %}
{{ obj.localidad }}
{% endfor %}
The reason is because you are passing distribuciones in the regular context, not as part of the class object so you can't reference it with object.distribuciones.

Trouble with Django ModelChoiceField

Hi bit of a beginner question about using django's modelchoicefield in a form I'm building.
I just need get django to display a drop down list of ingredients in a form. I've gotten to the point where the page renders but the form does not, I was getting errors before so I am kind of perplexed at the moment. I was hoping for some guidance.
Using python 2.7.6 and django 1.6.2. If I left anything out let me know.
Thanks!
Code is below:
views:
args = {}
#add csrf sercurity
args.update(csrf(request))
args['form'] = form
return render_to_response('newMeal.html', args)
form:
from django import forms
from models import meals, ingredients, recipe
class mealForm(forms.ModelForm):
breakfast = forms.ModelChoiceField(queryset=recipe.objects.all())
# Lunch = forms.ModelChoiceField(queryset=recipe.objects.all())
# Dinner = forms.ModelChoiceField(queryset=recipe.objects.all())
class Meta:
model = meals
fields = ('Breakfast','Lunch','Dinner','servingDate')
class recipeForm(forms.ModelForm):
class Meta:
model = recipe
fields = ('Name', 'Directions')
template:
{% extends "base.html" %}
{% block content %}
<p>New Meals go here!</p>
<form action="/meals/newmeal/" method="post">{% csrf_token %}
<table class="selection">
{{form.as_table}}
<tr><td colspan="2"><input type="submit" name="submit" value="Add Meal"></td></tr>
</table>
</form>
{% endblock %}
Model;
from django.db import models
import datetime
Create your models here.
class recipe(models.Model):
Name = models.CharField(max_length=200)
Directions = models.TextField()
pub_date = models.DateTimeField(auto_now_add = True)
def __unicode__(self):
return (self.id, self.Name)
class ingredients(models.Model):
Name = models.CharField(max_length=200)
Quantity = models.IntegerField(default=0)
Units = models.CharField(max_length=10)
Recipe = models.ForeignKey(recipe)
def __unicode__(self):
return self.Name
class meals(models.Model):
Breakfast = models.CharField(max_length=200)
Lunch = models.CharField(max_length=200)
Dinner = models.CharField(max_length=200)
servingDate = models.DateTimeField('date published')
did you import the mealForm:
some thing like :from app.forms import mealForm
form is a function. so try:
args['form'] = mealForm()
Note: don't use render_to_response. it is old use render instead(so don't even need csrf)::
from django.shortcuts import render
def...(request):
....
return render(request,'newMeal.html', {'form': mealForm()})

Categories